[Feature]Upload Modem source code

Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/middleware/hif/interface/cdcecm_data_path_trace_utmd.json b/mcu/middleware/hif/interface/cdcecm_data_path_trace_utmd.json
new file mode 100644
index 0000000..2348404
--- /dev/null
+++ b/mcu/middleware/hif/interface/cdcecm_data_path_trace_utmd.json
@@ -0,0 +1,106 @@
+{
+  "legacyParameters": {
+    "codeSection": "TCMFORCE", 
+    "l2BufferSetting": "L2_BUFFER_HIF", 
+    "l2MaxArg": 7, 
+    "modemType": "Generic"
+  }, 
+  "module": "CDCECM_L2", 
+  "stringTranslationDefs": [], 
+  "startGen": "Legacy",
+  "endGen": "Legacy",
+  "traceClassDefs": [
+    {
+      "ECM_L": {
+        "debugLevel": "Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "ECM_M": {
+        "debugLevel": "Medium", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "ECM_H": {
+        "debugLevel": "High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "ECM_UH": {
+        "debugLevel": "Ultra-High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "CDCECM_BUF_DOWNLINK": {
+        "format": "[ECM] cdcecm_buf_downlink(): queue_no(%d), payload(%xl), payload_len(%d)", 
+        "traceClass": "ECM_M"
+      }
+    }, 
+    {
+      "CDCECM_BUF_DL_MSG_INFO": {
+        "format": "[ECM] cdcecm_buf_downlink(): td_drb_idx(%d), payload_drb_idx(%d), payload_prb(%xl), payload_len(%d)", 
+        "traceClass": "ECM_M"
+      }
+    }, 
+    {
+      "CDCECM_RB_DOWNLINK": {
+        "format": "[ECM] cdcecm_rb_downlink(): queue_no(%d), did(%xl), pkt_num(%d), seg_num(%d), state(%d), is_usb_suspend(%d)", 
+        "traceClass": "ECM_M"
+      }
+    }, 
+    {
+      "CDCECM_RB_DL_ENUMERATION": {
+        "format": "[ECM] cdcecm_rb_downlink(): dl enumeration: i(%d), did(%xl), curr_sit(%xl), hif_type(%d), handled_seg_cnt(%d), seg_num(%d), total_len(%d)", 
+        "traceClass": "ECM_M"
+      }
+    }, 
+    {
+      "CDCECM_RB_DL_PACKET": {
+        "format": "[ECM] cdcecm_rb_downlink(): dl packet: i(%d), data_addr(%xl), data_len(%ul)", 
+        "traceClass": "ECM_M"
+      }
+    }, 
+    {
+      "CDCECM_RB_PWR_FILTER_NUM": {
+        "format": "[ECM] cdcecm_rb_downlink(): power management pattern filter check: filter_idx(%d)", 
+        "traceClass": "ECM_M"
+      }
+    }, 
+    {
+      "CDCECM_RB_PWR_FILTER_DROP": {
+        "format": "[ECM] cdcecm_rb_downlink(): power management pattern filter drop: xmit_frames(%d)", 
+        "traceClass": "ECM_M"
+      }
+    }, 
+    {
+      "CDCECM_RB_BULK_OUT_COMPLT": {
+        "format": "[ECM] cdcecm_rb_bulk_out_complete(): ul enumeration: curr_idx(%d), ul_meta(%xl), qtype(%d), net_type(%d), next_idx(%d), end_of_list(%d)", 
+        "traceClass": "ECM_M"
+      }
+    }
+  ], 
+  "traceFamily": "L2", 
+  "userModule": "MOD_ECM"
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/interface/dhcp4c_common.h b/mcu/middleware/hif/interface/dhcp4c_common.h
new file mode 100644
index 0000000..d7d132c
--- /dev/null
+++ b/mcu/middleware/hif/interface/dhcp4c_common.h
@@ -0,0 +1,58 @@
+/*!
+ *  @file dhcp4c_common.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides interface of dhcp4c ( DHCPv4 Client )
+ */
+
+#ifndef _DHCP4C_COMMON_H
+#define _DHCP4C_COMMON_H
+
+
+/*!
+ *  @brief  dhcp4c init function
+ */
+void dhcp4c_init(void);
+
+
+/*!
+ *  @brief  dhcp4c main function
+ */
+void dhcp4c_main(ilm_struct* ilm);
+
+
+#endif  // _DHCP4C_COMMON_H
+
diff --git a/mcu/middleware/hif/interface/dpfm_data_path_trace_utmd.json b/mcu/middleware/hif/interface/dpfm_data_path_trace_utmd.json
new file mode 100644
index 0000000..9c61dfc
--- /dev/null
+++ b/mcu/middleware/hif/interface/dpfm_data_path_trace_utmd.json
@@ -0,0 +1,124 @@
+{
+  "legacyParameters": {
+    "codeSection": "TCMFORCE", 
+    "l2BufferSetting": "L2_BUFFER_HIF", 
+    "l2MaxArg": 7, 
+    "modemType": "Generic"
+  }, 
+  "module": "DPFM_L2", 
+  "stringTranslationDefs": [], 
+  "startGen": "Legacy",
+  "endGen": "-",
+  "traceClassDefs": [
+    {
+      "DPFM_L": {
+        "debugLevel": "Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "DPFM_M": {
+        "debugLevel": "Medium", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "DPFM_H": {
+        "debugLevel": "High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "DPFM_UH": {
+        "debugLevel": "Ultra-High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "DPFM_START_FILTER_EXPIRED_TIMER": {
+        "format": "[DPFM] dpfm_start_filter_expired_timer(): Start filter expired timer, current_tick(%xl), elapse_time(%xl)", 
+        "traceClass": "DPFM_L"
+      }
+    }, 
+    {
+      "DPFM_CHECK_FILTER_VALID": {
+        "format": "[DPFM] dpfm_check_filter_valid_period(): Timer expired! Remaining filter number[%xl], expired filter number[%xl], timeout filter number[%xl]", 
+        "traceClass": "DPFM_H"
+      }
+    }, 
+    {
+      "DPFM_START_TRACK_TABLE_EXPIRED_TIMER": {
+        "format": "[DPFM] dpfm_start_track_table_expired_timer(): Start track table expired timer, current_tick(%xl), elapse_time(%xl)", 
+        "traceClass": "DPFM_L"
+      }
+    }, 
+    {
+      "DPFM_SET_GLOBAL_ALERT": {
+        "format": "[DPFM] dpfm_set_global_alert_value(): Set global alert value[%xl %xl]", 
+        "traceClass": "DPFM_UH"
+      }
+    }, 
+    {
+      "DPFM_SET_IQUOTA_LIMIT": {
+        "format": "[DPFM] dpfm_set_iquota_value(): Set limit iquota dpfm_netif_id[%d], value[%xl %xl]", 
+        "traceClass": "DPFM_UH"
+      }
+    }, 
+    {
+      "DPFM_DEL_IQUOTA_LIMIT": {
+        "format": "[DPFM] dpfm_del_iquota_value(): Del limit iquota dpfm_netif_id[%d]", 
+        "traceClass": "DPFM_UH"
+      }
+    }, 
+    {
+      "DPFM_ALERT_GLOBAL_ALERT": {
+        "format": "[DPFM] dpfm_update_global_alert_data_usage(): Send global alert to AP, remaining value[%xl %xl]", 
+        "traceClass": "DPFM_M"
+      }
+    }, 
+    {
+      "DPFM_ALERT_IQUOTA_LIMIT": {
+        "format": "[DPFM] dpfm_update_iquota_data_usage_of_netif(): dpfm_netif_id[%d] reaches iquota limit", 
+        "traceClass": "DPFM_UH"
+      }
+    }, 
+    {
+      "DPFM_DO_DL_FILTER_INVALID_MATCH_FILTER": {
+        "format": "[DPFM] dpfm_check_route_by_dl_filter(): matched_filter is NULL!! No need to do filter", 
+        "traceClass": "DPFM_H"
+      }
+    }, 
+    {
+      "DPFM_CHECK_ROUTE_RESULT_META": {
+        "format": "[DPFM] dpfm_check_route(): Check route with meta, result[%d], uplink[%d], match_result[%d], match_index[%d], filter_id[%d], out_netif_id[%xl]", 
+        "traceClass": "DPFM_H"
+      }
+    }, 
+    {
+      "DPFM_CHECK_ROUTE_RESULT_DID": {
+        "format": "[DPFM] dpfm_check_route(): Check route with DID, result[%d], uplink[%d], filter_id[%d], out_netif_id[%xl]", 
+        "traceClass": "DPFM_H"
+      }
+    }
+  ], 
+  "traceFamily": "L2", 
+  "userModule": "MOD_DPFM"
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/interface/ethercore_common.h b/mcu/middleware/hif/interface/ethercore_common.h
new file mode 100644
index 0000000..572c766
--- /dev/null
+++ b/mcu/middleware/hif/interface/ethercore_common.h
@@ -0,0 +1,259 @@
+/*!
+ *  @file ethercore_common.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides common definitions of ethercore
+ */
+
+#ifndef _ETHERCORE_COMMON_H
+#define _ETHERCORE_COMMON_H
+
+#include "kal_public_api.h"
+#include "ethercore_struct.h"
+#include "lhif_if.h"
+
+#if !defined(__MTK_TARGET__) && defined(_MSC_VER) && (_MSC_VER >= 1500)
+#pragma warning( disable : 4214 )
+#endif
+
+#define ETHC_ETHER_TYPE_IP          0x0800
+#define ETHC_ETHER_TYPE_ARP         0x0806
+#define ETHC_ETHER_TYPE_VLAN        0x8100
+#define ETHC_ETHER_TYPE_IPV6        0x86dd
+
+#define ETHC_SWAP16(_x)             ((_x & 0xff00) >> 8 | (_x & 0x00ff) << 8)
+#define ETHC_SWAP32(_x)             ((_x & 0xff000000) >> 24 |  \
+                                     (_x & 0x00ff0000) >> 8  |  \
+                                     (_x & 0x0000ff00) << 8  |  \
+                                     (_x & 0x000000ff) << 24)
+
+#define ETHC_HTONS(_x)              ETHC_SWAP16(_x)
+#define ETHC_HTONL(_x)              ETHC_SWAP32(_x)
+#define ETHC_NTOHS(_x)              ETHC_SWAP16(_x)
+#define ETHC_NTOHL(_x)              ETHC_SWAP32(_x)
+
+#define ETHC_ETHER_ADDR_SIZE        6
+
+typedef kal_uint8 ethc_mac_addr_t[ETHC_ETHER_ADDR_SIZE];
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ethc_ether_header {
+    ethc_mac_addr_t dst_mac;
+    ethc_mac_addr_t src_mac;
+    kal_uint16      ether_type;
+} ethc_ether_header_t;
+PRAGMA_END_PACK_STRUCT
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ethc_vlan_tag {
+    kal_uint16      tpid;               /* Tag Protocol Identifier */
+    struct ethc_tci {   /* Tag Control Identifier */
+        kal_uint16  pcp:3;              /* Priority Code Point */
+        kal_uint16  cfi:1;              /* Canonical Format Indicator */
+        kal_uint16  vid:12;             /* VLAN Identifier */
+    } tci;
+} ethc_vlan_tag_t;
+PRAGMA_END_PACK_STRUCT
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ethc_vlan_ether_header {
+    ethc_mac_addr_t dst_mac;
+    ethc_mac_addr_t src_mac;
+    ethc_vlan_tag_t vlan_tag;
+    kal_uint16      ether_type;
+} ethc_vlan_ether_header_t;
+PRAGMA_END_PACK_STRUCT
+
+
+#define ETHC_ARP_HRD_ETHERNET           1
+#define ETHC_ARP_HRD_IEEE802            6
+#define ETHC_ARP_HRD_ARCNET             7
+#define ETHC_ARP_HRD_FRAMERELAY         15
+#define ETHC_ARP_HRD_ATM                16
+#define ETHC_ARP_HRD_HDLC               17
+#define ETHC_ARP_HRD_FIBRE_CHANNEL      18
+#define ETHC_ARP_HRD_SERIAL_LINE        20
+
+#define ETHC_ARP_PRO_IPV4               0x0800
+#define ETHC_ARP_HLN_IEEE802_MAC        6
+#define ETHC_ARP_PLN_IPV4               4
+
+#define ETHC_ARP_OP_ARP_REQUEST         1
+#define ETHC_ARP_OP_ARP_REPLY           2
+#define ETHC_ARP_OP_ARP_RARP_REQUEST    3
+#define ETHC_ARP_OP_ARP_RARP_REPLY      4
+#define ETHC_ARP_OP_ARP_DRARP_REQUEST   5
+#define ETHC_ARP_OP_ARP_DRARP_REPLY     6
+#define ETHC_ARP_OP_ARP_DRARP_ERROR     7
+#define ETHC_ARP_OP_ARP_INARP_REQUEST   8
+#define ETHC_ARP_OP_ARP_INARP_REPLY     9
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ethc_arp_packet {
+    kal_uint16      arp_hrd;        /* hardware type */
+    kal_uint16      arp_pro;        /* protocol type */
+    kal_uint8       arp_hln;        /* hardware address length */
+    kal_uint8       arp_pln;        /* protocol address length */
+    kal_uint16      arp_op;         /* opcode */
+    ethc_mac_addr_t arp_sha;        /* sender hardware address */
+    kal_uint8       arp_spa[4];     /* sender protocol address */
+    ethc_mac_addr_t arp_tha;        /* target hardware address */
+    kal_uint8       arp_tpa[4];     /* target protocol address */
+} ethc_arp_packet_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief ethc_device_instance_t describe register information of a
+ *         generic ether device
+ */
+typedef struct _ethc_device_info {
+    /*!
+     *  @brief module id used to send ilm
+     */
+    module_type module_id;
+
+    /*!
+     *  @brief context to be passed in context function
+     */
+    void       *context;
+
+    /*!
+     *  @brief index the identify which network interface it is.
+     */
+    kal_uint32  netif_id;
+
+    /*!
+     *  @brief callback function to reload uplink buffers
+     *         Running Level: TASK
+     */
+    kal_bool    (*ul_reload)(void *context);
+
+    /*!
+     *  @brief callback function to submit io request to ether device
+     *         Running Level: TASK
+     */
+    void    (*tx_submit)(ethc_device_instance_t* instance, hif_io_request_t* ior);
+
+    /*!
+     *  @brief callback function to submit DID to ether device
+     *         Running Level: TASK
+     */
+    kal_bool (*rb_tx_submit)(ethc_device_instance_t *instance, void *did, kal_uint8 *ethc_drb_fh_idx, kal_uint32 *ethc_drb_fh_len);
+
+    /*!
+     *  @brief callback function to submit buffer to ether device
+     *         Running Level: TASK
+     */
+    kal_bool (*buf_tx_submit)(ethc_device_instance_t *instance, void *buf, kal_uint16 buf_len);
+
+    /*!
+     *  @used for SPD
+     */
+    kal_uint8                       tx_header_offset;//SPD use
+    kal_uint8                       tx_header_padding_align;//SPD use
+} ethc_device_info_t;
+
+
+/*!
+ *  @brief  attach new ether device to ethercore
+ *          Running Level: HISR/TASK
+ *  @param  device_info ether device information used to register
+ *  @return new instance of ether device if success, NULL if fail
+ */
+ethc_device_instance_t* ethc_device_attach(ethc_device_info_t* device_info);
+
+
+/*!
+ *  @brief  detach ether device from ethecore
+ *          Running Level: HISR/TASK
+ *  @param  instance  device instance obtained while attach 
+ */
+void ethc_device_detach(ethc_device_instance_t* instance);
+
+
+/*!
+ *  @brief  indicate received io request to ethecore
+ *          Running Level: TASK
+ *  @param  instance  device instance obtained while attach
+ *  @param  ior io request list to be indicated
+ */
+void ethc_device_rx_complete(ethc_device_instance_t* instance, hif_io_request_t* ior);
+
+
+/*!
+ *  @brief  indicate received ring-buffer data to ethecore
+ *          Running Level: TASK
+ *  @param  instance  device instance obtained while attach
+ *  @param  index  entry index
+ *  @param  queue_no  queue number of usb
+ *  @param  header_len  total header length
+ *  @param  net_type  LHIF network type
+ *  @param  pkt_cnt  total packet count
+ *  @param  byte_cnt  total byte count
+ *  @param  drop_pkt_cnt  total dropped packet count
+ *  @param  is_packet_handled  whether the packet has been handled
+ */
+void ethc_rb_rx_complete(ethc_device_instance_t* instance, kal_uint32 index, kal_uint8 queue_no, kal_uint32* header_len, LHIF_NET_TYPE* net_type, kal_uint32* pkt_cnt, kal_uint32* byte_cnt, kal_uint32* drop_pkt_cnt, kal_bool* is_packet_handled, kal_uint32* cjq_len);
+
+
+/*!
+ *  @brief  indicate the underlying device needs to reload UL buffers
+ *          Running Level: TASK
+ *  @param  instance  device instance obtained while attach
+ */
+void ethc_device_rx_need_reload(ethc_device_instance_t* instance);
+
+
+/*!
+ *  @brief  notify ethercore to handle packets if needed
+ *          Running Level: TASK
+ *  @param  instance  device instance obtained while attach
+ */
+void ethc_send_handle_packet_req(ethc_device_instance_t* instance);
+
+void ethc_get_host_mac(kal_uint32 netid_if, kal_uint8* mac_addr);
+
+extern void *ethc_vir_dev_attach(kal_uint32 id);
+extern int   ethc_vir_dev_detach(void);
+extern void *ethc_multiple_vir_dev_attach(kal_uint32 id);
+extern int ethc_multiple_vir_dev_detach(void);
+
+#endif  // _ETHERCORE_COMMON_H
+
diff --git a/mcu/middleware/hif/interface/ethercore_data_path_trace_utmd.json b/mcu/middleware/hif/interface/ethercore_data_path_trace_utmd.json
new file mode 100644
index 0000000..f299103
--- /dev/null
+++ b/mcu/middleware/hif/interface/ethercore_data_path_trace_utmd.json
@@ -0,0 +1,263 @@
+{
+  "legacyParameters": {
+    "codeSection": "TCMFORCE", 
+    "l2BufferSetting": "L2_BUFFER_HIF", 
+    "l2MaxArg": 7, 
+    "modemType": "Generic"
+  }, 
+  "module": "ETHERCORE_L2", 
+  "stringTranslationDefs": [], 
+  "startGen": "Legacy",
+  "endGen": "-",
+  "traceClassDefs": [
+    {
+      "ETHC_L": {
+        "debugLevel": "Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline", 
+          "Sensitive"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "ETHC_M": {
+        "debugLevel": "Medium", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "ETHC_H": {
+        "debugLevel": "High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "ETHC_UH": {
+        "debugLevel": "Ultra-High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "ETHC_HANDLE_ARP": {
+        "format": "[ETHERCORE] handle_arp_packet(): hrd(%d), pro(%ul), hln(%ul), pln(%ul), op(%ul)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_HANDLE_ARP_SHA_NOT_MATCH_NG": {
+        "format": "[ETHERCORE] handle_arp_packet(): eth%d, sha 0-1(%xl) 2-5(%xl) not match", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_HANDLE_ARP_THA_NOT_MATCH_NG": {
+        "format": "[ETHERCORE] handle_arp_packet(): eth%d, tha 0-1(%xl) 2-5(%xl) not match", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_HANDLE_ARP_GRATUITOUS_NG": {
+        "format": "[ETHERCORE] handle_arp_packet(): eth%d, spa(%ul %ul %ul %ul) is gratuitous", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_HANDLE_ARP_ZERO_IP_NG": {
+        "format": "[ETHERCORE] handle_arp_packet(): eth%d, spa(%ul %ul %ul %ul) is zero ip", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_HANDLE_ARP_ALLOC_NET_DL_NG": {
+        "format": "[ETHERCORE] handle_arp_packet(): failed to allocate NET_DL to handle ARP request(%xl), drop it!", 
+        "traceClass": "ETHC_UH"
+      }
+    }, 
+    {
+      "ETHC_HANDLE_ARP_DONE": {
+        "format": "[ETHERCORE] handle_arp_packet(): eth%d, result(%ul), parse_arp_req(%ul), gpd(%xl), tx_gpd(%xl)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_PROC_RX_GPD": {
+        "format": "[ETHERCORE] [%d] process rx gpd(%xl), result(%l), ether_type(%xl), qos_priority(%l)", 
+        "traceClass": "ETHC_M"
+      }
+    }, 
+    {
+      "ETHC_PROC_RX_GPD_TYPE_IP": {
+        "format": "[ETHERCORE] [%d] process rx gpd(%xl) w/ ipv4, ip_proto_type(%l)", 
+        "traceClass": "ETHC_M"
+      }
+    }, 
+    {
+      "ETHC_PROC_RX_GPD_TYPE_ARP": {
+        "format": "[ETHERCORE] [%d] process rx gpd(%xl) w/ arp", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_PROC_RX_GPD_TYPE_IPV6": {
+        "format": "[ETHERCORE] [%d] process rx gpd(%xl) w/ ipv6, next_header(%l)", 
+        "traceClass": "ETHC_M"
+      }
+    }, 
+    {
+      "ETHC_PROC_RX_GPD_TYPE_UNSUPPORTED": {
+        "format": "[ETHERCORE] [%d] process unsupported rx gpd(%xl)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_PROC_TX_TYPE_GPD_BD": {
+        "format": "[ETHERCORE] [%d] process_tx_gpd_list(): insert a header bd into tx gpd(%xl)", 
+        "traceClass": "ETHC_M"
+      }
+    }, 
+    {
+      "ETHC_PROC_TX_ALLOC_BD_NG": {
+        "format": "[ETHERCORE] [%d] process_tx_gpd_list(): fail to allocate a header bd, current_gpd(%xl), first_gpd(%xl), last_gpd(%xl)", 
+        "traceClass": "ETHC_UH"
+      }
+    }, 
+    {
+      "ETHC_RB_TX_FREE_ALL_VRB_ENUM": {
+        "format": "[ETHERCORE] ethc_rb_tx_free_all_vrb(): enumerate did_sit list, did(%xl), handled_seg_cnt(%ul), curr_sit(%xl), p_data(%xl), len(%ul)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_RB_TX_FREE_ALL_VRB_DONE": {
+        "format": "[ETHERCORE] ethc_rb_tx_free_all_vrb(): enumerate done, did(%xl), handled_seg_cnt(%ul)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_RB_TX_ENCAP_ETHER_HEADER_DONE": {
+        "format": "[ETHERCORE] ethc_rb_encap_ether_header(): ip_packet(%xl), ip_ver(%xl), ether_type_idx(%xl), vlan_enable_idx(%ul), fh_idx(%ul), fh_len(%ul)", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_RB_PROC_TX_PKT": {
+        "format": "[ETHERCORE] ethc_rb_process_tx_pkt(): process TX packet, did(%xl), seg_num(%ul)", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_RB_PROC_TX_PKT_INVALID_DID_FORMAT": {
+        "format": "[ETHERCORE] ethc_rb_process_tx_pkt(): invalid did format, curr_idx(%d), did(%xl)!", 
+        "traceClass": "ETHC_UH"
+      }
+    }, 
+    {
+      "ETHC_RB_PROC_TX_PKT_ENUM": {
+        "format": "[ETHERCORE] ethc_rb_process_tx_pkt(): enumerate did list, curr_idx(%d), sit(%xl), p_data(%xl), len(%xl), pkt_cnt(%ul), byte_cnt(%ul), is_first_gpd(%ul)", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_BUF_ENCAP_ETHER_HEADER_DONE": {
+        "format": "[ETHERCORE] ethc_buf_encap_ether_header(): encap ether header done, type(%ul), out_data(%xl), out_data_len(%ul)", 
+        "traceClass": "ETHC_M"
+      }
+    }, 
+    {
+      "ETHC_RB_IPC_TX_SUBMIT_DONE": {
+        "format": "[ETHERCORE] ethc_rb_ipc_tx_submit(): ethcore tx submit done, ret(%d), did(%xl)", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_RB_IPC_TX_SUBMIT_NOT_LINK_UP": {
+        "format": "[ETHERCORE] ethc_rb_ipc_tx_submit(): device state is not link up, did(%xl)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_RB_DECAP_ETHER_HEADER": {
+        "format": "[ETHERCORE] ethc_rb_decap_ether_header(): ether_type(%xl), eth_hdr(%xl), prb_addr(%xl), length(%ul)", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_RB_DECAP_ETHER_HEADER_INVALID_VLAN_FORMAT": {
+        "format": "[ETHERCORE] ethc_rb_decap_ether_header(): invalid vlan format, vlan_cfi(%d)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_RB_DECAP_ETHER_HEADER_2": {
+        "format": "[ETHERCORE] ethc_rb_decap_ether_header(): decap ether header_2, data_addr(%xl), data_len(%ul), remove_len(%ul)", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_RB_PROC_RX_PKT": {
+        "format": "[ETHERCORE] ethc_rb_process_rx_pkt(): result(%d), xit(%xl), ether_type(%xl), qos_priority(%ul)", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_RB_PROC_RX_PKT_TYPE_IP": {
+        "format": "[ETHERCORE] ethc_rb_process_rx_pkt(): ipv4 type, xit(%xl), ip_pro(%ul)", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_RB_PROC_RX_PKT_TYPE_ARP": {
+        "format": "[ETHERCORE] ethc_rb_process_rx_pkt(): arp type, xit(%xl)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_RB_PROC_RX_PKT_TYPE_IPV6": {
+        "format": "[ETHERCORE] ethc_rb_process_rx_pkt(): ipv6 type, xit(%xl), next_header(%ul)", 
+        "traceClass": "ETHC_L"
+      }
+    }, 
+    {
+      "ETHC_RB_PROC_RX_PKT_ALLOC_GPD_NG": {
+        "format": "[ETHERCORE] ethc_rb_rx_complete(): fail to allocate GPD, drop packet. xit(%xl), ether_type(%xl), qos_priority(%ul)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_PROC_RX_PKT_TYPE_UNSUPPORTED": {
+        "format": "[ETHERCORE] ethc_rb_process_rx_pkt(): unknown type, xit(%xl)", 
+        "traceClass": "ETHC_H"
+      }
+    }, 
+    {
+      "ETHC_RX_PKT_DROP": {
+        "format": "[ETHERCORE] ethc_rb_rx_complete(): drop packet, eth_id(%d), dev_state(%d), xit(%xl)", 
+        "traceClass": "ETHC_H"
+      }
+    },
+	{
+      "ETHC_FN_TX_SUBMIT_NONE": {
+        "format": "[ETHERCORE] ethc_rb_ipc_tx_submit(): tx_submit callback not register, dev_state(%d), tx_submit=(%xl)", 
+        "traceClass": "ETHC_H"
+      }
+    }
+  ], 
+  "traceFamily": "L2", 
+  "userModule": "MOD_ETHERCORE"
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/interface/hif_mw_cccidev_trace_utmd.json b/mcu/middleware/hif/interface/hif_mw_cccidev_trace_utmd.json
new file mode 100644
index 0000000..49d4c2c
--- /dev/null
+++ b/mcu/middleware/hif/interface/hif_mw_cccidev_trace_utmd.json
@@ -0,0 +1,204 @@
+{
+  "endGen": "-", 
+  "legacyParameters": {
+    "codeSection": "TCMFORCE", 
+    "l2BufferSetting": "L2_BUFFER_HIF", 
+    "l2MaxArg": 7, 
+    "modemType": "Generic"
+  }, 
+  "module": "HIF_MW_CCCIDEV", 
+  "startGen": "Legacy", 
+  "stringTranslationDefs": [], 
+  "traceClassDefs": [
+    {
+      "DL_UL": { 
+        "debugLevel": "Ultra-Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }, 
+    {
+      "CCMNI_UL": {
+        "debugLevel": "Ultra-Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }, 
+    {
+      "CCMNI_DL_UL": {
+        "debugLevel": "Ultra-Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }, 
+    {
+      "CCMNI_UL_UL": {
+        "debugLevel": "Ultra-Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }, 
+    {
+      "CCMNI_DUMP_UL": {
+        "debugLevel": "Ultra-Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }, 
+    {
+      "CCCITTY_DUMP_H": {
+        "debugLevel": "High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "CCMNI_DATA_DUMP_TRACE": {
+        "format": "[CCMNI DUMP] %b: %10xl %10xl %10xl %10xl", 
+        "traceClass": "CCMNI_DUMP_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_DATA_DUMP_GPD_PTR": {
+        "format": "[CCMNI DL] CCMNI%b: GDP=%xl BD1=%xl BD2=%xl DATA=%xl", 
+        "traceClass": "CCMNI_DUMP_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_DL_DATA_IPv6_PACKET_TRACE": {
+        "format": "[CCMNI DLv6] Protocol:%b GPD=%xl Checksum=%xl Src Addr=%10xl %10xl %10xl %10xl", 
+        "traceClass": "CCMNI_DL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_UL_DATA_IPv6_PACKET_TRACE": {
+        "format": "[CCMNI ULv6] Protocol:%b GPD=%xl Checksum=%xl Dst Addr=%10xl %10xl %10xl %10xl", 
+        "traceClass": "CCMNI_UL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_DL_DATA_PACKET_TRACE": {
+        "format": "[CCMNI DL] CCMNI%b: CCCIHDR=%xl SEQ=%xd IPID=%xd checksum=%xd", 
+        "traceClass": "CCMNI_DL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_DL_DATA_PACKET_NON_IPV4V6_TRACE": {
+        "format": "[CCMNI DL] CCMNI%b: CCCIHDR=%xl SEQ=%xd PAYLOAD=%xl PAYLOAD_LEN=%d", 
+        "traceClass": "CCMNI_DL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_UL_DATA_PACKET_TRACE": {
+        "format": "[CCMNI UL] CCMNI%b: GPD=%xl IPID=%xd checksum=%xd", 
+        "traceClass": "CCMNI_UL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_UL_GPD_IN_HIF": {
+        "format": "[CCMNI UL] CCMNI%b: Receive GPD=%d, Need Reload=%d, GPD in HIF=%d, Data_Q=%d, Ack_Q=%d", 
+        "traceClass": "CCMNI_UL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_UL_RELOAD_RGPD": {
+        "format": "[CCMNI UL_RELOAD] CCMNI%b: Reload RGPD Want=%d, Allocated=%d, in HIF=%d", 
+        "traceClass": "CCMNI_UL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_UL_RELOAD_RGPD_IN_HIF": {
+        "format": "[CCMNI UL_RELOAD] CCMNI%b: Nor_Q_before=%d, Nor_Q_after=%d, Nor_Q_MAX=%d, Ack_Q_before=%d, Ack_Q_after=%d, Ack_Q_MAX=%d", 
+        "traceClass": "CCMNI_UL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_MAX_RELOAD_RGPD_IN_HIF": {
+        "format": "[CCMNI MAX RGPD] Data_Q_MAX=%d Ack_Q_MAX=%d, Misc_Q_MAX=%d", 
+        "traceClass": "CCMNI_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_DEVICE_STATUS": {
+        "format": "[CCMNI STATUS] CCMNI%b: event=%b status=%b -> %b", 
+        "traceClass": "CCMNI_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCMNI_DL_DATA_FIRST_FAST_CCCI_HDR": {
+        "format": "[CCMNI DL] CCMNI%b: Rem_gpd(%d)", 
+        "traceClass": "CCMNI_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCCITTY_DATA_DUMP_TRACE": {
+        "format": "[CCCITTY DUMP] %b: %10xl %10xl %10xl %10xl", 
+        "traceClass": "CCCITTY_DUMP_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCCIDEV_PROCESS_DL_SPD_TRACE": {
+        "format": "[CCCIDEV DL SPD] pkt_num:%d current_gpd:%xl", 
+        "traceClass": "DL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCCIDEV_PROCESS_DL_SPD_SET_IGR_TRACE": {
+        "format": "[CCCIDEV DL SPD] ignore bit set (%d) in pkt:%d pie:%xl", 
+        "traceClass": "DL_UL", 
+        "traceHighlightOption": "warn"
+      }
+    }, 
+    {
+      "CCCIDEV_SPD_RELAYOUT_SET_PKTNUM_TRACE": {
+        "format": "[CCCIDEV DL SPD] Get pkt_num:%d from pi:%xl and write to spd_ext:%xl", 
+        "traceClass": "DL_UL", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "CCCIDEV_SPD_RELAYOUT_GET_EOL_BREAK_TRACE": {
+        "format": "[CCCIDEV DL SPD] BREAK!!! total pkt_num:%d current pkt_num:%d spd_ph:%xl", 
+        "traceClass": "DL_UL", 
+        "traceHighlightOption": "warn"
+      }
+    }
+  ], 
+  "traceFamily": "L2", 
+  "userModule": "MOD_CCCIDEV"
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/interface/hif_mw_data_path_ipcore_trace_utmd.json b/mcu/middleware/hif/interface/hif_mw_data_path_ipcore_trace_utmd.json
new file mode 100755
index 0000000..d46d555
--- /dev/null
+++ b/mcu/middleware/hif/interface/hif_mw_data_path_ipcore_trace_utmd.json
@@ -0,0 +1,907 @@
+{
+  "legacyParameters": {
+    "codeSection": "TCMFORCE",
+    "l2BufferSetting": "L2_BUFFER_HIF",
+    "l2MaxArg": 7,
+    "modemType": "Generic"
+  },
+  "module": "HIF_MW_IPCORE",
+  "startGen": "Legacy",
+  "endGen": "-",
+  "stringTranslationDefs": [
+    {
+      "IPC_IP_TYPE": [
+        "IPC_IP_TYPE_MIXED",
+        "IPC_IP_TYPE_IPV4",
+        "IPC_IP_TYPE_IPV6"
+      ]
+    }
+  ],
+  "traceClassDefs": [
+    {
+      "UL_UH": {
+        "debugLevel": "Ultra-High",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "CoreDesign"
+      }
+    },
+    {
+      "DL_UH": {
+        "debugLevel": "Ultra-High",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "CoreDesign"
+      }
+    },
+    {
+      "GE_UH": {
+        "debugLevel": "Ultra-High",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "DesignInfo"
+      }
+    },
+    {
+      "UL_DETAIL_H": {
+        "debugLevel": "High",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "CoreDesign"
+      }
+    },
+    {
+      "DL_DETAIL_H": {
+        "debugLevel": "High",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "CoreDesign"
+      }
+    },
+    {
+      "GE_DETAIL_H": {
+        "debugLevel": "High",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "CoreDesign"
+      }
+    },
+    {
+      "DPFM_UH": {
+        "debugLevel": "Ultra-High",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "CoreDesign"
+      }
+    },
+    {
+      "DATA_PATH_SENSATIVE_L": {
+        "debugLevel": "Low",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "CoreDesign"
+      }
+    },
+    {
+      "DATA_PATH_M": {
+        "debugLevel": "Medium",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "CoreDesign"
+      }
+    }     
+  ],
+  "traceDefs": [
+    {
+      "IPC_UL_UPLINK_CALLBACK": {
+        "format": "[IPCORE] ipc_uplink() : [%ub] Callback with UL IP IOR[%xl] for netif[%xl], netif's features[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_META_UPLINK_CALLBACK": {
+        "format": "[IPCORE] ipc_meta_uplink() : Callback with UL IP Meta start_idx[%xl], end_idx[%xl], q_type[%ub]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_META_PN_MISS_MATCH": {
+        "format": "[IPCORE] ipc_check_and_fill_session_info() : UL IP Meta PDN info are different(mask with proto_idx). netif_id[%xl], ip_type[%xb], PDN_from_IPCORE[%xl], PDN_from_meta[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_META_DPFM_CMD": {
+        "format": "[IPCORE] ipc_on_process_UL_UHpc_result() : UL DPFM CMD result [%xl], meta_idx[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_DEQUEUE_UPLINK_PRIORITY_QUEUE": {
+        "format": "[IPCORE] ipc_on_process_ul_ior_list() : Pending IOR count[%d], Throttling state: blocking-latency-concern[%ub]/ims-emergency[%ub]. High priority IOR list head[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_DEQUEUE_UPLINK_QUEUE": {
+        "format": "[IPCORE] ipc_on_process_ul_queue() : UL data throttled! Pending q_type[%ub], q_priority[%ub], cnt[%ul].",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_PROCESS_UPLINK_QUEUE": {
+        "format": "[IPCORE] ipc_on_process_ul_queue()",
+        "traceClass": "DATA_PATH_M",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_UPLINK_QUEUE_PENDING": {
+        "format": "[IPCORE] ipc_on_process_ul_queue() : Queue: type[%ub], priority[%ub] and Pending_cnt[%l]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_IOR_CHANGE_GPD_TYPE": {
+        "format": "[IPCORE] ipc_ior_change_gpd_type() : Change to GPD type[%d], with origin IOR[%xl] and new IOR[%xl]",
+        "traceClass": "UL_DETAIL_H",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_ON_PROCESS_NORMAL_IOR": {
+        "format": "[IPCORE] ipc_on_process_ul_ior_list() : [%ub] Handle IOR[%xl] belongs to netif[%xl]",
+        "traceClass": "UL_DETAIL_H",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_FORWARD_META": {
+        "format": "[IPCORE] ipc_on_process_ul_meta_table() : Forward UL Meta: start_idx[%xl], end_idx[%xl], q_type[%ub]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_THROTTLE_IMS_EMERGEMCY_IND": {
+        "format": "[IPCORE] ipc_ims_emergency_call_ind_handler(): VDM indication to change ims_block_flag from [%ub] to [%ub]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_TR_TIMER_UL_THROTTLE_TIMEOUT": {
+        "format": "[IPCORE] ipc_ul_throttle_timeout(): UL throttle timer timeout, current_tick(%l), current_state(%ub), enable(%ub), active(%ub), suspend(%ub)",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_TR_START_UL_THROTTLE_TIMER": {
+        "format": "[IPCORE] ipc_start_ul_throttle_timer(): Start UL throttle timer, current_tick(%l), elapse_time(%l)",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_RELOAD_UPLINK": {
+        "format": "[IPCORE] ipc_reload_uplink() : [%ub] Reload uplink for netif[%xl], netif_id[%xl], callback[%xl]",
+        "traceClass": "UL_DETAIL_H",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_RELOAD_UPLINK_RESULT": {
+        "format": "[IPCORE] ipc_reload_uplink() : [%ub] Reload uplink result for for netif[%xl], netif_id[%xl] : %ub",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_RELOAD_RETRY": {
+        "format": "[IPCORE] ipc_set_netif_ul_reload_retry() : Update retry-reload flag [%ub] for netif[%xl], netif_id[%xl], callback[%xl] while set-need-reload bit-mask[%xl]",
+        "traceClass": "UL_DETAIL_H",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_RELOAD_RETRY_RACE_COND": {
+        "format": "[IPCORE] ipc_set_netif_ul_reload_retry() : [%ub] Update retry-reload race condition occurred with retry-reload flag [%ub], set-need-reload flag [%l] and reload retrial bit-mask[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_RELOAD_RETRY_FLAG": {
+        "format": "[IPCORE] ipc_set_netif_ul_reload_retry() : [%ub] Uplink reload retrial bit-mask[%xl] while set-need-reload bit-mask[%xl]",
+        "traceClass": "UL_DETAIL_H",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_SET_NEED_RELOAD": {
+        "format": "[IPCORE] ipc_set_netif_ul_set_need_reload() : Update set-need-reload flag [%ub] for netif[%xl], netif_id[%xl], callback[%xl]",
+        "traceClass": "UL_DETAIL_H",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_SET_NEED_RELOAD_FLAG": {
+        "format": "[IPCORE] ipc_set_netif_ul_set_need_reload() : [%ub] Netif set need reload bit-mask[%xl]",
+        "traceClass": "UL_DETAIL_H",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_ON_RETRY_RELOAD": {
+        "format": "[IPCORE] ipc_on_retry_ul_reload() : [%ub] Current uplink reload retrial bit-mask[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_ON_RETRY_RELOAD_FOR_NETIF": {
+        "format": "[IPCORE] ipc_on_retry_ul_reload() : [%ub] Reload network interface[%xl] for bit[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_CHECK_UL_RELOAD_RETRY": {
+        "format": "[IPCORE] ipc_check_ul_reload_retry() : [%ub] Current uplink reload retrial bit-mask[%xl] : need retry reload !",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_DROP_UL_IOR": {
+        "format": "[IPCORE] ipc_forward_ul_ior() : [%ub] Drop UL IOR for netif[%xl], ior[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_LOOPBACK_UL_IOR": {
+        "format": "[IPCORE] ipc_forward_ul_ior() : [%ub] Loopback UL IOR for netif[%xl], ior[%xl], DL callback[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_LOOPBACK_UL_IOR_DROP": {
+        "format": "[IPCORE] ipc_forward_ul_ior() : [%ub] Drop loopback UL IOR due to invalid DL callback for netif[%xl], ior[%xl], DL callback[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_HANDLE_UL_GPD_LIST": {
+        "format": "[IPCORE] ipc_forward_ul_ior() : IP-Type(%ub) - To handle UL GPD : netif_id[%xl], first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_FORWARD_UL_SDU": {
+        "format": "[IPCORE] ipc_forward_ul_ior() : IP-Type(%ub) - Forward UL GPD : pdn_id[%xl], first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_HANDLE_IPV4_UL_GPD_LIST": {
+        "format": "[IPCORE] ipc_forward_ul_ior() : IP-Type(%ub) - To handle IPv4 UL GPD : netif_id[%xl], first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "UL_DETAIL_H",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_FORWARD_IPV4_UL_SDU": {
+        "format": "[IPCORE] ipc_forward_ul_ior() : IP-Type(%ub) - Forward IPv4 UL GPD : pdn_id[%xl], first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_HANDLE_IPV6_UL_GPD_LIST": {
+        "format": "[IPCORE] ipc_forward_ul_ior() : IP-Type(%ub) - To handle IPv6 UL GPD : netif_id[%xl], first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_FORWARD_IPV6_UL_SDU": {
+        "format": "[IPCORE] ipc_forward_ul_ior() : IP-Type(%ub) - Forward IPv6 UL GPD : pdn_id[%xl], first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_FORWARD_UL_SDU_MULTI_PS": {
+        "format": "[IPCORE] IPC_FORWARD_UL_SDU() : Forward UL GPD with pdn_id[%l]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_FORWARD_UL_SDU_BY_EBI_MULTI_PS": {
+        "format": "[IPCORE] IPC_FORWARD_UL_SDU_BY_EBI() : Forward GPD to UL with EBI(%l)",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_DHCP4C_PKT_SESSION": {
+        "format": "[IPCORE] ipc_on_dhcp4c_packet_ind() : [%ub] Send DHCPv4 gpd[%xl], ip_id[%ub], session[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_DHCP4C_PKT_UPLINK": {
+        "format": "[IPCORE] ipc_on_dhcp4c_packet_ind() : [%ub] Send DHCPv4 gpd[%xl], session[%xl], netif_id[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_SEND_PKT": {
+        "format": "[IPCORE] ipc_send_ul_pkt() : Receive GPD to UL with EBI(%l) : head[%xl] ~ tail[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_SEND_PKT_BY_PDN": {
+        "format": "[IPCORE] ipc_send_ul_pkt_by_pdn() : Receive GPD to UL with PDN(%l), ip_type(%xb) : head[%xl] ~ tail[%xl], length (%xl)",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_SEND_PKT_MULTI_PS": {
+        "format": "[IPCORE] ipc_send_ul_pkt_multiple_ps() : Function be called with EBI(%l) and proto_idx(%l)",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_SEND_PKT_BY_PDN_MULTI_PS": {
+        "format": "[IPCORE] ipc_send_ul_pkt_by_pdn_multiple_ps() : Function be called with PDN(%l) and proto_idx(%l)",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_SEND_PKT_BY_NETIF_ID": {
+        "format": "[IPCORE] ipc_send_ul_pkt_by_netif_id() : Send GPD to UL with NETIF_ID(%xl), ip_tpye(%xb) : head[%xl] ~ tail[%xl], length(%xl)",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_SEND_PKT_FORWARD": {
+        "format": "[IPCORE] ipc_on_process_ul_ior_list() : Send GPD to UL with EBI(%l) : head[%xl] ~ tail[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_CLUB_PKT_B4_FORWARD": {
+        "format": "[IPCORE] ipc_on_process_ul_ior_list() : Club curr UL GPD for EBI(%l) : head[%xl] ~ tail[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_CLUB_PKT_BY_PDN_B4_FORWARD": {
+        "format": "[IPCORE] ipc_on_process_ul_ior_list() : Club curr UL GPD for PDN(%l), ip_type(%xb) : head[%xl] ~ tail[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_SEND_PKT_BY_PDN_FORWARD": {
+        "format": "[IPCORE] ipc_on_process_ul_ior_list() : Send GPD to UL with PDN(%l), ip_type(%xb) : head[%xl] ~ tail[%xl]",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_META_DROP_DID_ALLOC_NG": {
+        "format": "[IPCORE] ipc_ipf_meta_do_filter() : packet drop because DID allocation failed, out_netif[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_META_DOWNLINK_CALLBACK": {
+        "format": "[IPCORE] ipc_meta_downlink() : Callback with DL IPF Meta start_idx[%xl], end_idx[%xl], q_type[%ub]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_META_ON_PROC": {
+        "format": "[IPCORE] ipc_on_process_dl_meta() : Process DL IPF Meta read_idx[%xl], end_idx[%xl], q_type[%ub]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_META_ON_PROC_DONE": {
+        "format": "[IPCORE] ipc_on_process_dl_meta() : Free DL IPF Meta read_idx[%xl], end_idx[%xl], q_cnt[%xl], q_type[%ub]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_META_PROC_INFO": {
+        "format": "[IPCORE] ipc_meta_downlink_dequeue() : DL IPF Meta head_idx[%xl], tail_idx[%xl], q_cnt[%xl], Pending_cnt[%xl], tbl_size[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_META_MATCH_RESULT": {
+        "format": "[IPCORE] ipc_on_process_dl_meta() : read_idx[%xl], match_result[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_LAN_DIRECT_SEND_DL_IOR": {
+        "format": "[IPCORE] ipc_on_process_ul_ior_list() : [%ub] CCMNI-LAN directly send DL IOR from netif_id[%xl] to netif_id[%xl] - IOR[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_SEND_IPV4_PKT": {
+        "format": "[IPCORE] ipc_send_dl_pkt() : [%ub] Send IPv4 GPD to netif_id[%xl], first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_SEND_IPV6_PKT": {
+        "format": "[IPCORE] ipc_send_dl_pkt() : [%ub] Send IPv6 GPD to netif_id[%xl], first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_SEND_PKT_DID": {
+        "format": "[IPCORE] ipc_send_dl_pkt_in_did() : Send DID to netif_id[%xl], did[%xl], pkt_cnt[%d]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_SEND_PKT_DID_PENDING": {
+        "format": "[IPCORE] ipc_send_dl_pkt_in_did() : Netif refuse to receive DL DIDs, pending_head[%xl], pending_tail[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_ON_DOWNLINK": {
+        "format": "[IPCORE] ipc_on_downlink() : Downlink handle from pdn_id[%l], head[%xl], tail[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_ON_DOWNLINK_FILTER_OUT": {
+        "format": "[IPCORE] ipc_on_downlink() : [%ub] Filter out all downlink GPDs : session_type[%ub], netif_id[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_ON_DOWNLINK_CALLBACK_INFO": {
+        "format": "[IPCORE] ipc_on_downlink() : Send DL GPDs from pdn_id[%l] - Session/netif information : session_type[%ub], netif_id[%xl]",
+        "traceClass": "DL_DETAIL_H",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_ON_DOWNLINK_CALLBACK_GPD": {
+        "format": "[IPCORE] ipc_on_downlink() : Send DL GPDs from pdn_id[%l] - GPD information : first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_ON_DOWNLINK_MULTI_PS": {
+        "format": "[IPCORE] ipc_on_downlink_multiple_ps() : Downlink handle from pdn_id[%l], proto_idx[%ub]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_ON_DID_DOWNLINK": {
+        "format": "[IPCORE] ipc_did_downlink_enqueue() : Downlink handle from pdn_id[%xl] (mask with proto_idx), head[%xl], tail[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_PROCESS_DL_DID": {
+        "format": "[IPCORE][DL_PSN flow: %ub, from: %xd, to: %xd, seg_num: %ud] ipc_on_process_dl_did_list() : Process DL DID[%xl] from pdn_id[%l]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_FWD_DL_CALLBACK_DID": {
+        "format": "[IPCORE] ipc_forward_dl_did_default() : Send DL %ub packets to netif_id[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_DO_FILTER_DID_ZERO_SIT": {
+        "format": "[IPCORE] ipc_do_did_filter() : hif_type is ignore && legnth is zero, curr_id[%ub] bypass_seg[%ub] pkt_seg[%ub]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_FWD_DL_CALLBACK_DID_WO_FILTER": {
+        "format": "[IPCORE] ipc_forward_dl_did_default_wo_filter() : Send DL %ub packets to netif_id[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_ON_DID_DOWNLINK_PENDING": {
+        "format": "[IPCORE] ipc_on_process_dl_did_list() : Netif refuse to receive DL DIDs, pending_head[%xl], pending_tail[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_ON_DID_DOWNLINK_TEST_LOOPBACK": {
+        "format": "[IPCORE] ipc_on_did_downlink_test_mode() : Downlink handle from pdn_id[%l], head[%xl], tail[%xl], test_mode[%ub]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_DO_FILTER_WHEN_LINK_DOWN": {
+        "format": "[IPCORE] ipc_on_process_dl_did_list_when_link_down() : Do DL filter when link down did_head[%xl], did_tail[%xl], from pdn_id[%l]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_INVALID_LEN_CHK": {
+        "format": "[IPCORE] ipc_pkt_do_filter() : dl_invalid_len : cur_gpd[%xl], cur_bd[%xl], pkt_length[%xl], valid_length[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_INVALID_LEN_CHK_DID": {
+        "format": "[IPCORE][DL_PSN flow: %ub, psn: %xd] ipc_pkt_do_filter() : dl_invalid_len : pkt_length[%xl], valid_length[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_INVALID_LEN_PKT_IP_HDR": {
+        "format": "[IPCORE] ipc_pkt_do_filter() : dl_invalid_len ip_header[%ub] header data[%xl]",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_FILTER_RULE_MATCHED": {
+        "format": "[IPCORE] ipc_pkt_do_filter() : [%ub] filter rule matched - filter rules: rules[%xl], features[%xb], valid_fields[%xl], matched[%xl]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_SPD_DO_FILTER": {
+        "format": "[IPCORE] ipc_spd_do_filter() : [%ub] SPD[%xl] with length[%xl], pkt_num[%xb] is about to do filter",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_SPD_ENTRY_IGR_INFO": {
+        "format": "[IPCORE] ipc_spd_do_filter() : One of SPD entries has been ignored : uplink[%ub], curr_spd[%xl], idx[%l], payload_len[%l]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_SPD_ALL_IGR_INFO": {
+        "format": "[IPCORE] ipc_do_filter() : All entry of the SPD have been ignored : uplink[%ub], curr_spd[%xl], packet_num[%l]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_DO_FILTER_GPD_UPDATE": {
+        "format": "[IPCORE] ipc_do_filter() : GPD update after uniting : uplink[%ub], curr_gpd[%xl], united_gpd[%xl]/len[%l]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_FILTER_OUT_INFO": {
+        "format": "[IPCORE] ipc_call_filter_cbk() : filter out and callback - General info : uplink[%ub], callback_context[%xl], filter_id[%xl]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_FILTER_OUT_GPD": {
+        "format": "[IPCORE] ipc_call_filter_cbk() : filter out and callback - GPD info : uplink[%ub], gpd_head[%xl], gpd_tail[%xl], length[%l]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_UNITE_FAIL_DROP": {
+        "format": "[IPCORE] ipc_do_filter() : Unite Failed ! Drop packet with length[%l], orgGPD[%lx]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_UNITE_FAIL_DROP_INFO": {
+        "format": "[IPCORE] ipc_do_filter() : Dropped packet info : FilterID[%l], orgGPD[%lx], pdnID[%l], netifID[%l]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_HANDLE_GPD": {
+        "format": "[IPCORE] ipc_pack_pkt() : [%ub] Handle GPD - head[%xl], tail[%xl]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_SET_ALLOC_DATA": {
+        "format": "[IPCORE] ipc_pack_pkt() : Set and allocate GPD for data buffer - data_len[%l], data[%xl], ip_header_len[%l], udp_header_len[%l]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_FILL_HEADER": {
+        "format": "[IPCORE] ipc_pack_pkt() : Fill header with total_le[%d] for GPD[%xl], ip_header_len[%l], udp_header_len[%l]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_PACK_PACKET_PUBLIC": {
+        "format": "[IPCORE] ipc_pack_pkt_public() : [%ub] ipc_pack_pkt_public() is invoked.",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GE_UNITED_GPD": {
+        "format": "[IPCORE] ipc_gpd_unite() : GPD is united with new one : uplink[%ub], p_gpd_in[%xl], *pp_gpd_out[%xl]/len[%l]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UL_PKT_FILTER_RESULT_META": {
+        "format": "[IPCORE][UL_PSN: %xd] ipc_pkt_do_filter() : packet match result[%ub], dpfm_rule_id[%ub] (only valid when result=3)",
+        "traceClass": "UL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_PKT_FILTER_RESULT_DID": {
+        "format": "[IPCORE][DL_PSN flow: %ub, psn: %xd] ipc_pkt_do_filter() : packet match result[%ub], dpfm_rule_id[%ub] (only valid when result=3)",
+        "traceClass": "DL_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_PKT_FILTER_RESULT_GPD": {
+        "format": "[IPCORE] ipc_pkt_do_filter() : uplink[%ub], gpd[%xl], packet match result[%ub], dpfm_rule_id[%ub] (only valid when result=3)",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_PKT_FILTER_RESULT_SPD": {
+        "format": "[IPCORE] ipc_pkt_do_filter() : uplink[%ub], packet match result[%ub], dpfm_rule_id[%ub] (only valid when result=3)",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_TRANS_GPD_TO_DID": {
+        "format": "[IPCORE] ipc_send_dl_pkt_in_did_internal() : translate GPD[%xl] to DID head[%xl] and DID tail[%xl])",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "PFM_GE_MATCHED_PACKET_INFO": {
+        "format": "[PFM] pfm_matched_packet_trace(): The matched packet ! EBI[%d], IPID[%xb], checksum[%xd]",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "PFM_GE_MATCHED_PACKET_DUMP": {
+        "format": "[PFM DUMP] %3d: %10xl %10xl %10xl %10xl",
+        "traceClass": "DATA_PATH_SENSATIVE_L",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "PFM_DL_RECEIVED_FILTER_PACKET": {
+        "format": "[PFM] Received fin ack packet gpd_head (%xl) gpd_tail (%xl)",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DATA_DUMP_TRACE": {
+        "format": "[IPCORE] %b: %10xl %10xl %10xl %10xl",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_GET_NETIF_FROM_META": {
+        "format": "[IPCORE] ipc_get_netif_id_from_meta() : net_type(%d), channl_id(%d), netif(0x%xl)",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DL_ENQ_BY_NETIF": {
+        "format": "[IPCORE] ipc_data_dl_enq_by_netif() : Send did_head(0x%xl), did_head(0x%xl) to netif_id(%d)",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_CHECK_ROUTE_MATCHED": {
+        "format": "[IPCORE] ipc_pkt_do_filter() : uplink[%ub] ip_type[%ub] DPFM check route matched to out_netif_id[%xl]",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_ON_DOWNLINK": {
+        "format": "[IPCORE] ipc_dpfm_on_downlink() : [%ub] DPFM DL direct path : first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_ON_DOWNLINK_PKT_IPV4": {
+        "format": "[IPCORE] ipc_dpfm_on_downlink() : DPFM DL direct path IPV4 : curr_gpd[%xl], IPID = %xb, checksum = %xd",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_ON_DOWNLINK_PKT_IPV6": {
+        "format": "[IPCORE] ipc_dpfm_on_downlink() : DPFM DL direct path IPV6 : protocol:%d, curr_gpd[%xl], checksum = %xl, Src Addr=%10xl %10xl %10xl %10xl",
+        "traceClass": "DATA_PATH_SENSATIVE_L",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_ON_DOWNLINK_PKT_NON_IPV4V6": {
+        "format": "[IPCORE] ipc_dpfm_on_downlink() : DPFM DL direct path non IPv4 and IPv6 : curr_gpd[%xl], length = %d",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_FORWARD_UL_IOR": {
+        "format": "[IPCORE] ipc_dpfm_forward_ul_ior() : [%d] DPFM UL direct path : first_gpd[%xl], last_gpd[%xl]",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_FORWARD_UL_IOR_PKT_IPV4": {
+        "format": "[IPCORE] ipc_dpfm_forward_ul_ior() : DPFM UL direct path IPv4 : curr_gpd[%xl], IPID = %xl, checksum = %xl",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_FORWARD_UL_IOR_PKT_IPV6": {
+        "format": "[IPCORE] ipc_dpfm_forward_ul_ior() : DPFM UL direct path IPv6 : protocol:%d, curr_gpd[%xl], checksum = %xl, Src Addr=%10xl %10xl %10xl %10xl",
+        "traceClass": "DATA_PATH_SENSATIVE_L",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_FORWARD_UL_IOR_PKT_NON_IPV4V6": {
+        "format": "[IPCORE] ipc_dpfm_forward_ul_ior() : DPFM UL direct path non IPv4 and IPv6 : curr_gpd[%xl], length = %d",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_BIND_LAN_NETIF": {
+        "format": "[IPCORE] ipc_bind_lan_netif() : [%d] netif_1[%xl] id[%xl], netif_2[%xl] id[%xl]",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_UNBIND_LAN_NETIF": {
+        "format": "[IPCORE] ipc_unbind_lan_netif() : [%d] netif_1[%xl], id[%xl], netif_2[%xl] id[%xl]",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_DPFM_DETECT_FM_NOT_MATCH": {
+        "format": "[IPCORE] ipc_on_pdn_deact() : DPFM detect flight mode not match [%d] netif[%xl]",
+        "traceClass": "DPFM_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_TR_CUST_FILTER_CBK": {
+        "format": "[IPCORE] Filter matched and invoke cust filter cbk with pkt (0x%xl) pkt_len (0x%xl) filter_id (0x%xl) result (0x%xl)",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "IPC_SEND_L2_UNK_INFO": {
+        "format": "[IPCORE] Send L2 unknown header info from meta (0x%xl) to meta (0x%xl) unk_cnt (0x%xl) begin_cntl (0x%xl) end_cntl (0x%xl) rb_idx (0x%xl) proto_idx (0x%xl)",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "LTM_SIM_TPUT_ANALYSIS": {
+        "format": "[LTM_SIM] REAL_PKT_NUM : %d, EXPECTED_PKT_NUM : %l, TIME_DIFF : %l, Current_Time: %l, Last_Time : %l, RECYCLE_PKT_NUM : %l.",
+        "traceClass": "GE_UH",
+        "traceHighlightOption": "info"
+      }
+    }
+  ],
+  "traceFamily": "L2",
+  "userModule": "MOD_IPCORE"
+}
diff --git a/mcu/middleware/hif/interface/ipcore_dhcph.h b/mcu/middleware/hif/interface/ipcore_dhcph.h
new file mode 100644
index 0000000..a59222b
--- /dev/null
+++ b/mcu/middleware/hif/interface/ipcore_dhcph.h
@@ -0,0 +1,201 @@
+/*!
+ *  @file ipcore_dhcph.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides DHCP Header definitions of ipcore
+ */
+
+#ifndef _IPCORE_DHCPH_H
+#define _IPCORE_DHCPH_H
+
+#include "kal_public_api.h"
+
+#define IPC_BP_CHADDR_LEN           16
+#define IPC_BP_SNAME_LEN            64
+#define IPC_BP_FILE_LEN             128
+//#define IPC_BP_VEND_LEN             312+32
+
+#define IPC_BP_BOOT_REQUEST         1
+#define IPC_BP_BOOT_REPLY           2
+
+#define IPC_BP_HTYPE_ETHERNET       1
+#define IPC_BP_HTYPE_EXP_ETHERNET   2
+#define IPC_BP_HTYPE_AX25           3
+#define IPC_BP_HTYPE_PRONET         4
+#define IPC_BP_HTYPE_CHAOS          5
+#define IPC_BP_HTYPE_IEEE802        6
+#define IPC_BP_HTYPE_ARCNET         7
+
+#define IPC_BP_MAGIC_COOKIE         {0x63, 0x82, 0x53, 0x63}
+
+#define IPC_BP_OPTION_PAD                                   0
+#define IPC_BP_OPTION_SUBNET_MASK                           1
+#define IPC_BP_OPTION_ROUTER                                3
+#define IPC_BP_OPTION_DOMAIN_NAME_SERVER                    6
+#define IPC_BP_OPTION_HOST_NAME                             12
+#define IPC_BP_OPTION_INTERFACE_MTU                         26
+#define IPC_BP_OPTION_REQUESTED_IP_ADDRESS                  50
+#define IPC_BP_OPTION_IP_ADDRESS_LEASE_TIME                 51
+#define IPC_BP_OPTION_DHCP_MESSAGE_TYPE                     53
+#define IPC_BP_OPTION_SERVER_IDENTIFIER                     54
+#define IPC_BP_OPTION_PARAMETER_REQUEST_LIST                55
+#define IPC_BP_OPTION_MAXIMUM_DHCP_MESSAGE_SIZE             57
+#define IPC_BP_OPTION_RENEWAL_TIME_VALUE                    58
+#define IPC_BP_OPTION_REBINDING_TIME_VALUE                  59
+#define IPC_BP_OPTION_VENDOR_CLASS_IDENTIFIER               60
+#define IPC_BP_OPTION_CLIENT_IDENTIFIER                     61
+#define IPC_BP_OPTION_CLIENT_FULLY_QUALIFIED_DOMAIN_NAME    81
+#define IPC_BP_OPTION_END                                   255
+
+#define IPC_BP_DHCP_MESSAGE_TYPE_DHCP_DISCOVER              1
+#define IPC_BP_DHCP_MESSAGE_TYPE_DHCP_OFFER                 2
+#define IPC_BP_DHCP_MESSAGE_TYPE_DHCP_REQUEST               3
+#define IPC_BP_DHCP_MESSAGE_TYPE_DHCP_DECLINE               4
+#define IPC_BP_DHCP_MESSAGE_TYPE_DHCP_ACK                   5
+#define IPC_BP_DHCP_MESSAGE_TYPE_DHCP_NAK                   6
+#define IPC_BP_DHCP_MESSAGE_TYPE_DHCP_RELEASE               7
+#define IPC_BP_DHCP_MESSAGE_TYPE_DHCP_INFORM                8
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bootp_header {
+    kal_uint8       bp_op;                  // packet opcode type
+    kal_uint8       bp_htype;               // hardware addr type
+    kal_uint8       bp_hlen;                // hardware addr length
+    kal_uint8       bp_hops;                // gateway hops
+    kal_uint32      bp_xid;                 // transaction ID
+    kal_uint16      bp_secs;                // seconds since boot began
+    kal_uint16      bp_flags;               // RFC1532 broadcazst, etc
+    ipc_ip4_addr_t  bp_ciaddr;              // client IP address
+    ipc_ip4_addr_t  bp_yiaddr;              // your IP address
+    ipc_ip4_addr_t  bp_siaddr;              // server IP address
+    ipc_ip4_addr_t  bp_giaddr;              // gateway IP address
+    kal_uint8       bp_chaddr[IPC_BP_CHADDR_LEN];   // client hardware address
+    kal_uint8       bp_sname[IPC_BP_SNAME_LEN];     // server host name
+    kal_uint8       bp_file[IPC_BP_FILE_LEN];       // boot file name
+} ipc_bootp_header_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_dhcp_message_type {
+    kal_uint8           code;
+    kal_uint8           len;
+    kal_uint8           type;
+} ipc_bp_option_dhcp_message_type_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_requested_ip_address {
+    kal_uint8           code;
+    kal_uint8           len;
+    ipc_ip4_addr_t      address;
+} ipc_bp_option_requested_ip_address_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_server_identifier {
+    kal_uint8           code;
+    kal_uint8           len;
+    ipc_ip4_addr_t      address;
+} ipc_bp_option_server_identifier_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_ip_address_lease_time {
+    kal_uint8           code;
+    kal_uint8           len;
+    kal_uint32          lease_time;
+} ipc_bp_option_ip_address_lease_time_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_maximum_dhcp_message_size {
+    kal_uint8           code;
+    kal_uint8           len;
+    kal_uint16          length;
+} ipc_bp_option_maximum_dhcp_message_size_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_subnet_mask {
+    kal_uint8           code;
+    kal_uint8           len;
+    ipc_ip4_addr_t      subnet_mask;
+} ipc_bp_option_subnet_mask_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_router {
+    kal_uint8           code;
+    kal_uint8           len;
+    ipc_ip4_addr_t      address;
+} ipc_bp_option_router_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_domain_name_server {
+    kal_uint8           code;
+    kal_uint8           len;
+    ipc_ip4_addr_t      address;
+} ipc_bp_option_domain_name_server_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_renewal_time_value {
+    kal_uint8           code;
+    kal_uint8           len;
+    kal_uint32          t1_interval;
+} ipc_bp_option_renewal_time_value_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_rebinding_time_value {
+    kal_uint8           code;
+    kal_uint8           len;
+    kal_uint32          t2_interval;
+} ipc_bp_option_rebinding_time_value_t;
+PRAGMA_END_PACK_STRUCT
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_bp_option_interface_mtu {
+    kal_uint8           code;
+    kal_uint8           len;
+    kal_uint16          mtu;
+} ipc_bp_option_interface_mtu_t;
+PRAGMA_END_PACK_STRUCT
+
+#endif  // _IPCORE_DHCPH_H
+
diff --git a/mcu/middleware/hif/interface/ipcore_icmph.h b/mcu/middleware/hif/interface/ipcore_icmph.h
new file mode 100644
index 0000000..50569b8
--- /dev/null
+++ b/mcu/middleware/hif/interface/ipcore_icmph.h
@@ -0,0 +1,311 @@
+/*!
+ *  @file ipcore_icmph.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides ICMP Header definitions of ipcore
+ */
+
+#ifndef _IPCORE_ICMPH_H
+#define _IPCORE_ICMPH_H
+
+#include "kal_public_api.h"
+
+#define IPC_ICMP_ECHO_REPLY             0       /* Echo Reply               */
+#define IPC_ICMP_ECHO_REQUEST           8       /* Echo Request             */
+
+
+#define IPC_ICMP6_ECHO_REQUEST          128     /* echo request             */
+#define IPC_ICMP6_ECHO_REPLY            129     /* echo reply               */
+#define IPC_ICMP6_NDP_ROUTER_SOLICIT    133     /* router solicitation      */
+#define IPC_ICMP6_NDP_ROUTER_ADVERT     134     /* router advertisment      */
+#define IPC_ICMP6_NDP_NEIGHBOR_SOLICIT  135     /* neighbor solicitation    */
+#define IPC_ICMP6_NDP_NEIGHBOR_ADVERT   136     /* neighbor advertisment    */
+#define IPC_ICMP6_NDP_REDIRECT          137     /* redirect                 */
+
+#define IPC_ICMP6_NDP_OPT_SOURCE_LINKADDR       1
+#define IPC_ICMP6_NDP_OPT_TARGET_LINKADDR       2
+#define IPC_ICMP6_NDP_OPT_PREFIX_INFORMATION    3
+#define IPC_ICMP6_NDP_OPT_REDIRECTED_HEADER     4
+#define IPC_ICMP6_NDP_OPT_MTU                   5
+#define IPC_ICMP6_NDP_OPT_RDNSS                 25
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_icmp_header {
+    kal_uint8   icmp_type;      // type field
+    kal_uint8   icmp_code;      // code field
+    kal_uint16  icmp_cksum;     // checksum field
+    union {
+        kal_uint32  icmp_un_data32[1];  // type-specific field
+        kal_uint16  icmp_un_data16[2];  // type-specific field
+        kal_uint8   icmp_un_data8[4];   // type-specific field
+   } icmp_dataun;
+} ipc_icmp_header_t;
+PRAGMA_END_PACK_STRUCT
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_icmp_echo_header {
+    kal_uint8   icmp_type;      // type field
+    kal_uint8   icmp_code;      // code field
+    kal_uint16  icmp_cksum;     // checksum field
+    kal_uint16  icmp_id;        // identifier
+    kal_uint16  icmp_seq;       // sequence
+} ipc_icmp_echo_header_t;
+PRAGMA_END_PACK_STRUCT
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_icmp6_header {
+    kal_uint8   icmp6_type;     // type field
+    kal_uint8   icmp6_code;     // code field
+    kal_uint16  icmp6_cksum;    // checksum field
+    union {
+        kal_uint32  icmp6_un_data32[1]; // type-specific field
+        kal_uint16  icmp6_un_data16[2]; // type-specific field
+        kal_uint8   icmp6_un_data8[4];  // type-specific field
+   } icmp6_dataun;
+} ipc_icmp6_header_t;
+PRAGMA_END_PACK_STRUCT
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_icmp6_echo_header {
+    kal_uint8   icmp6_type;     // type field
+    kal_uint8   icmp6_code;     // code field
+    kal_uint16  icmp6_cksum;    // checksum field
+    kal_uint16  icmp6_id;       // identifier
+    kal_uint16  icmp6_seq;      // sequence
+} ipc_icmp6_echo_header_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/* router solicitation */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ndp_router_solicit {
+    kal_uint8   icmp6_type;         // type field
+    kal_uint8   icmp6_code;         // code field
+    kal_uint16  icmp6_cksum;        // checksum field
+    kal_uint32  reserve;            // reserved
+    /* could be followed by options */
+} ipc_ndp_router_solicit_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/* router advertisement */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ndp_router_advert {
+    kal_uint8   icmp6_type;         // type field
+    kal_uint8   icmp6_code;         // code field
+    kal_uint16  icmp6_cksum;        // checksum field
+    kal_uint8   hop_limit;          // hop limit
+    kal_uint8   reserve:6,
+                is_other_stateful:1,// other stateful configuraiton flag
+                is_managed_addr:1;  // managed address configuration flag
+    kal_uint16  router_lifetime;    // router life time
+    kal_uint32  reachable_time;     // reachable time
+    kal_uint32  retransmit_time;    // retransmit timer
+    /* could be followed by options */
+} ipc_ndp_router_advert_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/* neighbor solicitation */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ndp_neighbor_solicit {
+    kal_uint8       icmp6_type;         // type field
+    kal_uint8       icmp6_code;         // code field
+    kal_uint16      icmp6_cksum;        // checksum field
+    kal_uint32      reserve;            // reserved
+    ipc_ip6_addr_t  target_addr;        // target address
+    /* could be followed by options */
+} ipc_ndp_neighbor_solicit_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/* neighbor advertisement */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ndp_neighbor_advert {
+    kal_uint8       icmp6_type;         // type field
+    kal_uint8       icmp6_code;         // code field
+    kal_uint16      icmp6_cksum;        // checksum field
+    kal_uint32      reserve:29,
+                    is_override:1,      // override flag
+                    is_solicited:1,     // solicited flag
+                    is_router:1;        // router flag
+    ipc_ip6_addr_t  target_addr;        // target address
+    /* could be followed by options */
+} ipc_ndp_neighbor_advert_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/* redirect */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ndp_redirect {
+    kal_uint8       icmp6_type;         // type field
+    kal_uint8       icmp6_code;         // code field
+    kal_uint16      icmp6_cksum;        // checksum field
+    kal_uint32      reserve;            // reserved
+    ipc_ip6_addr_t  target_addr;        // target address
+    ipc_ip6_addr_t  dst_addr;           // destination address
+    /* could be followed by options */
+} ipc_ndp_redirect_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/* Option Link-Layer Address */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ndp_opt_link_layer_addr {
+    kal_uint8               type;
+    kal_uint8               len;        // len = 1 for ieee 802 address
+    ipc_ieee_802_addr_t     addr;
+} ipc_ndp_opt_link_layer_addr_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/* Option Prefix Information */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ndp_opt_prefix {
+    kal_uint8       type;
+    kal_uint8       len;                // len = 4
+    kal_uint8       prefix_len;
+    kal_uint8       reserve1:6,
+                    is_on_link:1,
+                    is_autonomous:1;
+    kal_uint32      valid_lifetime;
+    kal_uint32      preferred_lifetime;
+    kal_uint32      reserve2;
+    ipc_ip6_addr_t  prefix;
+} ipc_ndp_opt_prefix_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/* Option MTU */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ndp_opt_mtu {
+    kal_uint8       type;
+    kal_uint8       len;                // len = 1
+    kal_uint16      reserve;
+    kal_uint32      mtu;
+} ipc_ndp_opt_mtu_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/* Option RDNSS */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ndp_opt_rdnss {
+    kal_uint8       type;
+    kal_uint8       len;                // minimum 3
+    kal_uint16      reserve;
+    kal_uint32      life_time;
+    ipc_ip6_addr_t  dns_addr;
+} ipc_ndp_opt_rdnss_t;
+PRAGMA_END_PACK_STRUCT
+
+static INLINE kal_uint16 ipc_icmp_cksum(ipc_icmp_header_t* pIcmp, kal_uint16 len)
+{
+    kal_uint32 cksum    = 0;
+    kal_uint16 word     = 0;
+    kal_uint16 i        = 0;
+
+    for ( i=0; i<((len+1)&~1); i+=2 )
+    {
+        if ( i == (len -1) )
+        {
+            word = ((((kal_uint8*)pIcmp)[i] << 8) & 0xff00) + 0x00 ;
+        } else {
+            word = ((((kal_uint8*)pIcmp)[i] << 8) & 0xff00) + (((kal_uint8*)pIcmp)[i+1] & 0xff) ;
+        }
+        cksum = cksum + word;
+    }
+
+    while ( cksum >> 16 )
+        cksum = ( cksum & 0xffff ) + (cksum >> 16);
+
+    return (kal_uint16)~cksum;
+}
+
+
+static INLINE kal_uint16 ipc_icmp6_cksum(ipc_ip6_addr_t* src, ipc_ip6_addr_t* dst, kal_uint32 len, kal_uint16* data)
+{
+    kal_uint32 chksum = 0;
+    kal_uint32 i;
+    union {
+        kal_uint32 dword;
+        kal_uint16 word[2];
+        kal_uint8  byte[4];
+    } tmp;
+
+    for ( i=0; i<8; i++ )
+    {
+        chksum += src->s6_addr16[i];
+    }
+
+    for ( i=0; i<8; i++ )
+    {
+        chksum += dst->s6_addr16[i];
+    }
+
+    tmp.dword = IPC_NTOHL(len);
+    chksum += tmp.word[0];
+    chksum += tmp.word[1];
+
+    tmp.dword = 0;
+    tmp.byte[3] = IPC_IPPROTO_ICMP6;
+    chksum += tmp.word[0];
+    chksum += tmp.word[1];
+
+    for ( i=0; i<(len & ~1); i+=2 )
+    {
+        chksum += *data++;
+    }
+
+    if ( len & 1 )
+        chksum += *(kal_uint8*)data;
+
+    while ( chksum > 0xffff )
+    {
+        chksum = ( chksum & 0xffff ) + (chksum >> 16);
+    }
+
+    chksum = ~chksum & 0xffff;
+
+    return (kal_uint16)chksum;
+
+}
+
+#endif  // _IPCORE_ICMPH_H
+
diff --git a/mcu/middleware/hif/interface/ipcore_iph.h b/mcu/middleware/hif/interface/ipcore_iph.h
new file mode 100644
index 0000000..1b5569c
--- /dev/null
+++ b/mcu/middleware/hif/interface/ipcore_iph.h
@@ -0,0 +1,336 @@
+/*!
+ *  @file ipcore_iph.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides IP Header definitions of ipcore
+ */
+
+#ifndef _IPCORE_IPH_H
+#define _IPCORE_IPH_H
+
+#include "kal_public_api.h"
+
+#if !defined(__MTK_TARGET__) && defined(_MSC_VER) && (_MSC_VER >= 1500)
+#pragma warning( disable : 4214 )
+#endif
+
+#define IPC_IP4_VERSION         4
+#define IPC_IP6_VERSION         6
+
+#define IPC_IPPROTO_HOPOPTS     0       /* IP6 hop-by-hop options */
+#define IPC_IPPROTO_ICMP        1       /* ICMP */
+#define IPC_IPPROTO_TCP         6       /* TCP */
+#define IPC_IPPROTO_UDP         17      /* UDP */
+#define IPC_IPPROTO_ROUTING     43      /* IP6 routing header */
+#define IPC_IPPROTO_FRAGMENT    44      /* IP6 fragmentation header */
+#define IPC_IPPROTO_ESP         50      /* IP6 Encap Sec. Payload */
+#define IPC_IPPROTO_AH          51      /* IP6 Auth Header */
+#define IPC_IPPROTO_ICMP6       58      /* ICMP6 */
+#define IPC_IPPROTO_NONE        59      /* IP6 no next header */
+#define IPC_IPPROTO_DSTOPTS     60      /* IP6 destination option */
+
+#define IPC_IPPORT_BOOTPS       67      /* Bootstrap Protocol Server */
+#define IPC_IPPORT_BOOTPC       68      /* Bootstrap Protocol Client */
+
+#define IPC_EUI64_GBIT          0x01
+#define IPC_EUI64_UBIT          0x02
+
+#define IPC_IP6_IS_ADDR_UNSPECIFIED(_addr)  \
+    ((*(const kal_uint32 *)(const void *)(&(_addr)->s6_addr8[0]) == 0) &&   \
+     (*(const kal_uint32 *)(const void *)(&(_addr)->s6_addr8[4]) == 0) &&   \
+     (*(const kal_uint32 *)(const void *)(&(_addr)->s6_addr8[8]) == 0) &&   \
+     (*(const kal_uint32 *)(const void *)(&(_addr)->s6_addr8[12]) == 0))
+
+#define IPC_SWAP16(_x)          ((_x & 0xff00) >> 8 | (_x & 0x00ff) << 8)
+#define IPC_SWAP32(_x)          ((_x & 0xff000000) >> 24 |  \
+                                 (_x & 0x00ff0000) >> 8  |  \
+                                 (_x & 0x0000ff00) << 8  |  \
+                                 (_x & 0x000000ff) << 24)
+
+#define IPC_HTONS(_x)           IPC_SWAP16(_x)
+#define IPC_HTONL(_x)           IPC_SWAP32(_x)
+#define IPC_NTOHS(_x)           IPC_SWAP16(_x)
+#define IPC_NTOHL(_x)           IPC_SWAP32(_x)
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ieee_802_addr {
+    kal_uint8   addr[6];
+} ipc_ieee_802_addr_t;
+PRAGMA_END_PACK_STRUCT
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ip4_addr {
+    union {
+        kal_uint8   _u4_addr8[4];
+        kal_uint16  _u4_addr16[2];
+        kal_uint32  _u4_addr32;
+    } _u4_addr;
+} ipc_ip4_addr_t;
+PRAGMA_END_PACK_STRUCT
+#define s4_addr8  _u4_addr._u4_addr8
+#define s4_addr16 _u4_addr._u4_addr16
+#define s4_addr32 _u4_addr._u4_addr32
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ip6_addr {
+    union {
+        kal_uint8   _u6_addr8[16];
+        kal_uint16  _u6_addr16[8];
+        kal_uint32  _u6_addr32[4];
+    } _u6_addr;
+} ipc_ip6_addr_t;
+PRAGMA_END_PACK_STRUCT
+#define s6_addr8  _u6_addr._u6_addr8
+#define s6_addr16 _u6_addr._u6_addr16
+#define s6_addr32 _u6_addr._u6_addr32
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ip4_header {
+    kal_uint8       ip_hl:4,    // header length
+                    ip_ver:4;   // version
+    kal_uint8       ip_tos;     // type of service
+    kal_uint16      ip_len;     // total length
+    kal_uint16      ip_id;      // identification
+    kal_uint16      ip_off;     // fragment offset field
+    kal_uint8       ip_ttl;     // time to live
+    kal_uint8       ip_pro;     // protocol
+    kal_uint16      ip_sum;     // checksum
+    ipc_ip4_addr_t  ip_src;     // source address
+    ipc_ip4_addr_t  ip_dst;     // destination address
+} ipc_ip4_header_t;
+PRAGMA_END_PACK_STRUCT
+
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_ip6_header {
+    union {
+        kal_uint8   ip6_ver;                // 4 bits version
+        kal_uint32  ip6_flow;               // 20 bits of flow-ID
+    } ip6_un;
+    kal_uint16      ip6_plen;               // payload length
+    kal_uint8       ip6_nxt;                // next header
+    kal_uint8       ip6_hlim;               // hop limit
+    ipc_ip6_addr_t  ip6_src;                // source address
+    ipc_ip6_addr_t  ip6_dst;                // destionation address
+} ipc_ip6_header_t;
+PRAGMA_END_PACK_STRUCT
+#define IPC_IP6_VERSION_OFFSET      4
+#define ip6_verion                  ip6_un.ip6_ver
+#define ip6_flow                    ip6_un.ip6_flow
+
+
+static INLINE void ipc_eui64_to_link_local(ipc_ip6_addr_t* dst)
+{
+    /* Link Local Prefix */
+    dst->s6_addr8[0]    = 0xFE;
+    dst->s6_addr8[1]    = 0x80;
+    /* Admin Subnet */
+    dst->s6_addr8[2]    = 0x00;
+    dst->s6_addr8[3]    = 0x00;
+    dst->s6_addr8[4]    = 0x00;
+    dst->s6_addr8[5]    = 0x00;
+    dst->s6_addr8[6]    = 0x00;
+    dst->s6_addr8[7]    = 0x00;
+}
+
+
+static INLINE void ipc_mac_to_eui64(ipc_ieee_802_addr_t* src, ipc_ip6_addr_t* dst)
+{
+    /* Link Local Prefix */
+    dst->s6_addr8[0]    = 0x00;
+    dst->s6_addr8[1]    = 0x00;
+    /* Admin Subnet */
+    dst->s6_addr8[2]    = 0x00;
+    dst->s6_addr8[3]    = 0x00;
+    dst->s6_addr8[4]    = 0x00;
+    dst->s6_addr8[5]    = 0x00;
+    dst->s6_addr8[6]    = 0x00;
+    dst->s6_addr8[7]    = 0x00;
+    /* Interface ID */
+    dst->s6_addr8[8]    = src->addr[0];
+    dst->s6_addr8[8]   &= ~IPC_EUI64_GBIT;
+    dst->s6_addr8[8]   |= IPC_EUI64_UBIT;
+    dst->s6_addr8[9]    = src->addr[1];
+    dst->s6_addr8[10]   = src->addr[2];
+    dst->s6_addr8[11]   = 0xff;
+    dst->s6_addr8[12]   = 0xfe;
+    dst->s6_addr8[13]   = src->addr[3];
+    dst->s6_addr8[14]   = src->addr[4];
+    dst->s6_addr8[15]   = src->addr[5];
+}
+
+
+static INLINE void ipc_eui64_to_mac(ipc_ip6_addr_t* src, ipc_ieee_802_addr_t* dst)
+{
+    dst->addr[0]    = src->s6_addr8[8];
+    dst->addr[0]   &= ~IPC_EUI64_UBIT;
+    dst->addr[1]    = src->s6_addr8[9];
+    dst->addr[2]    = src->s6_addr8[10];
+    dst->addr[3]    = src->s6_addr8[13];
+    dst->addr[4]    = src->s6_addr8[14];
+    dst->addr[5]    = src->s6_addr8[15];
+}
+
+
+static INLINE void ipc_find_ipv4_data_header(ipc_ip4_header_t* pIp, kal_uint32* offset)
+{
+    *offset = pIp->ip_hl*4;
+}
+
+
+static INLINE void ipc_find_ipv6_data_header(ipc_ip6_header_t* pIp6, kal_uint8* next_header, kal_uint32* offset)
+{
+    kal_uint8 header_ext_len    = 0;
+
+    /* search all next header, and find the last one */
+    *next_header = pIp6->ip6_nxt;
+    *offset = sizeof(ipc_ip6_header_t);
+    do {
+        kal_bool is_exit = KAL_FALSE;
+
+        switch ( *next_header )
+        {
+            case IPC_IPPROTO_HOPOPTS:
+            case IPC_IPPROTO_ROUTING:
+            case IPC_IPPROTO_DSTOPTS:
+            {
+                *next_header = *((kal_uint8*)pIp6 + *offset);
+                header_ext_len = *((kal_uint8*)pIp6 + *offset+1);
+                *offset = 8 * ( 1 + header_ext_len );
+                break;
+            }
+            case IPC_IPPROTO_FRAGMENT:
+            {
+                *next_header = *((kal_uint8*)pIp6 + *offset);
+                header_ext_len = 0;
+                *offset = 8;
+                break;
+            }
+            case IPC_IPPROTO_AH:
+            {
+                *next_header = *((kal_uint8*)pIp6 + *offset);
+                header_ext_len = *((kal_uint8*)pIp6 + *offset+1);
+                *offset = 4 * ( 2 + header_ext_len );
+                break;
+            }
+            case IPC_IPPROTO_NONE:
+            case IPC_IPPROTO_ESP:
+            default:
+            {
+                is_exit = KAL_TRUE;
+                break;
+            }
+        }
+
+        if ( is_exit == KAL_TRUE ) break;
+
+    } while (1);
+
+}
+
+
+static INLINE kal_uint16 ipc_ip4_cksum(ipc_ip4_header_t* pIp, kal_uint16 len)
+{
+    kal_uint32 cksum    = 0;
+    kal_uint16 word     = 0;
+    kal_uint32 i        = 0;
+
+    for ( i=0; i<len; i+=2 )
+    {
+        word = ((((kal_uint8*)pIp)[i] << 8) & 0xff00) + (((kal_uint8*)pIp)[i+1] & 0xff) ;
+        cksum = cksum + word;
+    }
+
+    while ( cksum >> 16 )
+        cksum = ( cksum & 0xffff ) + (cksum >> 16);
+
+    return (kal_uint16)~cksum;
+}
+
+
+#define IPC_MASK_IP_VER         (0xF0)
+#define IPC_IPV4_VER            (0x40)
+#define IPC_IPV6_VER            (0x60)
+#define IPC_MIN_IPV4_HDR_LEN    (20)
+#define IPC_MIN_IPV6_HDR_LEN    (40)
+#define IPC_MIN_IP_HEADER_LEN   (40)
+
+#define IPC_IS_IPV4_PACKET(n) \
+            (((n) & IPC_MASK_IP_VER) == IPC_IPV4_VER)
+#define IPC_IS_IPV6_PACKET(n) \
+            (((n) & IPC_MASK_IP_VER) == IPC_IPV6_VER)
+static INLINE kal_bool ipc_swap_ip_addr(kal_uint8 *ip_hdr)
+{
+    kal_uint32 tmp;
+
+    if (IPC_IS_IPV4_PACKET(*ip_hdr)) {
+        ipc_ip4_header_t *ipv4 = (ipc_ip4_header_t *)ip_hdr;
+
+        tmp = ipv4->ip_src.s4_addr32;   
+        ipv4->ip_src.s4_addr32 = ipv4->ip_dst.s4_addr32;
+        ipv4->ip_dst.s4_addr32 = tmp;
+    } else if (IPC_IS_IPV6_PACKET(*ip_hdr)) {
+        ipc_ip6_header_t *ipv6 = (ipc_ip6_header_t *)ip_hdr;
+
+        tmp = ipv6->ip6_src.s6_addr32[0];
+        ipv6->ip6_src.s6_addr32[0] = ipv6->ip6_dst.s6_addr32[0];
+        ipv6->ip6_dst.s6_addr32[0] = tmp;
+
+        tmp = ipv6->ip6_src.s6_addr32[1];
+        ipv6->ip6_src.s6_addr32[1] = ipv6->ip6_dst.s6_addr32[1];
+        ipv6->ip6_dst.s6_addr32[1] = tmp;
+
+        tmp = ipv6->ip6_src.s6_addr32[2];
+        ipv6->ip6_src.s6_addr32[2] = ipv6->ip6_dst.s6_addr32[2];
+        ipv6->ip6_dst.s6_addr32[2] = tmp;
+
+        tmp = ipv6->ip6_src.s6_addr32[3];
+        ipv6->ip6_src.s6_addr32[3] = ipv6->ip6_dst.s6_addr32[3];
+        ipv6->ip6_dst.s6_addr32[3] = tmp;
+    } else {
+        return KAL_FALSE;
+    }
+
+    return KAL_TRUE;
+}
+
+
+#endif  // _IPCORE_IPH_H
+
diff --git a/mcu/middleware/hif/interface/ipcore_udph.h b/mcu/middleware/hif/interface/ipcore_udph.h
new file mode 100644
index 0000000..0ff957c
--- /dev/null
+++ b/mcu/middleware/hif/interface/ipcore_udph.h
@@ -0,0 +1,96 @@
+/*!
+ *  @file ipcore_udph.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides UDP Header definitions of ipcore
+ */
+
+#ifndef _IPCORE_UDPH_H
+#define _IPCORE_UDPH_H
+
+#include "kal_public_api.h"
+
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _ipc_udp_header {
+    kal_uint16      udp_src_port;           // udp source port
+    kal_uint16      udp_dst_port;           // udp destination port
+    kal_uint16      udp_len;                // udp length
+    kal_uint16      udp_sum;                // udp checksum
+} ipc_udp_header_t;
+PRAGMA_END_PACK_STRUCT
+
+
+
+static INLINE kal_uint16 ipc_udp_cksum(ipc_udp_header_t* pUdp, kal_uint16 len, ipc_ip4_addr_t* ip_src, ipc_ip4_addr_t* ip_dst)
+{
+    kal_uint32 cksum    = 0;
+    kal_uint16 word     = 0;
+    kal_uint16 i        = 0;
+
+    for (i=0; i< ((len+1)&~1); i=i+2)
+    {
+        if ( i == (len -1) )
+        {
+            word = ( (((kal_uint8*)pUdp)[i] << 8 ) & 0xff00 ) + 0x00;
+        } else {
+            word = ( (((kal_uint8*)pUdp)[i] << 8 ) & 0xff00 ) + (((kal_uint8*)pUdp)[i+1] & 0xff);
+        }
+        cksum = cksum + word;
+    }
+
+    for (i=0; i<sizeof(ipc_ip4_addr_t); i=i+2)
+    {
+        word = ( (((kal_uint8*)ip_src)[i] << 8 ) & 0xff00 ) + (((kal_uint8*)ip_src)[i+1] & 0xff);
+        cksum = cksum + word;
+    }
+
+    for (i=0; i<sizeof(ipc_ip4_addr_t); i=i+2)
+    {
+        word = ( (((kal_uint8*)ip_dst)[i] << 8 ) & 0xff00 ) + (((kal_uint8*)ip_dst)[i+1] & 0xff);
+        cksum = cksum + word;
+    }
+
+    cksum = cksum + IPC_IPPROTO_UDP +len;
+
+    while ( cksum >> 16 )
+        cksum = ( cksum & 0xffff ) + ( cksum >> 16 );
+
+    return (kal_uint16)~cksum;
+}
+
+
+#endif  // _IPCORE_UDPH_H
+
diff --git a/mcu/middleware/hif/interface/ipfc_export_plugin_dl_filter.h b/mcu/middleware/hif/interface/ipfc_export_plugin_dl_filter.h
new file mode 100644
index 0000000..9f9a387
--- /dev/null
+++ b/mcu/middleware/hif/interface/ipfc_export_plugin_dl_filter.h
@@ -0,0 +1,18 @@
+#ifndef __INC_IPFC_PLUGIN_DL_FILTER
+#define __INC_IPFC_PLUGIN_DL_FILTER
+
+#include "ipfc_export_plugin_dl_filter_type.h"
+#include "kal_public_api.h"
+
+kal_bool ipfc_plugin_dl_filter_enable();
+
+void ipfc_plugin_dl_filter_query_meta_info(void** base, kal_uint16* entry_num, kal_uint32 queue_type);
+void ipfc_plugin_dl_filter_release_meta_entry(kal_uint16 rel_num, kal_uint32 queue_type);
+
+void ipfc_plugin_dl_filter_set_pn_match(kal_uint8 pdn_sim_id, kal_uint16 nc_id, kal_uint8 ipv4, kal_uint8 ipv6);
+
+kal_int32 ipfc_plugin_dl_filter_query_id_by_index(kal_uint32 ipf_index);
+kal_bool ipfc_plugin_dl_filter_take_tlb(void** buff_base, kal_uint32* max_entry_num);
+kal_bool ipfc_plugin_dl_filter_submit_tlb(kal_uint32 filter_num, kal_uint32 v6_unknow_pro_ck);
+
+#endif  //__INC_IPFC_PLUGIN_DL_FILTER
diff --git a/mcu/middleware/hif/interface/ipfc_export_plugin_dl_filter_type.h b/mcu/middleware/hif/interface/ipfc_export_plugin_dl_filter_type.h
new file mode 100644
index 0000000..85f79d4
--- /dev/null
+++ b/mcu/middleware/hif/interface/ipfc_export_plugin_dl_filter_type.h
@@ -0,0 +1,13 @@
+#ifndef __INC_IPFC_PLUGIN_DL_FILTER_TYPE
+#define __INC_IPFC_PLUGIN_DL_FILTER_TYPE
+
+typedef enum _ipfc_dl_filter_queue_type
+{
+    IPFC_META_QUEUE_DL      = 0,
+#if (CUR_GEN >= MD_GEN97)
+    IPFC_META_QUEUE_DL_NR,
+#endif    
+    IPFC_META_QUEUE_MAX,
+} ipfc_dl_filter_queue_type;
+
+#endif  //__INC_IPFC_PLUGIN_DL_FILTER_TYPE
diff --git a/mcu/middleware/hif/interface/ipfc_export_plugin_nat.h b/mcu/middleware/hif/interface/ipfc_export_plugin_nat.h
new file mode 100644
index 0000000..00db360
--- /dev/null
+++ b/mcu/middleware/hif/interface/ipfc_export_plugin_nat.h
@@ -0,0 +1,19 @@
+#ifndef  __INC_IPFC_EXPORT_PLUGIN_NAT
+#define  __INC_IPFC_EXPORT_PLUGIN_NAT
+
+#include "kal_public_api.h"
+
+kal_bool    ipfc_plugin_nat_enable();
+
+void        ipfc_plugin_nat_set_config(kal_uint32 nat_enable);
+kal_uint32  ipfc_plugin_nat_get_config();
+
+void        ipfc_plugin_nat_set_public_ip(kal_uint32 ip_addr);
+kal_uint32  ipfc_plugin_nat_get_public_ip();
+
+void        ipfc_plugin_nat_set_private_ip(kal_uint32 ip_addr, kal_uint32 lan_type);
+kal_uint32  ipfc_plugin_nat_get_private_ip(kal_uint32 lan_type);
+
+kal_uint32  ipfc_plugin_nat_get_rule_num();
+
+#endif
diff --git a/mcu/middleware/hif/interface/lms_api.h b/mcu/middleware/hif/interface/lms_api.h
new file mode 100644
index 0000000..219c6fd
--- /dev/null
+++ b/mcu/middleware/hif/interface/lms_api.h
@@ -0,0 +1,135 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   lms_api.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   LTM Simulation public structure and interface definition.
+ *   It is used as a fork implementation of ltm_if.h.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __INC_LMS_API_H
+#define __INC_LMS_API_H
+
+#include "upcm.h"
+#include "ipcore_upcm_struct.h"
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+typedef void (*upcm_dlvr_dl_sdu_f)(kal_uint32 pdn_id, qbm_gpd* p_head, qbm_gpd* p_tail, kal_uint8 proto_id);
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+void lms_on_downlink(void* p_head, void* p_tail);
+
+void lms_rcv_ul_sdu_meta(kal_uint32 pit_start, kal_uint32 pit_end, LHIF_QUEUE_TYPE queue_type);
+
+void lms_rcv_ul_sdu(ip_type_e ip_type, kal_uint32 pdn_id, qbm_gpd *p_head, qbm_gpd *p_tail, kal_uint8 proto_id);
+
+void lms_rcv_ul_sdu_by_ebi(kal_uint32 ebi, qbm_gpd *p_head, qbm_gpd *p_tail, kal_uint8 proto_id);
+
+void lms_reg_cbk_notify_tick_source(upcm_nofify_lte_tick_f pf_notify);
+
+void lms_reg_cbk_dlvr_dl_sdu(upcm_dlvr_dl_sdu_93_f pf_dlvr_sdu);
+
+void lms_reg_cbk_dlvr_dl_sdu_legacy(upcm_dlvr_dl_sdu_f pf_dlvr_sdu);
+
+void lms_forced_sw_path_by_pdn(kal_uint8 _pdn_id_tmp, kal_bool KAL_TRUE, kal_uint8 _proto_idx);
+
+void lms_forced_sw_path_by_ebi(kal_uint8 _ebi_tmp, kal_bool KAL_TRUE, kal_uint8 _proto_idx);
+
+void lms_forced_sw_path_all(kal_bool option);
+
+#endif /* __INC_LMS_API_H */
diff --git a/mcu/middleware/hif/interface/mbim_common.h b/mcu/middleware/hif/interface/mbim_common.h
new file mode 100644
index 0000000..e4a747a
--- /dev/null
+++ b/mcu/middleware/hif/interface/mbim_common.h
@@ -0,0 +1,13 @@
+#ifndef _MBIM_COMMON_H
+#define _MBIM_COMMON_H
+
+#include "kal_public_api.h"
+
+#if !defined(__MTK_TARGET__) && defined(_MSC_VER) && (_MSC_VER >= 1500)
+#pragma warning( disable : 4214 )
+#endif
+
+
+void mbim_get_host_mac(kal_uint32 netid_if, kal_uint8* mac_addr);
+#endif  // _ETHERCORE_COMMON_H
+
diff --git a/mcu/middleware/hif/interface/mbim_data_path_trace_utmd.json b/mcu/middleware/hif/interface/mbim_data_path_trace_utmd.json
new file mode 100644
index 0000000..caae09a
--- /dev/null
+++ b/mcu/middleware/hif/interface/mbim_data_path_trace_utmd.json
@@ -0,0 +1,361 @@
+{
+  "legacyParameters": {
+    "codeSection": "TCMFORCE", 
+    "l2BufferSetting": "L2_BUFFER_HIF", 
+    "l2MaxArg": 7, 
+    "modemType": "Generic"
+  }, 
+  "module": "MBIM_L2", 
+  "stringTranslationDefs": [], 
+  "startGen": "Legacy",
+  "endGen": "Legacy",
+  "traceClassDefs": [
+    {
+      "MBIM_L": {
+        "debugLevel": "Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "MBIM_M": {
+        "debugLevel": "Medium", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "MBIM_H": {
+        "debugLevel": "High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "MBIM_UH": {
+        "debugLevel": "Ultra-High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "MBIM_RB_DOWNLINK": {
+        "format": "[MBIM] mbim_rb_downlink(): queue_no(%d), did(%xl), pkt_num(%d), seg_num(%d)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_ENUMERATION": {
+        "format": "[MBIM] mbim_rb_downlink(): dl enumeration: i(%d), did(%xl), curr_sit(%xl), hif_type(%d), handled_seg_cnt(%d), seg_num(%d), agg_cnt(%d)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_MULTI_PACKET": {
+        "format": "[MBIM] mbim_rb_downlink(): dl multi-packet transfer in DID_SIT: i(%d), curr_sit(%ul), address(%xl), length(%ul)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_AGG_CONTINUE_1": {
+        "format": "[MBIM] mbim_rb_downlink(): add aggregation msg: i(%d), agg_cnt(%d), header_drb_idx(%d), header_len(%ul), curr_total_len(%ul)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_AGG_CONTINUE_2": {
+        "format": "[MBIM] mbim_rb_downlink(): end to add aggregation msg: i(%d), agg_cnt(%d), payload_len(%ul), header_addr(%xl), sit_cnt(%d), submit_drb_cnt(%d), last_total_len(%ul)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_AGG_FIRST_NDP_1": {
+        "format": "[MBIM] mbim_rb_downlink(): add first NDP header: i(%d), agg_cnt(%d), header_len(%ul), curr_total_len(%ul)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_AGG_FIRST_NDP_2": {
+        "format": "[MBIM] mbim_rb_downlink(): end to add first NDP header: i(%d), payload_len(%ul), ndp_drb_idx(%d), header_len(%ul), sit_cnt(%d), submit_drb_cnt(%d)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_AGG_END_EOL": {
+        "format": "[MBIM] mbim_rb_downlink(): aggregation done: i(%d), trans_cnt(%d), agg_cnt(%d), handled_seg_cnt(%d), submit_drb_cnt(%d)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_RB_UL_ENUMERATION": {
+        "format": "[MBIM] mbim_rb_bulk_out_complete(): ul enumeration: curr_idx(%d), ul_meta(%xl), qtype(%d), net_type(%d), next_idx(%d), end_of_list(%d)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_LOOPBACK_ENUMERATION": {
+        "format": "[MBIM] mbim_rb_process_loopback(): loopback enumeration: curr_idx(%d), ul_meta(%xl), net_type(%d), next_idx(%d), end_of_list(%d)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_LOOPBACK_DL_MSG_INFO": {
+        "format": "[MBIM] mbim_rb_loopback_downlink(): payload_drb_idx(%d), payload_prb(%xl), payload_len(%d)", 
+        "traceClass": "MBIM_M"
+      }
+    }, 
+    {
+      "MBIM_RB_START_DATA_PATH_SUCCESS": {
+        "format": "[MBIM][CLEAR STALL] mbim_on_bulk_stall success: class id = %ul, BULK type =%ul, queue num = %ul, is stall = %ul", 
+        "traceClass": "MBIM_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_START_DATA_PATH_FAIL": {
+        "format": "[MBIM][CLEAR STALL] mbim_on_bulk_stall fail: class id = %ul, BULK type =%ul, queue num = %ul, is stall = %ul", 
+        "traceClass": "MBIM_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_UL_ENUMERATION1": {
+        "format": "[MBIM] mbim_rb_bulk_out_complete(): ul enumeration 1: rel_idx(%ul), start_idx(%ul), end_idx(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_UL_ENUMERATION2": {
+        "format": "[MBIM] mbim_rb_bulk_out_complete(): ul enumeration 2: curr_idx(%ul), xit(%xl), next_idx(%ul), end_of_list(%d)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_UL_DISCARD_ON_INVALID_NTH": {
+        "format": "[MBIM] mbim_rb_cal_header_len(): NTB Header: signature(%ul), header_length(%ul), sequence(%ul),block_length(%ul),fp_index(%ul)", 
+        "traceClass": "MBIM_UH", 
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "MBIM_RB_UL_DISCARD_ON_INVALID_NDP": {
+        "format": "[MBIM] mbim_rb_cal_header_len(): NDP Header: signature(%ul), length(%ul), next_fp_index(%ul),datagrams[0].index(%ul),datagrams[0].length(%ul) ,block_length(%ul)", 
+        "traceClass": "MBIM_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_UL_DISCARD_ON_UNALIGN_NDP": {
+        "format": "[MBIM] mbim_rb_cal_header_len(): NDP Header address: (%ul)", 
+        "traceClass": "MBIM_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_UL_DISCARD_ON_UNALIGN_DATAGRAM": {
+        "format": "[MBIM] mbim_rb_cal_header_len(): DATAGRAM address: (%ul)", 
+        "traceClass": "MBIM_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_UL_DISCARD_ON_INVALID_NDP_1": {
+        "format": "[MBIM] mbim_rb_cal_header_len(): NDP Header: next_fp_index(%ul),datagrams[1].index(%ul),datagrams[1].length(%ul)", 
+        "traceClass": "MBIM_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_UL_ENQUEUE_EMPTY_DID": {
+        "format": "[MBIM][USB_UL] mbim_rb_ul_meta_enqueue_lhif_ul_queue_did(): DO NOT enqueue empty DID. start_idx(%d), end_idx(%d), rel_idx(%d), entry_num(%d)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    },
+	{
+      "MBIM_RB_UL_BULKOUT_COMPLETE": {
+        "format": "[MBIM][USB_UL] mbim_rb_bulk_out_complete(): rel_idx=%ul, start_idx=%ul, end_idx=%ul, curr_net_type=%ul", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_UL_DONE": {
+        "format": "[MBIM] mbim_rb_bulk_out_complete(): ul process done. rel_idx(%ul), start_idx(%ul), end_idx(%ul), total_payload_len(%ul)", 
+        "traceClass": "MBIM_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+	{
+      "MBIM_RB_UL_PROCESS_PACKET": {
+        "format": "[MBIM] mbim_rb_cal_header_len(): ul process IP packet. NTB sequence(%ul), session ID(%ul),packet length(%ul)", 
+        "traceClass": "MBIM_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DOWNLINK": {
+        "format": "[MBIM] mbim_rb_downlink(): queue_no(%d), did(%xl), pkt_num(%d), seg_num(%d)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_ENUMERATION": {
+        "format": "[MBIM] mbim_rb_downlink_auto_header(): dl enumeration: curr_idx(%ul), did(%xl), curr_sit(%xl), hif_type(%d), handled_seg_cnt(%d), seg_num(%d), total_len(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_USB_PACKET": {
+        "format": "[MBIM] mbim_rb_downlink_auto_header(): usb dl packet: curr_idx(%ul), data_addr(%xl), data_len(%ul), is_first_pkt(%d), is_last_pkt(%d), ethc_drb_fh_idx(%d)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_AGG_NO_ROOM_FOR_NEXT": {
+        "format": "[MBIM] mbim_rb_downlink_auto_header(): no room to aggregate next msg: total_len(%ul)+curr_msg_len(%ul)+next_msg_len(%ul)=%ul > dl_max_trans_size(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_ADD_PACKET_HEADER_DRB": {
+        "format": "[MBIM] mbim_rb_add_payload_drb_auto_header(): add packet header drb, is_prb(%d), queue_no(%d), first_idx(%ul), additional_idx(%ul), padding_len(%ul), payload_len(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_AGG_CONTINUE_1": {
+        "format": "[MBIM] mbim_rb_downlink_auto_header(): add aggregation msg(1): curr_msg_len(%ul), curr_payload_len(%ul), ethc_drb_fh_len(%ul), total_len(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_AGG_CONTINUE_2": {
+        "format": "[MBIM] mbim_rb_downlink_auto_header(): add aggregation msg(2): agg_cnt(%d), sit_cnt(%d), submit_drb_cnt(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_ADD_PAYLOAD_DRB_1": {
+        "format": "[MBIM] mbim_rb_add_payload_drb_auto_header(): add payload drb(1), is_prb(%d), queue_no(%d), first_idx(%ul), additional_idx(%ul), p_data(%xl), len(%ul), seg_num(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_ADD_PAYLOAD_DRB_2": {
+        "format": "[MBIM] mbim_rb_add_payload_drb_auto_header(): add payload drb(2), create 1st drb, is_prb(%d), first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), phyAddr(%xl), phyLen(%ul), submit_urb_cnt(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_ADD_PAYLOAD_DRB_3": {
+        "format": "[MBIM] mbim_rb_add_payload_drb_auto_header(): add payload drb(3), 1st drb, set fixed header idx, is_prb(%d), first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), ethc_drb_fh_idx(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_ADD_PAYLOAD_DRB_4": {
+        "format": "[MBIM] mbim_rb_add_payload_drb_auto_header(): add payload drb(4), corss-page case, (%d)drb, first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), phyAddr(%xl), phyLen(%ul), submit_urb_cnt(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_ADD_PAYLOAD_DRB_5": {
+        "format": "[MBIM] mbim_rb_add_payload_drb_auto_header(): add payload drb(5), last drb, set padding len, is_prb(%d), first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), padding_len(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_ADD_PAYLOAD_DRB_6": {
+        "format": "[MBIM] mbim_rb_add_payload_drb_auto_header(): add payload drb(6), set EOT, first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_ADD_HEADERS_BEGIN": {
+        "format": "[MBIM] mbim_rb_add_headers(): payload_len(%ul), is_first_pkt(%d), is_last_pkt(%d), last_padding(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_CAL_HEADER_PADDING": {
+        "format": "[MBIM] mbim_rb_calculate_header_padding(): payload_len(%ul), is_last_pkt(%d), curr_padding(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_CASE1": {
+        "format": "[MBIM] mbim_rb_add_headers(): Case 1", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_CASE2": {
+        "format": "[MBIM] mbim_rb_add_headers(): Case 2: %d, curr_padding(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_DL_ADD_MBIM_PKT_MSG": {
+        "format": "[MBIM] mbim_rb_add_headers(): MBIM_PACKET_MSG added: message_length(%d), data_offset(%ul), data_length(%ul), msg(%xl)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_SUBMIT_DRB": {
+        "format": "[MBIM][USB_DL] mbim_rb_downlink_auto_header(): submit DRB to USBCore: queue_no(%d), submit_urb_cnt(%ul)", 
+        "traceClass": "MBIM_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "MBIM_RB_AH_DL_SUBMIT_DONE": {
+        "format": "[MBIM] mbim_rb_downlink_auto_header(): queue_no(%d), did(%xl), pkt_num(%d), seg_num(%d), submit_urb_cnt(%ul), total_payload_len(%ul)", 
+        "traceClass": "MBIM_H", 
+        "traceHighlightOption": "info"
+      }
+    },
+    {
+      "MBIM_LOOPBACK_DL_SUBMIT_DRB": {
+        "format": "[MBIM] mbim_rb_loopback_downlink(): submit DRB to USBCore: queue_no(%d), submit_urb_cnt(%d)", 
+        "traceClass": "MBIM_M"
+      }
+    }
+  ], 
+  "traceFamily": "L2", 
+  "userModule": "MOD_MBIM"
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/interface/ndpc_common.h b/mcu/middleware/hif/interface/ndpc_common.h
new file mode 100644
index 0000000..9bd67c0
--- /dev/null
+++ b/mcu/middleware/hif/interface/ndpc_common.h
@@ -0,0 +1,58 @@
+/*!
+ *  @file ndpc_common.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides interface of ndpc ( NDP Client )
+ */
+
+#ifndef _NDPC_COMMON_H
+#define _NDPC_COMMON_H
+
+
+/*!
+ *  @brief  ndpc init function
+ */
+void ndpc_init(void);
+
+
+/*!
+ *  @brief  ndpc main function
+ */
+void ndpc_main(ilm_struct* ilm);
+
+
+#endif  // _NDPC_COMMON_H
+
diff --git a/mcu/middleware/hif/interface/nmu_data_path_trace_utmd.json b/mcu/middleware/hif/interface/nmu_data_path_trace_utmd.json
new file mode 100644
index 0000000..3b94f28
--- /dev/null
+++ b/mcu/middleware/hif/interface/nmu_data_path_trace_utmd.json
@@ -0,0 +1,257 @@
+{
+  "legacyParameters": {
+    "codeSection": "TCMFORCE", 
+    "l2BufferSetting": "L2_BUFFER_HIF", 
+    "l2MaxArg": 7, 
+    "modemType": "Generic"
+  }, 
+  "module": "NMU_L2", 
+  "stringTranslationDefs": [], 
+  "startGen": "Legacy",
+  "endGen": "-",
+  "traceClassDefs": [
+    {
+      "NMU_L": {
+        "debugLevel": "Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline", 
+          "Sensitive"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "NMU_M": {
+        "debugLevel": "Medium", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "NMU_H": {
+        "debugLevel": "High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "NMU_UH": {
+        "debugLevel": "Ultra-High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "NMU_SET_PROPERTY": {
+        "format": "[NMU] nmu_set_property(): set property %d, len(%ul).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_GET_PROPERTY": {
+        "format": "[NMU] nmu_get_property(): get property %d, len(%ul).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_HOST_MAC": {
+        "format": "[NMU] nmu_set_host_mac(): set eth%d host_mac to 0-1(%xl) 2-5(%xl)", 
+        "traceClass": "NMU_L"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_HOST_MAC": {
+        "format": "[NMU] nmu_get_host_mac(): get eth%d host_mac to 0-1(%xl) 2-5(%xl)", 
+        "traceClass": "NMU_L"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_GW_MAC": {
+        "format": "[NMU] nmu_set_gateway_mac(): set eth%d gateway_mac to 0-1(%xl) 2-5(%xl)", 
+        "traceClass": "NMU_L"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_GW_MAC": {
+        "format": "[NMU] nmu_get_gateway_mac(): get eth%d gateway_mac to 0-1(%xl) 2-5(%xl)", 
+        "traceClass": "NMU_L"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_ETH_TX_PKT_CNT": {
+        "format": "[NMU] nmu_set_eth_tx_pkt_cnt(): set eth %d tx_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_ADD_ETH_TX_PKT_CNT": {
+        "format": "[NMU] nmu_add_eth_tx_pkt_cnt(): add eth %d tx_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_ETH_TX_PKT_CNT": {
+        "format": "[NMU] nmu_get_eth_tx_pkt_cnt(): get eth %d tx_pkt_cnt u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_ETH_RX_PKT_CNT": {
+        "format": "[NMU] nmu_set_eth_rx_pkt_cnt(): set eth %d rx_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_ADD_ETH_RX_PKT_CNT": {
+        "format": "[NMU] nmu_add_eth_rx_pkt_cnt(): add eth %d rx_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_ETH_RX_PKT_CNT": {
+        "format": "[NMU] nmu_get_eth_rx_pkt_cnt(): get eth %d rx_pkt_cnt u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_ETH_TX_BYTE_CNT": {
+        "format": "[NMU] nmu_set_eth_tx_byte_cnt(): set eth%d tx_byte_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_ADD_ETH_TX_BYTE_CNT": {
+        "format": "[NMU] nmu_add_eth_tx_byte_cnt(): add eth%d tx_byte_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_ETH_TX_BYTE_CNT": {
+        "format": "[NMU] nmu_get_eth_tx_byte_cnt(): get eth%d tx_byte_cnt u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_ETH_RX_BYTE_CNT": {
+        "format": "[NMU] nmu_set_eth_rx_byte_cnt(): set eth%d rx_byte_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_ADD_ETH_RX_BYTE_CNT": {
+        "format": "[NMU] nmu_add_eth_rx_byte_cnt(): add eth%d rx_byte_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_ETH_RX_BYTE_CNT": {
+        "format": "[NMU] nmu_get_eth_rx_byte_cnt(): get eth%d rx_byte_cnt u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_ETH_TX_ERROR_PKT_CNT": {
+        "format": "[NMU] nmu_set_eth_tx_error_pkt_cnt(): set eth%d tx_error_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_ADD_ETH_TX_ERROR_PKT_CNT": {
+        "format": "[NMU] nmu_add_eth_tx_error_pkt_cnt(): add eth%d tx_error_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_ETH_TX_ERROR_PKT_CNT": {
+        "format": "[NMU] nmu_get_eth_tx_error_pkt_cnt(): get eth%d tx_error_pkt_cnt u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_ETH_RX_ERROR_PKT_CNT": {
+        "format": "[NMU] nmu_set_eth_rx_error_pkt_cnt(): set eth%d rx_error_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_ADD_ETH_RX_ERROR_PKT_CNT": {
+        "format": "[NMU] nmu_add_eth_rx_error_pkt_cnt(): add eth%d rx_error_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_ETH_RX_ERROR_PKT_CNT": {
+        "format": "[NMU] nmu_get_eth_rx_error_pkt_cnt(): get eth%d rx_error_pkt_cnt u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_ETH_TX_DROP_PKT_CNT": {
+        "format": "[NMU] nmu_set_eth_tx_drop_pkt_cnt(): set eth%d tx_drop_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_ADD_ETH_TX_DROP_PKT_CNT": {
+        "format": "[NMU] nmu_add_eth_tx_drop_pkt_cnt(): add eth%d tx_drop_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_ETH_TX_DROP_PKT_CNT": {
+        "format": "[NMU] nmu_get_eth_tx_drop_pkt_cnt(): get eth%d tx_drop_pkt_cnt u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_ETH_RX_DROP_PKT_CNT": {
+        "format": "[NMU] nmu_set_eth_rx_drop_pkt_cnt(): set eth%d rx_drop_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_ADD_ETH_RX_DROP_PKT_CNT": {
+        "format": "[NMU] nmu_add_eth_rx_drop_pkt_cnt(): add eth%d rx_drop_pkt_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_ETH_RX_DROP_PKT_CNT": {
+        "format": "[NMU] nmu_get_eth_rx_drop_pkt_cnt(): get eth%d rx_drop_pkt_cnt u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_SET_ETH_RX_FRAME_ALIGN_ERROR_CNT": {
+        "format": "[NMU] nmu_set_eth_rx_frame_align_error_cnt(): set eth%d rx_frame_align_error_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_ADD_ETH_RX_FRAME_ALIGN_ERROR_CNT": {
+        "format": "[NMU] nmu_add_eth_rx_frame_align_error_cnt(): add eth%d rx_frame_align_error_cnt to u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }, 
+    {
+      "NMU_UTIL_GET_ETH_RX_FRAME_ALIGN_ERROR_CNT": {
+        "format": "[NMU] nmu_get_eth_rx_frame_align_error_cnt(): get eth%d rx_frame_align_error_cnt u64(%xl %xl).", 
+        "traceClass": "NMU_H"
+      }
+    }
+  ], 
+  "traceFamily": "L2", 
+  "userModule": "MOD_NMU"
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/interface/rndis_data_path_trace_utmd.json b/mcu/middleware/hif/interface/rndis_data_path_trace_utmd.json
new file mode 100644
index 0000000..79f08b4
--- /dev/null
+++ b/mcu/middleware/hif/interface/rndis_data_path_trace_utmd.json
@@ -0,0 +1,660 @@
+{
+  "legacyParameters": {
+    "codeSection": "TCMFORCE", 
+    "l2BufferSetting": "L2_BUFFER_HIF", 
+    "l2MaxArg": 7, 
+    "modemType": "Generic"
+  }, 
+  "module": "RNDIS_L2", 
+  "stringTranslationDefs": [], 
+  "startGen": "Legacy",
+  "endGen": "-",
+  "traceClassDefs": [
+    {
+      "RNDIS_L": {
+        "debugLevel": "Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "RNDIS_M": {
+        "debugLevel": "Medium", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "RNDIS_H": {
+        "debugLevel": "High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }, 
+    {
+      "RNDIS_UH": {
+        "debugLevel": "Ultra-High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "RNDIS_DL_GPD_ADD_HEADERS_BEGIN": {
+        "format": "[RNDIS] rndis_add_headers(): eth_length(%d) is_first_gpd(%ul) is_last_gpd(%ul) last_padding(%ul) data_ptr(%xl)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_GPD_WITH_VLAN_PRI": {
+        "format": "[RNDIS] rndis_add_headers(): eth_length(%d) with vlan_pri_info: %2xl %2xl %2xl %2xl", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_GPD_PPI_VLAN_PRI_ADDED": {
+        "format": "[RNDIS] rndis_add_headers(): eth_length(%d) add ppi for vid: %3xl pri: %xl", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_GPD_DATA_OFFSET": {
+        "format": "[RNDIS] rndis_add_headers(): data_offset: %d", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_GPD_CASE1": {
+        "format": "[RNDIS] rndis_add_headers(): Case 1, last_padding(%d)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_GPD_CASE2": {
+        "format": "[RNDIS] rndis_add_headers(): Case 2.%d last_padding(%l)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_GPD_ADD_RNDIS_PKT_MSG": {
+        "format": "[RNDIS] rndis_add_headers(): RNDIS_PACKET_MSG added: message_length: %d, data_offset: %ul, data_length: %ul, data_ptr: %xl", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_IOR_ENUMERATION": {
+        "format": "[RNDIS] rndis_on_downlink(): netif_id(%d) curr_ior(%xl) next_ior(%xl) first_ior(%xl)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_GPD_ENUMERATION": {
+        "format": "[RNDIS] rndis_on_downlink(): netif_id(%d) curr_gpd: %xl, next_gpd: %xl, first_gpd: %xl, last_gpd: %xl", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_SPD_SINGLE_PKT_BEGIN": {
+        "format": "[RNDIS] rndis_process_tx_spd(): Begin DL single packet transfer in SPD: spd_entry_num(%d), spd1_header_len(%ul), curr_gpd(%xl)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_SPD_SINGLE_PKT_END": {
+        "format": "[RNDIS] rndis_process_tx_spd(): End DL single packet transfer in SPD: spd_entry_num(%d), total_header_len(%ul), total_data_len(%ul), flush_len(%ul)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_SPD_MULTI_PKT_BEGIN": {
+        "format": "[RNDIS] rndis_process_tx_spd(): Begin DL multi packet transfer in SPD: spd_entry_num(%d), total_payload_len(%ul), curr_gpd(%xl)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_SPD_MULTI_PKT_END": {
+        "format": "[RNDIS] rndis_process_tx_spd(): End DL multi packet transfer in SPD: spd_entry_num(%d), total_header_len(%ul), total_data_len(%ul), flush_len(%ul)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_SPD_ADD_RNDIS_PKT_MSG": {
+        "format": "[RNDIS] rndis_add_headers(): RNDIS_PACKET_MSG added: message_length: %d, data_length: %ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_AGG_CHECK_ROOM_FOR_NEXT": {
+        "format": "[RNDIS] rndis_on_downlink(): checking room for next msg: is_first_gpd: %d, is_last_gpd: %ul, last_padding: %ul, total_len: %ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_AGG_NO_ROOM_FOR_NEXT": {
+        "format": "[RNDIS] rndis_on_downlink(): no room to aggregate next msg: total_len(%d)+curr_msg_len(%ul)+next_msg_len(%ul)=%ul > dl_max_trans_size(%ul)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_ADD_HEADER": {
+        "format": "[RNDIS] rndis_on_downlink(): add RNDIS headers => curr_msg_len: %d total_len: %ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_AGG_END_NORMAL": {
+        "format": "[RNDIS] rndis_on_downlink(): aggregation ends normally, netif_id(%d)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_AGG_END_AND_RESTART": {
+        "format": "[RNDIS] rndis_on_downlink(): end this aggregation and restart it from next msg, netif_id(%d)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_SUBMIT_IOR_NG": {
+        "format": "[RNDIS] rndis_on_downlink(): submit IOR, dl_gpd_num=%d, dl_pkt_num=%ul to usbcore because usb_state is not ready. ior=%xl, next_ior=%xl, first_gpd=%xl, last_gpd=%xl", 
+        "traceClass": "RNDIS_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_START_DP_CONNECTED": {
+        "format": "[RNDIS] set start data path indicate CONNECTED, netif_id(%d)", 
+        "traceClass": "RNDIS_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_START_DP_RETRY_TIMEOUT": {
+        "format": "[RNDIS] start data path retry timer callback, netif_id(%d)", 
+        "traceClass": "RNDIS_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_START_DP_RETRY_TIMER": {
+        "format": "[RNDIS] set start data path retry timer, netif_id(%d)", 
+        "traceClass": "RNDIS_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_PPI_IN_FIRST_BUF": {
+        "format": "[RNDIS] PPI case 1, ppi_offset: %d, ppi_length: %ul <= 1st buf length: %ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_PPI_RECORD": {
+        "format": "[RNDIS] PPI size(%d), type(%ul), offset(%ul)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_PPI_MATCHED": {
+        "format": "[RNDIS] PPI matched, ppi_length(%d)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_PPI_VLAN_PRI_FOUND": {
+        "format": "[RNDIS] PPI vlan_pri_info: %d, vid: %3xl, pri:%xl", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_PPI_NOT_MATCHED": {
+        "format": "[RNDIS] PPI NOT matched, ppi_type(%d)", 
+        "traceClass": "RNDIS_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_PPI_CROSS_BUF": {
+        "format": "[RNDIS] PPI case 2, ppi_offset: %d, ppi_length: %ul > 1st buf length: %ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_STRIP_PKT_MSG": {
+        "format": "[RNDIS] rndis_strip_off_headers(): msg_length:%d, data_offset:%ul, gpd:%xl", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_STRIP_PADDING_BD_CASE": {
+        "format": "[RNDIS] rndis_strip_off_headers(): BD list case, strip off pendding bytes:%d, curr desc is EOL:%ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_FREE_PADDING_BD": {
+        "format": "[RNDIS] rndis_strip_off_headers(): free padding BD, data_len:%d, is_eol:%ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_STRIP_PADDING_GPD_CASE": {
+        "format": "[RNDIS] rndis_strip_off_headers(): GPD case, strip off pendding bytes, MSG length:%d Previous GPD data length:%ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_RELOAD_BY_START_DATA_PATH_REQ": {
+        "format": "[RNDIS] rndis_reload_ul_buffers() called by MSG_ID_RNDIS_START_DATA_PATH_REQ, netif_id(%d)", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_GPD_SUBMITTED": {
+        "format": "[RNDIS] UL GPD submitted, in HIF: %d", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_BULKOUT_EMPTY_IOR": {
+        "format": "[RNDIS] rndis_on_bulk_out_complete(): empty IOR => drop it, num_gpd(%d)", 
+        "traceClass": "RNDIS_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_BUF_DOWNLINK": {
+        "format": "[RNDIS] rndis_buf_downlink(): queue_no(%d), payload(%xl), payload_len(%d)", 
+        "traceClass": "RNDIS_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_BUF_DL_MSG_INFO": {
+        "format": "[RNDIS] rndis_buf_downlink(): header_drb_idx(%d), payload_drb_idx(%d), header_addr(%xl), msg_len(%d), payload_prb(%xl), payload_len(%d)", 
+        "traceClass": "RNDIS_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_BUF_DL_SUBMIT_DRB": {
+        "format": "[RNDIS] rndis_buf_downlink(): submit DRB to USBCore: queue_no(%d), submit_urb_cnt(%ul)", 
+        "traceClass": "RNDIS_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DOWNLINK": {
+        "format": "[RNDIS] rndis_rb_downlink(): queue_no(%d), did(%xl), pkt_num(%d), seg_num(%d)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_ENUMERATION": {
+        "format": "[RNDIS] rndis_rb_downlink(): dl enumeration: curr_idx(%d), did(%xl), curr_sit(%xl), hif_type(%d), handled_seg_cnt(%d), seg_num(%d), total_len(%d)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_USB_PACKET": {
+        "format": "[RNDIS] rndis_rb_downlink(): usb dl packet: curr_idx(%d), data_addr(%xl), data_len(%ul), is_first_pkt(%d), is_last_pkt(%d), last_padding(%d), ethc_drb_fh_idx(%d)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_AGG_NO_ROOM_FOR_NEXT": {
+        "format": "[RNDIS] rndis_rb_downlink(): no room to aggregate next msg: total_len(%d)+curr_msg_len(%ul)+next_msg_len(%ul)=%ul > dl_max_trans_size(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_AGG_CONTINUE_1": {
+        "format": "[RNDIS] rndis_rb_downlink(): add aggregation msg(1): header_drb_idx(%d), header_addr(%xl), curr_msg_len(%ul), curr_payload_len(%ul), ethc_drb_fh_len(%ul), total_len(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_AGG_CONTINUE_2": {
+        "format": "[RNDIS] rndis_rb_downlink(): add aggregation msg(2): header_drb_idx(%d), agg_cnt(%d), sit_cnt(%d), submit_drb_cnt(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_ADD_PAYLOAD_DRB_1": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb(): add payload drb(1), queue_no(%d), first_idx(%ul), additional_idx(%ul), p_data(%xl), len(%ul), seg_num(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_ADD_PAYLOAD_DRB_2": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb(): add payload drb(2), create 1st prb, first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), phyAddr(%xl), phyLen(%ul), submit_urb_cnt(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_ADD_PAYLOAD_DRB_3": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb(): add payload drb(3), 1st prb, set fixed header idx, first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), ethc_drb_fh_idx(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_ADD_PAYLOAD_DRB_4": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb(): add payload drb(4), corss-page case, 2nd prb, first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), phyAddr(%xl), phyLen(%ul), submit_urb_cnt(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_ADD_PAYLOAD_DRB_5": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb(): add payload drb(5), set EOT, first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_BUF_AH_DOWNLINK": {
+        "format": "[RNDIS] rndis_buf_downlink_auto_header(): queue_no(%d), payload(%xl), payload_len(%d)", 
+        "traceClass": "RNDIS_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_BUF_AH_DL_MSG_INFO": {
+        "format": "[RNDIS] rndis_buf_downlink_auto_header(): payload_drb_idx(%d), payload_prb(%xl), payload_len(%d)", 
+        "traceClass": "RNDIS_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_BUF_AH_DL_SUBMIT_DRB": {
+        "format": "[RNDIS] rndis_buf_downlink_auto_header(): submit DRB to USBCore: queue_no(%d), submit_urb_cnt(%ul)", 
+        "traceClass": "RNDIS_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DOWNLINK": {
+        "format": "[RNDIS] rndis_rb_downlink_auto_header(): queue_no(%d), did(%xl), pkt_num(%d), seg_num(%d)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_ENUMERATION": {
+        "format": "[RNDIS] rndis_rb_downlink_auto_header(): dl enumeration: curr_idx(%ul), did(%xl), curr_sit(%xl), hif_type(%d), handled_seg_cnt(%d), seg_num(%d), total_len(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_USB_PACKET": {
+        "format": "[RNDIS] rndis_rb_downlink_auto_header(): usb dl packet: curr_idx(%ul), data_addr(%xl), data_len(%ul), is_first_pkt(%d), is_last_pkt(%d), ethc_drb_fh_idx(%d)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_AGG_NO_ROOM_FOR_NEXT": {
+        "format": "[RNDIS] rndis_rb_downlink_auto_header(): no room to aggregate next msg: total_len(%ul)+curr_msg_len(%ul)+next_msg_len(%ul)=%ul > dl_max_trans_size(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_ADD_PACKET_HEADER_DRB": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb_auto_header(): add packet header drb, is_prb(%d), queue_no(%d), first_idx(%ul), additional_idx(%ul), padding_len(%ul), payload_len(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_AGG_CONTINUE_1": {
+        "format": "[RNDIS] rndis_rb_downlink_auto_header(): add aggregation msg(1): curr_msg_len(%ul), curr_payload_len(%ul), ethc_drb_fh_len(%ul), total_len(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_AGG_CONTINUE_2": {
+        "format": "[RNDIS] rndis_rb_downlink_auto_header(): add aggregation msg(2): agg_cnt(%d), sit_cnt(%d), submit_drb_cnt(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_ADD_PAYLOAD_DRB_1": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb_auto_header(): add payload drb(1), is_prb(%d), queue_no(%d), first_idx(%ul), additional_idx(%ul), p_data(%xl), len(%ul), seg_num(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_ADD_PAYLOAD_DRB_2": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb_auto_header(): add payload drb(2), create 1st drb, is_prb(%d), first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), phyAddr(%xl), phyLen(%ul), submit_urb_cnt(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_ADD_PAYLOAD_DRB_3": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb_auto_header(): add payload drb(3), 1st drb, set fixed header idx, is_prb(%d), first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), ethc_drb_fh_idx(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_ADD_PAYLOAD_DRB_4": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb_auto_header(): add payload drb(4), corss-page case, (%d)drb, first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), phyAddr(%xl), phyLen(%ul), submit_urb_cnt(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_ADD_PAYLOAD_DRB_5": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb_auto_header(): add payload drb(5), last drb, set padding len, is_prb(%d), first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul), padding_len(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_ADD_PAYLOAD_DRB_6": {
+        "format": "[RNDIS] rndis_rb_add_payload_drb_auto_header(): add payload drb(6), set EOT, first_idx(%ul), additional_idx(%ul), payload_drb_idx(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_ADD_HEADERS_BEGIN": {
+        "format": "[RNDIS] rndis_rb_add_headers(): payload_len(%ul), is_first_pkt(%d), is_last_pkt(%d), last_padding(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_CAL_HEADER_PADDING": {
+        "format": "[RNDIS] rndis_rb_calculate_header_padding(): payload_len(%ul), is_last_pkt(%d), curr_padding(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_CASE1": {
+        "format": "[RNDIS] rndis_rb_add_headers(): Case 1", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_CASE2": {
+        "format": "[RNDIS] rndis_rb_add_headers(): Case 2: %d, curr_padding(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_ADD_RNDIS_PKT_MSG": {
+        "format": "[RNDIS] rndis_rb_add_headers(): RNDIS_PACKET_MSG added: message_length(%d), data_offset(%ul), data_length(%ul), msg(%xl)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_UL_ENUMERATION1": {
+        "format": "[RNDIS] rndis_rb_bulk_out_complete(): ul enumeration 1: rel_idx(%ul), start_idx(%ul), end_idx(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_UL_ENUMERATION2": {
+        "format": "[RNDIS] rndis_rb_bulk_out_complete(): ul enumeration 2: curr_idx(%ul), xit(%xl), next_idx(%ul), end_of_list(%d)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_UL_DONE": {
+        "format": "[RNDIS] rndis_rb_bulk_out_complete(): ul process done. rel_idx(%ul), start_idx(%ul), end_idx(%ul), total_payload_len(%ul)", 
+        "traceClass": "RNDIS_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_UL_STRIP_PKT_MSG": {
+        "format": "[RNDIS] rndis_rb_strip_off_headers(): msg_length(%d), data_length(%ul), data_offset(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_UL_CAL_HEADER_LEN": {
+        "format": "[RNDIS] rndis_rb_cal_header_len(): msg_length(%d), data_length(%ul), data_offset(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_DL_SUBMIT_IOR": {
+        "format": "[RNDIS][USB_DL] rndis_on_downlink(): submit IOR, dl_gpd_num=%d, dl_pkt_num=%ul to usbcore. ior=%xl, next_ior=%xl, first_gpd=%xl, last_gpd=%xl", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_ALLOC_GPD": {
+        "format": "[RNDIS][USB_UL_RELOAD] rndis_reload_ul_buffers(): usb_ul_gpd_want_allocate=%d, usb_ul_gpd_to_allocate=%ul, usb_ul_gpd_in_hif=%ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_UL_BULKOUT_COMPLETE": {
+        "format": "[RNDIS][USB_UL] rndis_on_bulk_out_complete(): usb_ul_gpd_received=%d, usb_ul_gpd_in_hif=%ul", 
+        "traceClass": "RNDIS_M", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_DL_SUBMIT_DRB": {
+        "format": "[RNDIS][USB_DL] rndis_rb_downlink(): submit DRB to USBCore: queue_no(%d), submit_urb_cnt(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_SUBMIT_DRB": {
+        "format": "[RNDIS][USB_DL] rndis_rb_downlink_auto_header(): submit DRB to USBCore: queue_no(%d), submit_urb_cnt(%ul)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_AH_DL_SUBMIT_DONE": {
+        "format": "[RNDIS] rndis_rb_downlink_auto_header(): queue_no(%d), did(%xl), pkt_num(%d), seg_num(%d), submit_urb_cnt(%ul), total_payload_len(%ul)", 
+        "traceClass": "RNDIS_H", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_UL_BULKOUT_COMPLETE": {
+        "format": "[RNDIS][USB_UL] rndis_rb_bulk_out_complete(): usb_ul_pkt_cnt=%ul, usb_ul_byte_cnt=%ul, usb_ul_error_pkt_cnt=%ul, usb_ul_drop_pkt_cnt=%ul", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_START_DATA_PATH_SUCCESS": {
+        "format": "[RNDIS][CLEAR STALL] rndis_on_bulk_stall success: class id = %ul, BULK type =%ul, queue num = %ul, is stall = %ul", 
+        "traceClass": "RNDIS_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_START_DATA_PATH_FAIL": {
+        "format": "[RNDIS][CLEAR STALL] rndis_on_bulk_stall fail: class id = %ul, BULK type =%ul, queue num = %ul, is stall = %ul", 
+        "traceClass": "RNDIS_UH", 
+        "traceHighlightOption": "info"
+      }
+    }, 
+    {
+      "RNDIS_RB_UL_ENQUEUE_EMPTY_DID": {
+        "format": "[RNDIS][USB_UL] rndis_rb_ul_meta_enqueue_lhif_ul_queue_did(): DO NOT enqueue empty DID. start_idx(%d), end_idx(%d), rel_idx(%d), entry_num(%d)", 
+        "traceClass": "RNDIS_L", 
+        "traceHighlightOption": "info"
+      }
+    }
+  ], 
+  "traceFamily": "L2", 
+  "userModule": "MOD_RNDIS"
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/interface/ufpm_usbclass.h b/mcu/middleware/hif/interface/ufpm_usbclass.h
new file mode 100644
index 0000000..b30d109
--- /dev/null
+++ b/mcu/middleware/hif/interface/ufpm_usbclass.h
@@ -0,0 +1,69 @@
+/*!
+ *  @file usbidle_main.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main definitions of usbcore
+ */
+
+#ifndef _UFPM_USBCLASS_H
+#define _UFPM_USBCLASS_H
+
+#include "ufpm_usb_struct.h"
+
+/***************************************************
+ * UFPM Function Common API
+ ***************************************************/
+void usbc_direct_class_device_submit_control_request(ufpm_send_ap_ep0_msg_t* ep0_rsp_ptr, kal_bool isIndication);
+
+
+/***************************************************
+ * UFPM Tethering RNDIS API
+ ***************************************************/
+void ufpm_query_tethering_activation_info(tethering_activate_meta_info_t* tethering_meta_info);
+
+void ufpm_set_tethering_deactivation_info(tethering_deactivate_meta_info_t* deactInfo);
+
+kal_bool ufpm_dpfm_lan_dev_register(kal_uint32 netif_id, kal_uint8 net_type);
+
+/***************************************************
+ * UFPM LOGGING ACM API
+ ***************************************************/
+void ufpm_query_logging_activation_info(logging_activate_meta_info_t* logging_meta_info);
+
+void ufpm_set_logging_deactivation_info(logging_deactivate_meta_info_t* deactInfo);
+
+#endif  // _UFPM_USBCLASS_H
+
diff --git a/mcu/middleware/hif/interface/ufpm_usbcore.h b/mcu/middleware/hif/interface/ufpm_usbcore.h
new file mode 100644
index 0000000..3ff4829
--- /dev/null
+++ b/mcu/middleware/hif/interface/ufpm_usbcore.h
@@ -0,0 +1,59 @@
+/*!
+ *  @file usbidle_main.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main definitions of usbcore
+ */
+
+#ifndef _UFPM_USBCORE_H
+#define _UFPM_USBCORE_H
+
+#include "hifusb_qmu.h"
+#include "ufpm_usb_struct.h"
+
+kal_bool ufpm_init(void);
+
+void ufpm_on_ilm(ilm_struct *current_ilm);
+
+kal_bool ufpm_check_func_support(ufpm_func_mode_e func_mode);
+
+kal_uint8 ufpm_query_ep_logic_to_phy(hif_queue_type_e queue_type, kal_uint8 logic_queue_no);
+
+void ufpm_set_control_request(ufpm_send_ap_ep0_msg_t* ep0_rsp_ptr, kal_bool isIndication);
+
+void ufpm_redirect_l4_ilm(ilm_struct *ilm);
+
+#endif  // _UFPM_USBCORE_H
diff --git a/mcu/middleware/hif/interface/usbcore_class_device.h b/mcu/middleware/hif/interface/usbcore_class_device.h
new file mode 100644
index 0000000..4c0d208
--- /dev/null
+++ b/mcu/middleware/hif/interface/usbcore_class_device.h
@@ -0,0 +1,351 @@
+/*!
+ *  @file usbcore_class_device.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.2
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides application interface of usbcore for class device
+ */
+
+#ifndef _USBCORE_CLASS_DEVICE_H
+#define _USBCORE_CLASS_DEVICE_H
+
+#include "usbcore_common.h"
+#include "usbcore_usbstd.h"
+#include "usbc_custom.h"
+
+#define USBC_USBCLASS_DEVICE_DRV_DRB_MACRO(HIFUSB_DRB_MACRO, _class_device_id, _q, ...)       (HIFUSB_DRB_MACRO(usbc_class_device_get_phy_queue_num(_class_device_id, _q), __VA_ARGS__))
+
+/*!
+ *  @brief usbc_class_device_info_t describe register information of a
+ *         generic usb class device
+ */
+typedef struct _usbc_class_device_info {
+
+    /*!
+     *  @brief class type of this device
+     */
+    usb_class_type_e        class_type;
+    /*!
+     *  @brief total pipes of this device
+     */
+    kal_uint8               total_pipes;
+    /*!
+     *  @brief reserve for 4 bytes alignment
+     */
+    kal_uint8               reserve[2];
+    /*!
+     *  @brief per class device context
+     */
+    void                   *class_device_context;
+    /*!
+     *  @brief each pipe type of this device
+     */
+    usbc_pipe_type_e        pipe_type[MAX_USBCORE_CLASS_PIPE_NUM];
+    /*!
+     *  @brief callback function while usb state changed.
+     *         Running Level: TASK
+     */
+    void                    (*notify_usb_state)(kal_uint8 class_device_id, usbc_usb_state_e state);
+    /*!
+     *  @brief callback function while usb speed changed.
+     *         Running Level: TASK
+     */
+    void                    (*notify_usb_speed)(kal_uint8 class_device_id, usbc_usb_speed_e speed);
+    /*!
+     *  @brief callback function while control tranfer for this device
+     *         is received
+     *         Running Level: TASK
+     */
+    void                    (*notify_control_setup_packet)(kal_uint8 class_device_id, usbc_setup_packet_t* packet);
+    /*!
+     *  @brief callback function while control tranfer is complete
+     *         Running Level: TASK
+     */
+    void                    (*notify_control_complete)(kal_uint8 class_device_id);
+    /*!
+     *  @brief callback function while interface alternate setting is set
+     *         Running Level: TASK
+     */
+    void                    (*notify_alternate_setting)(kal_uint8 class_device_id, usbc_interface_type_e inteface, kal_uint8 alternate_setting);
+    /*!
+     *  @brief callback function while each pipe tranfer is complete (GPD/SPD)
+     *         Running Level: TASK
+     */
+    void                    (*notify_pipe_complete[MAX_USBCORE_CLASS_PIPE_NUM])(kal_uint8 class_device_id, usbc_io_request_t* io_request);
+    /*!
+     *  @brief callback function while each pipe tranfer is complete (UL META/DRB)
+     *         Running Level: TASK
+     */
+    void                    (*notify_rb_pipe_complete[MAX_USBCORE_CLASS_PIPE_NUM])(kal_uint8 class_device_id, kal_uint32 start_idx, kal_uint32 end_idx, kal_uint32 rel_idx);
+    /*!
+     *  @brief callback function to indicate pipe is stall or not
+     *         Running Level: TASK
+     */
+    void                    (*notify_pipe_stall[MAX_USBCORE_CLASS_PIPE_NUM])(kal_uint8 class_device_id, kal_bool stall);
+    /*!
+     *  @brief callback function to notify a function enable/disable function remote wakeup
+     */
+    void                    (*notify_func_wk_ability)(kal_uint8 class_device_id, kal_bool ability);
+    /*!
+     *  @brief callback function to query the status of class device
+     */
+    kal_uint16              (*query_func_wk_status)(kal_uint8 class_device_id);
+} usbc_class_device_info_t;
+
+typedef struct _usbc_class_device_esl_connect_parm {
+    LOCAL_PARA_HDR
+    kal_uint8   class_device_id;
+} usbc_class_device_esl_connect_parm;
+
+/*!
+ *  @brief  register new usb class device to usbcore
+ *          Running Level: TASK INIT/TASK 
+ *  @param  class_device_id  device instance id to register
+ *  @param  device_info class device information used to register
+ *  @param  class_device_id device instance id obtained while register 
+ *  @return new instance of usb class device if success, NULL if fail
+ */
+usbc_class_device_instance_t* usbc_class_device_register(kal_uint8 class_device_id, usbc_class_device_info_t* device_info);
+
+
+/*!
+ *  @brief  deregister usb class device from usbcore
+ *          Running Level: TASK INIT/TASK
+ *  @param  class_device_id  device instance id obtained while register
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_deregister(kal_uint8 class_device_id);
+
+/*!
+ *  @brief  retrieve per usb class device context registed in usbc_class_device_register()
+ *          Running Level: ANY
+ *  @param  class_device_id  device instance id obtained while register
+ *  @return per usb class device context
+ */
+void* usbc_class_device_get_context(kal_uint8 class_device_id);
+
+/*!
+ *  @brief  submit control transfer request to usbcore
+ *          Running Level: TASK
+ *  @param  class_device_id     class device id obtained while register
+ *  @param  buffer              pointer to byte array to send or receive data
+ *  @param  length              length of buffer to send, or to receive
+ *  @param  type                send or receive or stall
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_submit_control_request(kal_uint8 class_device_id, kal_uint8* buffer, kal_uint32 length, usbc_control_request_type_e type);
+
+
+/*!
+ *  @brief  submit io request to usbcore
+ *          Running Level: TASK
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            QMU queue no
+ *  @param  io_request          io request submit to usbcore
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_submit_io_request(kal_uint8 class_device_id, kal_uint8 queue_no, usbc_io_request_t* io_request);
+
+/*!
+ *  @brief  submit io request to usbcore with more configurations
+ *          Running Level: TASK
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            QMU queue no
+ *  @param  io_request          io request submit to usbcore
+ *  @param  info                configurations apply to the requests
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_submit_io_request_ext(kal_uint8 class_device_id, kal_uint8 queue_no, usbc_io_request_t *io_request, usbc_io_ext_info_t *info);
+
+/*!
+ *  @brief  flush io request already submitted to usbcore
+ *          Running Level: TASK
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            QMU queue no
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_flush_io_request(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+
+/*!
+ *  @brief  flush DRB/XIT queue
+ *          Running Level: TASK
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            QMU queue no
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_flush_rb(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+
+/*!
+ *  @brief  change notify complete function already registered to usbcore
+ *          Running Level: TASK
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            QMU queue no
+ *  @param  notify_complete     notify complete callback function
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_change_notify_complete(kal_uint8 class_device_id, kal_uint8 queue_no, void (*notify_complete)(kal_uint8 class_device_id, usbc_io_request_t* io_request));
+
+
+/*!
+ *  @brief  ask usbcore to detach from bus
+ *          Running Level: TASK
+ *  @param  class_device_id     device instance id obtained while register
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_set_hif_disconnect(kal_uint8 class_device_id);
+
+/*!
+ *  @brief  submit DRB to usbcore
+ *          Running Level: TASK
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            QMU queue no
+ *  @param  submit_drb_count    number of DRBs to be submitted
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_submit_drb(kal_uint8 class_device_id, kal_uint8 queue_no,kal_uint32 submit_drb_count);
+
+kal_bool usbc_class_device_rst_ep_pipe(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+
+kal_bool usbc_class_device_set_header_rule(kal_uint32 header_rule, void *ph_addr, void *xh_addr, kal_uint16 ph_length, kal_uint16 xh_length);
+
+void
+usbc_resource_reset(void);
+
+usbc_interface_info_t*
+usbc_get_interface_number(kal_uint8 config_num, kal_uint8 *if_num_p);
+
+kal_uint8
+usbc_get_string_number(void *string);
+
+usbc_interface_association_descriptor_t*
+usbc_get_iad_number(kal_uint8 config_num, kal_uint8 *iad_num_p);
+
+usbc_endpoint_info_t*
+usbc_get_endpoint_tx_number(kal_uint8 config_num, kal_uint8 *tx_ep_num_p);
+
+usbc_endpoint_info_t*
+usbc_get_endpoint_rx_number(kal_uint8 config_num, kal_uint8 *rx_ep_num_p);
+
+
+/*!
+ *  @brief  ask usbcore to send function remote wakeup notification to the host
+ *          Running Level: TASK
+ *  @param  class_device_id     device instance id obtained while register
+ *  @return KAL_TRUE if success, otherwise KAL_FALSE if fail
+ */
+kal_bool usbc_class_device_func_remote_wk(kal_uint8 class_device_id);
+
+/*!
+ *  @brief  the handler for function remote wakeup notification timeout
+ *  @param  class_device_id     device instance id obtained while register
+ *  @return
+ */
+void usbc_wk_notify_timeout();
+
+/*!
+ *  @brief  set timer for sending function remote wakeup notification
+ *  @param  class_device_id     device instance id obtained while register
+ *  @return
+ */
+void usbc_set_wk_notify_timer(kal_uint8 class_device_id);
+
+/*!
+ *  @brief  The netwotk USB function uses the API to notify L4 that it has been in suspending states
+ *  @param  class_device_id     device instance id obtained while register
+ *  @parm   suspend             the network USB funtion is going to suspending or resuming
+ *  @param  remote_wakeup       Is remote wakeup of the suspended function enabled
+ *  @return
+ */
+void usbc_class_device_netifx_suspend_notify(kal_uint8 class_device_id, kal_bool suspend, kal_bool remote_wakeup);
+
+kal_bool usbc_class_device_check_ep_empty(kal_uint8 class_device_id, kal_uint8 queue_no);
+/*!
+ *  @brief  Get physical USB queue number
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            queue number maintained in USBCLASS internal structure
+ *  @return                     physical USB queuen umber
+ */
+kal_uint8 usbc_class_device_get_phy_queue_num(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+/*!
+ *  @brief  halt USB queue
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            queue number maintained in USBCLASS internal structure
+ *  @return
+ */
+kal_bool usbc_class_device_set_stall(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+/*!
+ *  @brief  resume usb queue
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            queue number maintained in USBCLASS internal structure
+ *  @return
+ */
+kal_bool usbc_class_device_clear_stall(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+/*!
+ *  @brief  Start USB ULQ/DLQ
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            queue number maintained in USBCLASS internal structure
+ *  @return
+ */
+kal_bool usbc_class_device_start_data_q(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+/*!
+ *  @brief  Handle Invalid EP0
+ *  @return
+ */
+void usbc_class_device_stall_ep0(void);
+
+/*!
+ * @brief restore GPDs from SW to HW
+ * @return T or F
+ */
+kal_bool usbc_class_device_restore_gpd_pwrsave(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+usb_class_owner_e usbc_class_get_class_device_owner(kal_uint8 class_device);
+/*!
+ *  @brief  Flush RX EP with GPD re-submit
+ *  @param  class_device_id     device instance id obtained while register
+ *  @param  queue_no            queue number maintained in USBCLASS internal structure
+ *  @return
+ */
+kal_bool usbc_class_device_flush_rx_io_with_submit(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+#endif  // _USBCORE_CLASS_DEVICE_H
+
diff --git a/mcu/middleware/hif/interface/usbcore_common.h b/mcu/middleware/hif/interface/usbcore_common.h
new file mode 100644
index 0000000..a7eeb26
--- /dev/null
+++ b/mcu/middleware/hif/interface/usbcore_common.h
@@ -0,0 +1,682 @@
+/*!
+ *  @file usbcore_common.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides common definitions of usbcore
+ */
+
+#ifndef _USBCORE_COMMON_H
+#define _USBCORE_COMMON_H
+
+#include "qmu_bm.h"
+#include "usbc_custom_def.h"
+#include "usbc_custom.h"
+#include "hif_usb.h"
+#include "usbcore_usbstd.h"
+
+
+/*!
+ * @brief Swap the pointed-to 16-bit quantity from USB byte order
+ *        (little-endian) to host byte order, in an alignment-safe manner.
+ * @param _pData pointer (as unsigned char*)
+ * @return quantity in host byte order
+ */
+#define USBC_EF16P(_pData)  ((*(_pData+1) << 8) | *(_pData))
+
+
+/*!
+ * @brief Swap the pointed-to 24-bit quantity from USB byte order
+ *        (little-endian) to host byte order, in an alignment-safe manner.
+ * @param _pData pointer (as unsigned char*)
+ * @return quantity in host byte order
+ */
+#define USBC_EF24P(_pData)  ((*(_pData+2) << 16) | (*(_pData+1) << 8) | *(_pData))
+
+
+/*!
+ * @brief Swap the pointed-to 32-bit quantity from USB byte order
+ *        (little-endian) to host byte order, in an alignment-safe manner.
+ * @param _pData pointer (as unsigned char*)
+ * @return quantity in host byte order
+ */
+#define USBC_EF32P(_pData)  ((*(_pData+3) << 24) | (*(_pData+2) << 16) | (*(_pData+1) << 8) | *(_pData))
+
+
+/*!
+ *  @brief MAX_USBCORE_CLASS_INTERFACE_NUM defines the maximum value of
+ *         interface per class device that usbcore can support
+ */
+#define MAX_USBCORE_CLASS_INTERFACE_NUM     4
+
+
+/*!
+ *  @brief MAX_USBCORE_CLASS_PIPE_NUM defines the maximum value of pipe
+ *         per class device that usbcore can support
+ */
+#define MAX_USBCORE_CLASS_PIPE_NUM          8
+
+
+/*!
+ *  @brief MAX_USBCORE_CONFIG_NUM defines the maximum value of configuration
+ *         usbcore can handle
+ */
+#define MAX_USBCORE_CONFIG_NUM                      8
+
+
+/*!
+ *  @brief MAX_USBCORE_INTERFACE_NUM defines the maximum value of class
+ *         interface usbcore can handle
+ */
+#define MAX_USBCORE_INTERFACE_NUM                   16
+
+
+/*!
+ *  @brief MAX_USBCORE_QUEUE_NUM defines the maximum value of QMU queues
+ *         that usbcore can support
+ */
+#define MAX_USBCORE_QUEUE_NUM                       16
+
+
+/*!
+ *  @brief MAX_USBCORE_STRING_DESCRIPTOR_NUM defines the maximum value of string
+ *         descriptors usbcore can handle
+ */
+#define MAX_USBCORE_STRING_DESCRIPTOR_NUM           254
+
+
+/*!
+ *  @brief MAX_USBCORE_CONTROL_REQUEST_BUFFER_SIZE defines the maximum value
+ *         of control request buffer
+ */
+#define MAX_USBCORE_CONTROL_REQUEST_BUFFER_SIZE     64
+
+
+
+
+
+
+
+#define MAX_USBCORE_CLASS_EPDESC_LENGTH             12
+#define MAX_USBCORE_IFDESC_LENGTH                  258  // this will change depends on different class interface, refer to 6280
+#define MAX_USBCORE_EPNUM_PER_IF                     3
+#define MAX_USBCORE_IAD_NUM                          8
+
+
+
+/*!
+ *  @brief USBC_USB11_MAX_PACKET_SIZE define maximum packet size in USB SPEED 1.1
+ */
+#define USBC_USB11_MAX_PACKET_SIZE          64
+
+
+/*!
+ *  @brief USBC_USB20_MAX_PACKET_SIZE define maximum packet size in USB SPEED 2.0
+ */
+#define USBC_USB20_MAX_PACKET_SIZE          512
+
+
+/*!
+ *  @brief USBC_USB30_MAX_PACKET_SIZE define maximum packet size in USB SPEED 3.0
+ */
+#define USBC_USB30_MAX_PACKET_SIZE          1024
+
+
+
+/*!
+ *  @brief usbc_usb_state_e enumerate possible states of usb device
+ *  @param USBC_USB_STATE_MIN           pseudo state
+ *  @param USBC_USB_STATE_ATTACHING     start attaching to usb bus
+ *  @param USBC_USB_STATE_ATTACHED      attach to usb bus already
+ *  @param USBC_USB_STATE_DETACHING     start detaching from usb bus
+ *  @param USBC_USB_STATE_DETACHED      detach from usb bus already
+ *  @param USBC_USB_STATE_SUSPENDING    start suspending
+ *  @param USBC_USB_STATE_SUSPENDED     suspend already
+ *  @param USBC_USB_STATE_RESUME        recevie usb resume signal
+ *  @param USBC_USB_STATE_RESET         recevie usb bus reset
+ *  @param USBC_USB_STATE_MAX           pseudo state
+ */
+typedef enum _usbc_usb_state {
+    USBC_USB_STATE_MIN                  = 0,
+    USBC_USB_STATE_ATTACHING            = 1,
+    USBC_USB_STATE_ATTACHED             = 2,
+    USBC_USB_STATE_DETACHING            = 3,
+    USBC_USB_STATE_DETACHED             = 4,
+    USBC_USB_STATE_SUSPENDING           = 5,
+    USBC_USB_STATE_SUSPENDED            = 6,
+    USBC_USB_STATE_RESUME               = 7,
+    USBC_USB_STATE_RESET                = 8,
+    USBC_USB_STATE_PWRDOWN                = 9,
+    USBC_USB_STATE_MAX                  = 10,
+} usbc_usb_state_e;
+
+/*!
+ *  @brief usbc_func_state_e indicate possible states of class device for function suspend
+ *  @param USBC_FUNC_WK_ENABLE          to enable function remote wakeup
+ *  @param USBC_FUNC_WK_DISABLE         to disable function remote wakeup
+ *  @param USBC_FUNC_STATE_SUSPENDING   to suspend a class device
+ *  @param USBC_FUNC_STATE_RESUME       to resume a suspended class device
+ */
+typedef enum _usbc_func_state {
+    USBC_FUNC_WK_ENABLE                     = 0,
+    USBC_FUNC_WK_DISABLE                    = 1,
+    USBC_FUNC_STATE_SUSPENDING              = 5,
+    USBC_FUNC_STATE_RESUME                  = 7,
+    USBC_FUNC_WK_ENABLE_STATE_SUSPENDING    = 21,
+    USBC_FUNC_WK_ENABLE_STATE_RESUME        = 22,
+    USBC_FUNC_WK_DISABLE_STATE_SUSPENDING   = 23,
+    USBC_FUNC_WK_DISABLE_STATE_RESUME       = 24,
+    USBC_FUNC_SET_FEATURE_ERROR             = 25,
+} usbc_func_state_e;
+
+
+/*!
+ *  @brief usbc_op_mode_e USB Core operation mode
+ *  @param USBC_OP_MODE_UNKNOWN        unknown operation mode
+ *  @param USBC_OP_MODE_DETECTION      host and driver detection mode
+ *  @param USBC_OP_MODE_NORMAL         normal operation mode
+ *  @param USBC_OP_MODE_EXCEPTION      exception mode 
+ *  @param USBC_OP_MODE_MDONLY      DIPC only MD port
+ *  @param USBC_OP_MODE_NOLOGGING      DIPC no MD logging port
+ *  @param USBC_OP_MODE_METADEBUG      DIPC meta debug mode
+ *  @param USBC_OP_MODE_UNUSED      DIPC mode do not use USB
+ */
+typedef enum _usbc_op_mode {
+    USBC_OP_MODE_UNKNOWN                = 0,
+    USBC_OP_MODE_DETECTION              = 1,
+    USBC_OP_MODE_NORMAL                 = 2,
+    USBC_OP_MODE_EXCEPTION              = 3,    
+    USBC_OP_MODE_MDONLY                 =4,
+    USBC_OP_MODE_NOLOGGING          = 5,    
+    USBC_OP_MODE_METADEBUG          = 6,
+    USBC_OP_MODE_FACTORY               = 7,
+    USBC_OP_MODE_UNUSED                 =8,
+    USBC_OP_MODE_NUM,
+} usbc_op_mode_e;
+
+/*!
+ *  @brief usbc_usb_speed_e enumerate possible speed of usb device
+ *  @param USBC_USB_SPEED_MIN           pseudo speed
+ *  @param USBC_USB_SPEED_USB11         usb 1.1 full speed
+ *  @param USBC_USB_SPEED_USB20         usb 2.0 high speed
+ *  @param USBC_USB_SPEED_USB30         usb 3.0 super speed
+ *  @param USBC_USB_SPEED_MAX           pseudo speed
+ */
+typedef enum _usbc_usb_speed {
+    USBC_USB_SPEED_MIN                  = 0,
+    USBC_USB_SPEED_USB11                = 1,
+    USBC_USB_SPEED_USB20                = 2,
+    USBC_USB_SPEED_USB30                = 3,
+    USBC_USB_SPEED_MAX                  = 4,
+} usbc_usb_speed_e;
+
+
+/*!
+ *  @brief usbc_request_owner_e enumerate all possible types of usb control
+ *         request type
+ *  @param USBC_CONTROL_REQUEST_TYPE_MIN        pseudo type
+ *  @param USBC_CONTROL_REQUEST_TYPE_SEND       request to send
+ *  @param USBC_CONTROL_REQUEST_TYPE_RECEIVE    request to receive
+ *  @param USBC_CONTROL_REQUEST_TYPE_STALL      request to stall
+ *  @param USBC_CONTROL_REQUEST_TYPE_MAX        pseudo type
+ */
+typedef enum _usbc_control_request_type {
+    USBC_CONTROL_REQUEST_TYPE_MIN       = 0,
+    USBC_CONTROL_REQUEST_TYPE_SEND      = 1,
+    USBC_CONTROL_REQUEST_TYPE_RECEIVE   = 2,
+    USBC_CONTROL_REQUEST_TYPE_STALL     = 3,
+    USBC_CONTROL_REQUEST_TYPE_MAX       = 4,
+} usbc_control_request_type_e;
+
+
+/*!
+ *  @brief usbc_interface_type_e enumerate support list of interface types
+ *  @param USBC_INTERFACE_TYPE_MIN              pseudo interface
+ *  @param USBC_INTERFACE_TYPE_CDC_ACM_CONTROL  CDC ACM control interface
+ *  @param USBC_INTERFACE_TYPE_CDC_ACM_DATA     CDC ACM data interface
+ *  @param USBC_INTERFACE_TYPE_RNDIS_CONTROL    RNDIS control interface
+ *  @param USBC_INTERFACE_TYPE_RNDIS_DATA       RNDIS data interface
+ *  @param USBC_INTERFACE_TYPE_MAX              pseudo interface
+ */
+typedef enum _usbc_interface_type {
+    USBC_INTERFACE_TYPE_MIN                         = 0x0,
+    USBC_INTERFACE_TYPE_CDC_ACM_CONTROL             = 0x1,
+    USBC_INTERFACE_TYPE_CDC_ACM_DATA                = 0x2,
+    USBC_INTERFACE_TYPE_RNDIS_CONTROL               = 0x3,
+    USBC_INTERFACE_TYPE_RNDIS_DATA                  = 0x4,
+    USBC_INTERFACE_TYPE_MBIM_CONTROL                = 0x5,
+    USBC_INTERFACE_TYPE_MBIM_DATA                   = 0x6,
+    USBC_INTERFACE_TYPE_MSD_CONTROL                 = 0x7,
+    USBC_INTERFACE_TYPE_MSD_DATA                    = 0x8,
+    USBC_INTERFACE_TYPE_CDC_ECM_CONTROL               = 0x9,
+    USBC_INTERFACE_TYPE_CDC_ECM_DATA                  = 0xA,        
+    USBC_INTERFACE_TYPE_ADB_DATA                  = 0xB,    
+    USBC_INTERFACE_TYPE_MAX
+} usbc_interface_type_e;
+
+
+/*!
+ *  @brief usbc_pipe_type_e enumerate all possible types of usb classs
+ *         device pipe
+ *  @param USBC_PIPE_TYPE_MIN                   pseudo type
+ *  @param USBC_PIPE_TYPE_CDC_ACM_DATA_IN       CDC ACM data in pipe
+ *  @param USBC_PIPE_TYPE_CDC_ACM_COMM_IN       CDC ACM comm in pipe
+ *  @param USBC_PIPE_TYPE_CDC_ACM_DATA_OUT      CDC ACM data out pipe
+ *  @param USBC_PIPE_TYPE_GCOM_DATA_IN          Generic COM data in pipe
+ *  @param USBC_PIPE_TYPE_GCOM_DATA_OUT         Generic COM data out pipe
+ *  @param USBC_PIPE_TYPE_CDC_ECM_DATA_IN       CDC ECM data in pipe
+ *  @param USBC_PIPE_TYPE_CDC_ECM_COMM_IN       CDC ECM comm in pipe
+ *  @param USBC_PIPE_TYPE_CDC_ECM_DATA_OUT      CDC ECM data out pipe
+ *  @param USBC_PIPE_TYPE_RNDIS_DATA_IN         RNDIS data in pipe
+ *  @param USBC_PIPE_TYPE_RNDIS_COMM_IN         RNDIS comm in pipe
+ *  @param USBC_PIPE_TYPE_RNDIS_DATA_OUT        RNDIS data out pipe
+ *  @param USBC_PIPE_TYPE_MASS_STORAGE_DATA_IN  Mass Storage data in pipe
+ *  @param USBC_PIPE_TYPE_MASS_STORAGE_DATA_OUT Mass Storage data out pipe
+ *  @param USBC_PIPE_TYPE_MAX                   pseudo type
+ */
+typedef enum _usbc_pipe_type {
+    USBC_PIPE_TYPE_MIN                      = 0,
+    USBC_PIPE_TYPE_CDC_ACM_DATA_IN          = 1,
+    USBC_PIPE_TYPE_CDC_ACM_COMM_IN          = 2,
+    USBC_PIPE_TYPE_CDC_ACM_DATA_OUT         = 3,
+    USBC_PIPE_TYPE_GCOM_DATA_IN             = 4,
+    USBC_PIPE_TYPE_GCOM_DATA_OUT            = 5,
+    USBC_PIPE_TYPE_CDC_ECM_DATA_IN          = 6,
+    USBC_PIPE_TYPE_CDC_ECM_COMM_IN          = 7,
+    USBC_PIPE_TYPE_CDC_ECM_DATA_OUT         = 8,
+    USBC_PIPE_TYPE_RNDIS_DATA_IN            = 9,
+    USBC_PIPE_TYPE_RNDIS_COMM_IN            = 10,
+    USBC_PIPE_TYPE_RNDIS_DATA_OUT           = 11,
+    USBC_PIPE_TYPE_MASS_STORAGE_DATA_IN     = 12,
+    USBC_PIPE_TYPE_MASS_STORAGE_DATA_OUT    = 13,
+    USBC_PIPE_TYPE_MBIM_DATA_IN             = 14,
+    USBC_PIPE_TYPE_MBIM_COMM_IN             = 15,
+    USBC_PIPE_TYPE_MBIM_DATA_OUT            = 16,
+    USBC_PIPE_TYPE_ADB_DATA_IN             = 17,
+    USBC_PIPE_TYPE_ADB_DATA_OUT            = 18,
+    USBC_PIPE_TYPE_MAX
+} usbc_pipe_type_e;
+
+
+
+
+
+
+
+
+
+
+/*!
+ *  @brief usbc_core_class_device_state_e enumerate all possible states of
+ *         class device in USBCORE module
+ *  @param USBC_CORE_CLASS_DEVICE_STATE_MIN         pseudo state
+ *  @param USBC_CORE_CLASS_DEVICE_STATE_NOTEXIST    this device is not existed
+ *  @param USBC_CORE_CLASS_DEVICE_STATE_INITIATED   this device is initiated 
+ *  @param USBC_CORE_CLASS_DEVICE_STATE_REGISTERED  this device is registered
+ *  @param USBC_CORE_CLASS_DEVICE_STATE_MAX         pseudo state
+ */
+typedef enum _usbc_core_class_device_state {
+    USBC_CORE_CLASS_DEVICE_STATE_MIN        = 0,
+    USBC_CORE_CLASS_DEVICE_STATE_NOTEXIST   = 1,
+    USBC_CORE_CLASS_DEVICE_STATE_INITIATED  = 2,
+    USBC_CORE_CLASS_DEVICE_STATE_REGISTERED = 3,
+    USBC_CORE_CLASS_DEVICE_STATE_MAX        = 4,
+} usbc_core_class_device_state_e;
+
+
+/*!
+ *  @brief usbc_core_class_interface_state_e enumerate all possible states of
+ *         class interface in USBCORE module
+ *  @param USBC_CORE_CLASS_INTERFACE_STATE_MIN          pseudo state
+ *  @param USBC_CORE_CLASS_INTERFACE_STATE_DISABLE      this interface is disabled
+ *  @param USBC_CORE_CLASS_INTERFACE_STATE_INITIATED    this interface is initiated
+ *  @param USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE       this interface is actived
+ *  @param USBC_CORE_CLASS_INTERFACE_STATE_MAX          pseudo state
+ */
+typedef enum _usbc_core_class_interface_state {
+    USBC_CORE_CLASS_INTERFACE_STATE_MIN         = 0,
+    USBC_CORE_CLASS_INTERFACE_STATE_DISABLE     = 1,
+    USBC_CORE_CLASS_INTERFACE_STATE_INITIATED   = 2,
+    USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE      = 3,
+    USBC_CORE_CLASS_INTERFACE_STATE_MAX         = 4,
+} usbc_core_class_interface_state_e;
+
+
+/*!
+ *  @brief usbc_core_queue_state_e enumerate all possible states of QMU Queue
+ *         in USBCORE module
+ *  @param USBC_CORE_QUEUE_STATE_MIN        pseudo state
+ *  @param USBC_CORE_QUEUE_STATE_DISABLE    this queue is not used
+ *  @param USBC_CORE_QUEUE_STATE_INITIATED  this queue is initiated
+ *  @param USBC_CORE_QUEUE_STATE_ACTIVE     this queue is enabled,and used
+ *  @param USBC_CORE_QUEUE_STATE_STALL      this queue is enabled,but stalled
+ *  @param USBC_CORE_QUEUE_STATE_MAX        pseudo state
+ */
+typedef enum _usbc_core_queue_state {
+    USBC_CORE_QUEUE_STATE_MIN               = 0,
+    USBC_CORE_QUEUE_STATE_DISABLE           = 1,
+    USBC_CORE_QUEUE_STATE_INITIATED         = 2,
+    USBC_CORE_QUEUE_STATE_ACTIVE            = 3,
+    USBC_CORE_QUEUE_STATE_STALL             = 4,
+    USBC_CORE_QUEUE_STATE_MAX               = 5,
+} usbc_core_queue_state_e;
+
+/*!
+ *  @brief usbc_setup_packet_sm_e USBCORE setup state machine
+ *  @param USBC_CORE_SETUP_SM_INITIALIZE        initialize state
+ *  @param USBC_CORE_SETUP_SM_RECEIVED    usbcore received setup packet
+ *  @param USBC_CORE_SETUP_SM_MULTI_SETUP  received multiple setup packet
+ *  @param USBC_CORE_SETUP_SM_MAX        pseudo state
+ */
+typedef enum _usbc_setup_packet_sm{
+    USBC_CORE_SETUP_SM_INITIALIZE = 0,
+    USBC_CORE_SETUP_SM_RECEIVED = 1,
+    USBC_CORE_SETUP_SM_MULTI_SETUP = 2,
+    USBC_CORE_SETUP_SM_MAX = 3,
+}usbc_setup_packet_sm_e;
+
+/*!
+ *  @brief usbc_io_request_t is a typedef of struct _usbc_io_request
+ */
+typedef struct _usbc_io_request usbc_io_request_t;
+/*!
+ *  @brief struct _usbc_io_request describe usbc io request used to communicate
+ *         usb class device and usbcore
+ */
+struct _usbc_io_request {
+    /*!
+     *  @brief next io request
+     */
+    usbc_io_request_t*      next_request;
+    /*!
+     *  @brief pointer to current gpd of this io request
+     */
+    qbm_gpd*                first_gpd;
+    /*!
+     *  @brief pointer to last gpd of this io request
+     */
+    qbm_gpd*                last_gpd;
+};
+
+
+/*!
+ *  @brief usbc_core_queue_t describe queue information maintain within usbcore
+ */
+typedef struct _usbc_core_queue {
+
+    /*!
+     *  @brief current queue state of this queue
+     */
+    usbc_core_queue_state_e     state;
+    /*!
+     *  @brief id of class device that own this queue
+     */
+    kal_uint8                   class_device_id;
+    /*!
+     *  @brief pipe type of this queue
+     */
+    usbc_pipe_type_e            pipe_type;
+    /*!
+     *  @brief usb transfer type of this queue
+     */
+    hifusb_usb_xfer_type_e      xfer_type;
+    /*!
+     *  @brief endpoint number of this queue
+     */
+    kal_uint8                   ep_no;
+    /*!
+     *  @brief maximum packet size of this queue
+     */
+    kal_uint16                  max_packet_size;
+    /*!
+     *  @brief fifo type is DOUBLE FIFO or not
+     */
+    kal_uint8                   fifo_n;
+    kal_uint8                   rsvd[3];
+    /*!
+     *  @brief queue configuration
+     */
+    kal_uint32                  config;
+    /*!
+     *  @brief queue owner
+     */
+    usb_class_owner_e       owner;
+    /*!
+     *  @brief complete function to notify class device (GPD/SPD)
+     */
+    void                        (*notify_complete)(kal_uint8 class_deivce_id, usbc_io_request_t* io_request);
+    /*!
+     *  @brief complete function to notify class device (UL META/DRB)
+     */
+    void                        (*notify_rb_complete)(kal_uint8 class_deivce_id, kal_uint32 start_idx, kal_uint32 end_idx, kal_uint32 rel_idx);
+    /*!
+     *  @brief callback function to notify class device queue is stall or not
+     */
+    void                        (*notify_stall)(kal_uint8 class_device_id, kal_bool stall);
+} usbc_core_queue_t;
+
+typedef struct _usbc_endpoint_info_t {
+
+    /*!
+     *  @brief Descriptor length
+     */
+    kal_uint16                             epdscr_size;
+    
+    /*!
+     *  @brief Endpoint descriptor
+     */
+    union {
+        usbc_endpoint_descriptor_t         stdep;
+        kal_uint8                          classep[MAX_USBCORE_CLASS_EPDESC_LENGTH];
+    } epdscr;
+
+    usbc_core_queue_t                      queue_info;
+} usbc_endpoint_info_t;
+
+typedef struct _usbc_alternate_interface_info_t {
+    /*!
+     *  @brief Descriptor length
+     */
+    kal_uint16                             ifdscr_size;
+
+    union {
+        usbc_interface_descriptor_t        stdif;
+        kal_uint8                          classif[MAX_USBCORE_IFDESC_LENGTH];
+    } ifdscr;
+
+    usbc_endpoint_info_t                   *ep_info[MAX_USBCORE_EPNUM_PER_IF];
+    
+} usbc_alternate_interface_info_t;
+
+/*!
+ *  @brief usbc_core_class_interface_t describe class interface information
+ *         maintain within usbcore
+ */
+typedef struct _usbc_core_class_interface_t {
+    /*!
+     *  @brief interace number of this interface
+     */
+    kal_uint8                           interface_no;
+    /*!
+     *  @brief interace type of this interface
+     */
+    usbc_interface_type_e               interface_type;
+    /*!
+     *  @brief id of class device that own this interface
+     */
+    kal_uint8                           class_device_id;
+    /*!
+     *  @brief current state of this interface
+     */
+    usbc_core_class_interface_state_e   state;
+    /*!
+     *  @brief bAlternateSetting of this interface
+     */
+    kal_uint8                           alternate_setting;
+    kal_uint8                           rsvd[3];
+    /*!
+     *  @brief callback function while control tranfer for this device
+     *         is received
+     */
+    void                                (*notify_control_setup_packet)(kal_uint8 class_device_id, usbc_setup_packet_t* packet);
+    /*!
+     *  @brief callback function while control tranfer is complete
+     */
+    void                                (*notify_control_complete)(kal_uint8 class_device_id);
+    /*!
+     *  @brief callback function while interface alternate setting is set
+     */
+    void                                (*notify_alternate_setting)(kal_uint8 class_device_id, usbc_interface_type_e inteface, kal_uint8 alternate_setting);
+
+} usbc_core_class_interface_t;
+
+/*!
+ *  @brief usbc_core_class_interface_t describe class interface information
+ *         maintain within usbcore
+ */
+typedef struct _usbc_interface_info_t {
+
+    usb_class_type_e                       type;
+
+    /*!
+     *  @brief Descriptor length
+     */
+    kal_uint16                             ifdscr_size;
+
+    /*!
+     *  @brief Interface descriptor
+     */
+    union {
+        usbc_interface_descriptor_t        stdif;
+        kal_uint8                          classif[MAX_USBCORE_IFDESC_LENGTH];
+    } ifdscr;
+
+    usbc_endpoint_info_t                   *ep_info[MAX_USBCORE_EPNUM_PER_IF];
+
+    kal_bool                               altn_surpport; // FALSE (no alternate setting) or TRUE (has alternate setting)
+    usbc_alternate_interface_info_t        altn_if_info;
+
+    usbc_core_class_interface_t            class_interface;
+
+} usbc_interface_info_t;
+
+/*!
+ *  @brief usbc_class_device_instance_t describe instance of a
+ *         generic usb class device
+ */
+typedef struct _usbc_class_device_instance {
+    /*!
+    *   @brief instance id of this device
+    */
+    kal_uint8               id;
+
+    /*!
+     *  @brief current usb speed of this device
+     */
+    kal_uint8               speed;
+    /*!
+     *  @brief total_interfaces for this class device
+     */
+    kal_uint8               total_interfaces;
+    kal_uint8               rsvd[1];
+    /*!
+     *  @brief per class device context
+     */
+    void                   *context;
+    /*!
+     *  @brief qmu queue no for each pipe
+     */
+    kal_uint8               queue_no_for_pipe[MAX_USBCORE_CLASS_PIPE_NUM];
+    /*!
+     *  @brief interface type of each interface for this class device
+     */
+    usbc_interface_type_e   interface_type[MAX_USBCORE_CLASS_INTERFACE_NUM];
+    /*!
+     *  @brief interface number of each interface for this class device
+     */
+    kal_uint8               interface_no[MAX_USBCORE_CLASS_INTERFACE_NUM];
+} usbc_class_device_instance_t;
+
+/*!
+ *  @brief usbc_io_req_type_e Type of operation to for requests to submit to USB HIF.
+ *  @param USBC_IO_TX_NO_FLUSH                  Transmit operation without GPD checksum calcuation and cache flush.
+ */
+typedef enum _usbc_io_req_type {
+     USBC_IO_TX_NO_FLUSH        = 0x00000010,
+     USBC_IO_TYPE_DUMMY         = 0x7fffffff
+} usbc_io_req_type_e;
+
+/*!
+ *  @brief usbc_io_ext_info_t Configurations apply to the requests to submit to USB HIF.
+ *  @param type               Type of operation.
+ */
+typedef struct _usbc_io_ext_info {
+     usbc_io_req_type_e   type;
+} usbc_io_ext_info_t;
+
+
+/*
+ * @brief Settings of each type of node to checkin.
+ */
+typedef struct {
+    void       *init_func; /* iniitialize descriptor function pointer. */
+    void       *set_config_func; /* initialize configuration function pointer */
+    void       *reinit_func; /* reinit function pointer */
+    void       *query_func_wk_capability;   /*  callback function to remote wakeup capability of class device */
+} usbc_node_reg_entry_t;
+
+typedef kal_int32 (*usbc_class_init_func_t)(kal_uint8 class_device_id, usb_mode_e mode, kal_uint32 config_index, void *context, kal_uint32 flag);
+typedef kal_int32 (*usbc_class_set_config_func_t)(kal_uint8 class_device_id, kal_uint32 config_index, void *context);
+typedef void (*usbc_class_reinit_func_t)(kal_bool need_check_in);
+typedef kal_uint16 (*usbc_class_query_func_wk_capability_func_t)(void);
+
+
+usbc_class_set_config_func_t usbc_get_class_set_config_func(usb_class_type_e type);
+
+/*!
+ *  @brief  Add a node into USB stack, the USB stack will start loading configuration,
+ *          initializing corresponding modules.
+ *          Running Level: TASK INIT
+ *  @param  node     Node of USB stack.
+ *  @param  reg_table An array of settings. The last entry is ended with type=USBC_NODE_REG_ENTRY_END_TYPE.
+ */
+void usbc_stack_checkin(usb_class_type_e func_type, usbc_node_reg_entry_t *reg_table);
+
+void usbc_mode_switch(usb_mode_e mode);
+
+void usbc_reinit_class(void);
+
+#endif  // _USBCORE_COMMON_H
+
diff --git a/mcu/middleware/hif/interface/usbcore_direct.h b/mcu/middleware/hif/interface/usbcore_direct.h
new file mode 100644
index 0000000..b22f344
--- /dev/null
+++ b/mcu/middleware/hif/interface/usbcore_direct.h
@@ -0,0 +1,102 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   usbcore_direct.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   USB Core direct API.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *******************************************************************************/
+#ifndef _USBCORE_DIRECT_H
+#define _USBCORE_DIRECT_H
+
+#include "hifusb_qmu.h"
+#include "kal_public_api.h"
+#include "ufpm_usbcore.h"
+
+
+void usbc_direct_hif_usbcore_send_indication();
+
+void usbc_direct_hif_enable_poll_queue(kal_bool enable);
+
+void usbc_direct_hif_notify_usb_func_event(kal_uint8 class_device_id, usbc_usb_state_e state);
+
+void usbc_direct_hif_attach(usbc_usb_speed_e speed, kal_uint8 address, kal_uint8 configuration);
+
+void usbc_direct_hif_detach();
+
+void usbc_direct_set_config_class_device(kal_uint8 class_device_id, kal_uint8 configuration);
+
+void usbc_direct_core_set_config(kal_uint8 configuration);
+
+kal_bool usbc_direct_dispatch_control_setup_packet(kal_uint8 class_device_id, void* pkt_ptr);
+
+kal_bool usbc_direct_hif_usbq_set_gpd(hif_queue_type_e q_type, kal_uint8 logic_queue_no, qbm_gpd* first_gpd, qbm_gpd* last_gpd);
+
+kal_uint32 usbc_direct_hif_usbq_poll_gpd(hif_deq_info_t deq_info, void **first_gpd, void **last_gpd);
+
+kal_bool usbc_direct_hif_chk_newpkt(kal_bool isTx, kal_uint8 logic_queue_no);
+
+kal_bool usbc_direct_hif_usbq_chk_empty(hif_queue_type_e core_queue_hif_type, kal_uint8 q_num);
+
+kal_uint32 usbc_direct_hif_usbq_flush_gpd(hif_queue_type_e q_type, kal_uint8 logic_queue_no, hif_flush_type_e flush_type , void **pp_head, void **pp_tail);
+
+kal_uint32 usbc_direct_hif_sw_usbq_flush_gpd(hif_queue_type_e q_type, kal_uint8 logic_queue_no, hif_flush_type_e flush_type , void **pp_head, void **pp_tail);
+
+void usbc_direct_hifusb_set_usb_address_emulate(kal_uint8 address);
+
+void usbc_direct_init_ufpm_mapping_table(kal_uint8 config_no, kal_uint8 class_device_id, ufpm_usb_mapping_t* perClassMapTlb);
+
+kal_bool usbc_direct_hif_init(void);
+
+void usbc_direct_hif_notify_usb_core_event(usbc_usb_state_e state);
+
+kal_bool usbc_direct_hifusb_set_usbhif_connect_disconnect();
+
+void usbc_direct_set_usb_mapping(kal_bool isTx, kal_uint8 md_q_no, kal_uint8 ap_ep_no);
+
+#endif
diff --git a/mcu/middleware/hif/interface/usbcore_except.h b/mcu/middleware/hif/interface/usbcore_except.h
new file mode 100644
index 0000000..032d6da
--- /dev/null
+++ b/mcu/middleware/hif/interface/usbcore_except.h
@@ -0,0 +1,178 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   usbcore_except.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   USB Core exception mode interface.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __INC_USBCORE_EXCEPT_H
+#define __INC_USBCORE_EXCEPT_H
+
+#include "usbcore_common.h"
+#include "usbcore_class_device.h"
+
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+typedef enum _usbc_except_link_st {
+    USBC_LINK_NO_ERROR     = 0,
+    USBC_LINK_TX_TIMEOUT   = 1,
+} usbc_except_link_st_e;
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+
+/*!
+ *  @brief  Start exception mode HIF data path.
+ *          See also hif_except_initial() for more information.
+ *  @return KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+kal_bool usbc_except_init(void);
+
+/*!
+ *  @brief  Stop the queue and flush USB pipe FIFO. 
+ *          See also hif_except_clear_q() for more information.
+ *  @param  class_device_id USB class device id.
+ *  @param  queue_no QMU queue no.
+ *  @return KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+kal_bool usbc_except_clear_ch(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+/*!
+ *  @brief  Register the device to be used in exception mode and then trigger USB enumeration.
+ *  @param  device_info class device information of the device.
+ *  @return new instance of usb class device if succeeded, NULL otherwise.
+ */
+usbc_class_device_instance_t *usbc_except_reset_ch(usbc_class_device_info_t *device_info);
+
+/*!
+ *  @brief  Perform USB enumeration. 
+ *          Note that, this function exist either the enumeration process is completed or timeout.
+ *  @return KAL_TRUE if the USB enumeration is completed, KAL_FALSE if timeout.
+ */
+kal_bool usbc_except_enum_loop(void);
+
+/*!
+ *  @brief Check and handle USB control transfers and other device state changes.
+ *         See also hifusb_except_poll_isr() for more information.
+ *  @param  class_device_id USB class device id.
+ *  @return KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+kal_bool usbc_except_hif_poll(kal_uint8 class_device_id);
+
+/*!
+ *  @brief  Submit a list of GPD to the specified queue of a USB class device instance.
+ *          See also hif_except_set_gpd() for more information.
+ *  @param  class_device_id USB class device id.
+ *  @param  queue_no QMU queue no.
+ *  @param  p_first_gpd head of the GPD list.
+ *  @param  p_last_gpd tail of the GPD list.
+ *  @return KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+kal_bool usbc_except_submit_gpd(kal_uint8 class_device_id, kal_uint8 queue_no, void *p_first_gpd, void *p_last_gpd);
+
+/*!
+ *  @brief  Check if any GPD submitted to specified queue of a USB class device instance has been completed.
+ *          See also hif_except_poll_queue() for more information.
+ *  @param  class_device_id USB class device id.
+ *  @param  queue_no QMU queue no.
+ *  @param  pp_first_gpd Caller allocated space for a pointer to head of the GPD list completed. Its value is invalid if this function returns KAL_FALSE.
+ *  @param  pp_last_gpd Caller allocated space for a pointer to tail of the GPD list copmleted. Its value is invalid if this function returns KAL_FALSE.
+ *  @param  gpd_num Number of GPD completed. Its value is invalid if this function returns KAL_FALSE.
+ *  @return KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+kal_bool usbc_except_poll_queue(kal_uint8 class_device_id, kal_uint8 queue_no, void **pp_first_gpd, void **pp_last_gpd, kal_uint32 *gpd_num);
+
+/*!
+ *  @brief  Check specified queue status.
+ *          See also hif_except_get_txq_timeout(() for more information.
+ *  @param  class_device_id USB class device id.
+ *  @param  queue_no QMU queue no.
+ *  @param  link_state Return status of the queue if succeeded.
+ *  @return KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+kal_bool usbc_except_hif_state(kal_uint8 class_device_id, kal_uint8 queue_no, usbc_except_link_st_e *link_state);
+
+/*!
+ *  @brief  flush Tx/Rx queue in exception reset.
+ *  @param  class_device_id USB class device id.
+ *  @param  queue_no QMU queue no.
+ *  @param  number of returned flushed GPDs.
+ *  @param  address of the returned GPD's head.
+ *  @param  address of the returned GPD's tail.
+ *  @return KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+kal_bool usbc_except_reset_flush(kal_uint8 class_device_id, kal_uint8 queue_no, void** first_gpd, void** last_gpd, kal_uint32* gpd_num);
+#endif /* __INC_USBCORE_EXCEPT_H */
+
diff --git a/mcu/middleware/hif/interface/usbcore_usbstd.h b/mcu/middleware/hif/interface/usbcore_usbstd.h
new file mode 100644
index 0000000..e23203d
--- /dev/null
+++ b/mcu/middleware/hif/interface/usbcore_usbstd.h
@@ -0,0 +1,517 @@
+/*!
+ *  @file usbcore_usbstd.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides standard definitions of usb-if specification
+ */
+
+#ifndef _USBCORE_USBSTD_H
+#define _USBCORE_USBSTD_H
+
+#include "kal_public_api.h"
+
+/*
+ * Helper routines.
+ */
+#define USBC_GET_UINT8(_buf, _offset) \
+            *((kal_uint8*)(_buf) + (_offset))
+
+#define USBC_GET_UINT16(_buf, _offset) \
+            (  ((kal_uint16)*((kal_uint8 *)(_buf) + (_offset))) | \
+              (((kal_uint16)*((kal_uint8 *)(_buf) + (_offset) + 1)) << 8) )
+
+#define USBC_GET_UINT32(_buf, _offset) \
+            (  ((kal_uint32)*((kal_uint8 *)(_buf) + (_offset))) | \
+              (((kal_uint32)*((kal_uint8 *)(_buf) + (_offset) + 1)) << 8) | \
+              (((kal_uint32)*((kal_uint8 *)(_buf) + (_offset) + 2)) << 16) | \
+              (((kal_uint32)*((kal_uint8 *)(_buf) + (_offset) + 3)) << 24) )
+
+#define USBC_SET_UINT8(_buf, _offset, _value) \
+            *((kal_uint8*)(_buf) + (_offset)) = (kal_uint8)(_value)
+
+#define USBC_SET_UINT16(_buf, _offset, _value) \
+            *((kal_uint8*)(_buf) + (_offset)) = (kal_uint8)(_value); \
+            *((kal_uint8*)(_buf) + (_offset) + 1) = (kal_uint8)((_value) >> 8)
+
+#define USBC_SET_UINT32(_buf, _offset, _value) \
+            *((kal_uint8*)(_buf) + (_offset)) = (kal_uint8)(_value); \
+            *((kal_uint8*)(_buf) + (_offset) + 1) = (kal_uint8)((_value) >> 8); \
+            *((kal_uint8*)(_buf) + (_offset) + 2) = (kal_uint8)((_value) >> 16); \
+            *((kal_uint8*)(_buf) + (_offset) + 3) = (kal_uint8)((_value) >> 24)
+
+#define USBC_GET_DESC_LENGTH(_desc) \
+            USBC_GET_UINT8(_desc, 0)
+
+#define USBC_SET_DESC_LENGTH(_desc, _value) \
+            USBC_SET_UINT8(_desc, 0, _value)
+
+#define USBC_GET_DESC_TYPE(_desc) \
+            USBC_GET_UINT8(_desc, 1)
+
+#define USBC_SET_DESC_TYPE(_desc, _value) \
+            USBC_SET_UINT8(_desc, 1, _value)
+
+
+/*!
+ * @brief USB Standard Requests
+ */
+#define USBC_REQ_GET_STATUS                 0x00
+#define USBC_REQ_CLEAR_FEATURE              0x01
+#define USBC_REQ_SET_FEATURE                0x03
+#define USBC_REQ_SET_ADDRESS                0x05
+#define USBC_REQ_GET_DESCRIPTOR             0x06
+#define USBC_REQ_SET_DESCRIPTOR             0x07
+#define USBC_REQ_GET_CONFIGURATION          0x08
+#define USBC_REQ_SET_CONFIGURATION          0x09
+#define USBC_REQ_GET_INTERFACE              0x0A
+#define USBC_REQ_SET_INTERFACE              0x0B
+#define USBC_REQ_SYNCH_FRAME                0x0C
+#define USBC_REQ_SET_SEL                    0x30
+#define USBC_REQ_SET_ISOCHRONOUS_DELAY      0x31
+
+/*!
+ * @brief Vendor Request Codes
+ */
+#define USBC_REQ_GET_MS_DESCRIPTOR          0xCC
+
+/*!
+ * @brief USB Request Types
+ */
+#define USBC_REQUEST_TYPE_MASK              (0x03 << 5)
+#define USBC_REQUEST_TYPE_STANDARD          (0x00 << 5)
+#define USBC_REQUEST_TYPE_CLASS             (0x01 << 5)
+#define USBC_REQUEST_TYPE_VENDOR            (0x02 << 5)
+#define USBC_REQUEST_TYPE_RESERVED          (0x03 << 5)
+
+
+/*!
+ * @brief USB Request Recipients
+ */
+#define USBC_REQUEST_RECIP_MASK             0x1f
+#define USBC_REQUEST_RECIP_DEVICE           0x00
+#define USBC_REQUEST_RECIP_INTERFACE        0x01
+#define USBC_REQUEST_RECIP_ENDPOINT         0x02
+#define USBC_REQUEST_RECIP_OTHER            0x03
+
+
+/*!
+ * @breif USB Request Directions
+ */
+#define USBC_REQUEST_DIR_OUT                0
+#define USBC_REQUEST_DIR_IN                 0x80
+
+/*!
+ * @brief USB Set Features
+ */
+#define USBC_FEATURE_ENDPOINT_HALT          0x00
+#define USBC_FEATURE_FUNCTION_SUSPEND       0x00
+#define USBC_FEATURE_DEVICE_REMOTE_WAKEUP   0x01
+#define USBC_FEATURE_TEST_MODE              0x02
+#define USBC_FEATURE_U1_ENABLE              0x30
+#define USBC_FEATURE_U2_ENABLE              0x31
+#define USBC_FEATURE_LTM_ENABLE             0x32
+
+
+/*!
+ *  @brief Device Descriptor Types
+ */
+#define USBC_DT_DEVICE                      0x01
+#define USBC_DT_CONFIG                      0x02
+#define USBC_DT_STRING                      0x03
+#define USBC_DT_INTERFACE                   0x04
+#define USBC_DT_ENDPOINT                    0x05
+#define USBC_DT_DEVICE_QUALIFIER            0x06
+#define USBC_DT_OTHER_SPEED                 0X07
+#define USBC_DT_INTERFACE_POWER             0x08
+#define USBC_DT_OTG                         0x09
+#define USBC_DT_IAD                         0x0B
+#define USBC_DT_BOS                         0x0F
+#define USBC_DT_DEVICE_CAPABILITY           0x10
+#define USBC_DT_ENDPOINT_COMPANION          0x30
+
+
+/*!
+ * @breif USB Request Directions
+ */
+#define USBC_EP_ADDR_DIR_IN                 0x80
+#define USBC_EP_ADDR_NUM_MASK               0x7F
+
+
+
+/*!
+ *  @brief usbc_setup_packet_t describe the detail field definition of
+ *         control setup packet
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_setup_packet {
+    /*!
+     *  @brief request type of setup packet
+     *         Bit 7: Request direction
+     *                (0=Host to device - Out, 1=Device to host - In)
+     *         Bits 5-6: Request type
+     *                (0=standard, 1=class, 2=vendor, 3=reserved)
+     *         Bits 0-4: Recipient
+     *                (0=device, 1=interface, 2=endpoint,3=other)
+     */
+    kal_uint8       bmRequestType;
+    /*!
+     *  @brief the actual request, see the Standard Device Request Codes table
+     */
+    kal_uint8       bRequest;
+    /*!
+     *  @brief a word-size value that varies according to the request
+     */
+    kal_uint16      wValue;
+    /*!
+     *  @brief a word-size value that varies according to the request,
+     *         the index is generally used to specify an endpoint or
+     *         an interface.
+     */
+    kal_uint16      wIndex;
+    /*!
+     *  @brief a word-size value that indicates the number of bytes to be
+     *         transferred if there is a data stage
+     */
+    kal_uint16      wLength;
+}  usbc_setup_packet_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief Device Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_device_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint16      bcdUSB;
+    kal_uint8       bDeviceClass;
+    kal_uint8       bDeviceSubClass;
+    kal_uint8       bDeviceProtocol;
+    kal_uint8       bMaxPacketSize0;
+    kal_uint16      idVendor;
+    kal_uint16      idProduct;
+    kal_uint16      bcdDevice;
+    kal_uint8       iManufacturer;
+    kal_uint8       iProduct;
+    kal_uint8       iSerialNumber;
+    kal_uint8       bNumConfigurations;
+} usbc_device_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+#define USBC_DEVICE_DESC_SIZE sizeof(usbc_device_descriptor_t)
+
+/*!
+ *  @brief Configuration Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_configuration_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint16      wTotalLength;
+    kal_uint8       bNumInterfaces;
+    kal_uint8       bConfigurationValue;
+    kal_uint8       iConfiguration;
+    kal_uint8       bmAttributes;
+    kal_uint8       bMaxPower;
+} usbc_configuration_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+#define USBC_CONFIGURATION_DESC_SIZE sizeof(usbc_configuration_descriptor_t)
+#define USBC_MAX_CONF_SIZE 1024
+#define USBC_USB20_POWER_DESC_UINT 2 /* 2 mA unit */
+#define USBC_USB30_POWER_DESC_UINT 8 /* 8 mA unit */
+#define USBC_USB30_EP0_PACKET_SIZE 9 /* in power of 2 */
+
+#define USBC_GET_CONF_TOTAL_LENGTH(_desc) \
+            USBC_GET_UINT16(_desc, 2)
+#define USBC_SET_CONF_TOTAL_LENGTH(_desc, _value) \
+            USBC_SET_UINT16(_desc, 2, _value)
+
+#define USBC_GET_CONF_MAX_POWER(_desc) \
+            USBC_GET_UINT8(_desc, 8)
+#define USBC_SET_CONF_MAX_POWER(_desc, _value) \
+            USBC_SET_UINT8(_desc, 8, _value)
+
+
+/*!
+ *  @brief Interface Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_interface_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint8       bInterfaceNumber;
+    kal_uint8       bAlternateSetting;
+    kal_uint8       bNumEndpoints;
+    kal_uint8       bInterfaceClass;
+    kal_uint8       bInterfaceSubClass;
+    kal_uint8       bInterfaceProtocol;
+    kal_uint8       iInterface;
+} usbc_interface_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief Interface Association Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_interface_association_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint8       bFirstInterface;
+    kal_uint8       bInterfaceCount;
+    kal_uint8       bFunctionClass;
+    kal_uint8       bFunctionSubClass;
+    kal_uint8       bFunctionProtocol;
+    kal_uint8       iFunction;
+} usbc_interface_association_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief Endpoint Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_endpoint_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint8       bEndpointAddress;
+    kal_uint8       bmAttributes;
+    kal_uint16      wMaxPacketSize;
+    kal_uint8       bInterval;
+} usbc_endpoint_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+#define USBC_GET_EP_ATTRIBUTES(_desc) \
+            USBC_GET_UINT8(_desc, 3)
+#define USBC_SET_EP_ATTRIBUTES(_desc, _value) \
+            USBC_SET_UINT8(_desc, 3, _value)
+
+#define USBC_GET_EP_MAX_PACKET_SIZE(_desc) \
+            USBC_GET_UINT16(_desc, 4)
+#define USBC_SET_EP_MAX_PACKET_SIZE(_desc, _value) \
+            USBC_SET_UINT16(_desc, 4, _value)
+
+#define USBC_GET_EP_ADDR(_desc) \
+            USBC_GET_UINT16(_desc, 2)
+
+#define USBC_CONTROL_TRANSFER       0x00
+#define USBC_ISOCHRONOUS_TRANSFER   0x01
+#define USBC_BULK_TRANSFER          0x02
+#define USBC_INTERRUPT_TRANSFER     0x03
+
+#define USBC_GET_EP_TRANSFER_TYPE(_desc) \
+            (USBC_GET_EP_ATTRIBUTES(_desc) & 0x03)
+
+#define USBC_USB30_BULK_PACKET_SIZE 1024
+
+/*!
+ *  @brief String Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_string_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint16      wData[1];
+} usbc_string_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief Qualifier Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_device_qualifier_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint16      bcdUSB;
+    kal_uint8       bDeviceClass;
+    kal_uint8       bDeviceSubClass;
+    kal_uint8       bDeviceProtocol;
+    kal_uint8       bMaxPacketSize0;
+    kal_uint8       bNumConfigurations;
+    kal_uint8       bRESERVED;
+} usbc_device_qualifier_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief CS Header Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_cs_header_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint8       bDescriptorSubType;
+    kal_uint16      bcdCDC;
+} usbc_cs_header_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief CS Call Manage Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_cs_call_manager_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint8       bDescriptorSubType;
+    kal_uint8       bmCapabilities;
+    kal_uint8       bDataInterface;
+} usbc_cs_call_manage_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief CS Abstract Control Manage Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_cs_abstract_control_manage_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint8       bDescriptorSubType;
+    kal_uint8       bmCapabilities;
+} usbc_cs_abstract_control_manage_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief CS Union Function Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_cs_union_function_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint8       bDescriptorSubType;
+    kal_uint8       bMasterInterface;
+    kal_uint8       bSlaveInterface;
+} usbc_cs_union_function_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+
+/*!
+ *  @brief CS Ethernet Networking Function Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_cs_ethernet_networking_function_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint8       bDescriptorSubType;
+    kal_uint8       iMACAddress;
+    kal_uint32      bmEthernetStatistics;
+    kal_uint16      wMaxSegmentSize;
+    kal_uint16      wNumberMCFilters;
+    kal_uint8       bNumberPowerFilters;
+} usbc_cs_ethernet_networking_function_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+/*!
+ *  @brief Microsoft OS String Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_os_string_descriptor {
+    kal_uint8       bLength;
+    kal_uint8       bDescriptorType;
+    kal_uint8       qwSignature[14];
+    kal_uint8       bMS_VendorCode;
+    kal_uint8       bPad;
+} usbc_os_string_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+/*!
+ *  @brief Microsoft OS String Descriptor Structure
+ */
+PRAGMA_BEGIN_PACK_STRUCT
+typedef struct _usbc_ext_compat_id_os_feature_descriptor {
+    kal_uint32      dwLength;
+    kal_uint16      bcdVersion;
+    kal_uint16      wIndex;
+    kal_uint8       bCount;
+    kal_uint8       bPads_1[7];
+    kal_uint8       bFirstInterfaceNumber;
+    kal_uint8       bInterfaceCount;
+    kal_uint8       compatibleID[8];
+    kal_uint8       subcompatibleID[8];
+    kal_uint8       bPads_2[6];
+} usbc_ext_compat_id_os_feature_descriptor_t;
+PRAGMA_END_PACK_STRUCT
+
+/*
+ * USB 3.0 BOS descriptor.
+ */
+#define USBC_BOS_DESC_SIZE                          5
+#define USBC_MAX_BOS_SIZE \
+            ( USBC_BOS_DESC_SIZE + \
+              USBC_SUPERSPEED_USB_DEV_CAP_DESC_SIZE + \
+              USBC_USB20_EXT_DEV_CAP_DESC_SIZE )
+
+#define USBC_GET_BOS_TOTAL_LENGTH(_desc) \
+            USBC_GET_UINT16(_desc, 2)
+#define USBC_SET_BOS_TOTAL_LENGTH(_desc, _value) \
+            USBC_SET_UINT16(_desc, 2, _value)
+
+/*
+ * USB 2.0 Extension descriptor.
+ */
+#define USBC_USB20_EXT_DEV_CAP_DESC_SIZE            7
+
+/*
+ * SuperSpeed USB Device Capabilities descriptor.
+ */
+#define USBC_SUPERSPEED_USB_DEV_CAP_DESC_SIZE       10
+
+/*
+ * SuperSpeed Endpoint Companion descriptor.
+ */
+#define USBC_ENDPOINT_COMPANION_DESC_SIZE           6
+
+#define USBC_GET_EPC_MAX_BURST(_desc) \
+            USBC_GET_UINT8(_desc, 2)
+#define USBC_SET_EPC_MAX_BURST(_desc, _value) \
+            USBC_SET_UINT8(_desc, 2, _value)
+
+#define USBC_GET_EPC_ATTRIBUTES(_desc) \
+            USBC_GET_UINT8(_desc, 3)
+#define USBC_SET_EPC_ATTRIBUTES(_desc, _value) \
+            USBC_SET_UINT8(_desc, 3, _value)
+
+#define USBC_GET_EPC_BYTES_PER_INTERVAL(_desc) \
+            USBC_GET_UINT16(_desc, 4)
+#define USBC_SET_EPC_BYTES_PER_INTERVAL(_desc, _value) \
+            USBC_SET_UINT16(_desc, 4, _value)
+
+#endif  // _USBCORE_USBSTD_H
diff --git a/mcu/middleware/hif/interface/usbidle_if.h b/mcu/middleware/hif/interface/usbidle_if.h
new file mode 100644
index 0000000..9814f15
--- /dev/null
+++ b/mcu/middleware/hif/interface/usbidle_if.h
@@ -0,0 +1,57 @@
+/*!
+ *  @file usbidle_main.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main definitions of usbcore
+ */
+
+#ifndef _USBIDLE_IF_H
+#define _USBIDLE_IF_H
+
+typedef struct {
+    LOCAL_PARA_HDR
+    kal_bool notify_suspend;
+    kal_bool notify_suspend_with_remote_wk;
+}usbcore_usbidle_l4_power_saving_req_struct;
+
+void usb_idle_set_clockGating(kal_bool);
+
+void usb_idle_set_l4_power_saving(kal_bool);
+
+void usb_idle_event_notify_to_l4(kal_bool, kal_bool);
+
+#endif  // _USBIDLE_IF_H
+
diff --git a/mcu/middleware/hif/ipcore/include/ipc_config.h b/mcu/middleware/hif/ipcore/include/ipc_config.h
new file mode 100644
index 0000000..fa7643a
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_config.h
@@ -0,0 +1,110 @@
+#if defined(__L1_STANDALONE__) || defined(__L1EDPS_ENABLE__)
+#if defined(__LTM_SIMULATION_SUPPORT__)
+IPC_MODULE_ID(MOD_LTM_SIM)
+IPC_MODULE_PREFIX(lms)
+#endif
+#if defined(__ETHERCORE_SUPPORT__)
+IPC_MODULE_ID(MOD_ETHERCORE)
+IPC_MODULE_PREFIX(ethc_core)
+#endif
+#if defined(__DPFM_SUPPORT__)
+IPC_MODULE_ID(MOD_DPFM)
+IPC_MODULE_PREFIX(dpfm)
+#endif
+/*
+	For L1-only mode, L4 related modules are not included.
+
+	__L1_STANDALONE__ : Used in 23G
+	__L1EDPS_ENABLE__ : Used in 4G
+*/
+#else
+
+/************************* IP Core Modue Begin ******************/
+#if defined(__UMTS_RAT__) || defined(__GSM_RAT__)
+IPC_MODULE_ID(MOD_RATDM)
+IPC_MODULE_PREFIX(ratdm_multimode)
+#if defined(__GEMINI__)
+IPC_MODULE_ID(MOD_RATDM_2)
+IPC_MODULE_PREFIX(ratdm_multimode)
+#if (GEMINI_PLUS >= 3)
+IPC_MODULE_ID(MOD_RATDM_3)
+IPC_MODULE_PREFIX(ratdm_multimode)
+#if (GEMINI_PLUS >= 4)
+IPC_MODULE_ID(MOD_RATDM_4)
+IPC_MODULE_PREFIX(ratdm_multimode)
+#endif /* GEMINI_PLUS >= 4 */
+#endif /* GEMINI_PLUS >= 3 */
+#endif /* __GEMINI__ */
+#endif /* __UMTS_RAT__ || __GSM_RAT__ */
+/************************* IP Core Modue End ******************/
+/************************* IP Core Modue Begin ******************/
+IPC_MODULE_ID(MOD_UPCM)
+IPC_MODULE_PREFIX(upcm)
+#ifdef __GEMINI__
+IPC_MODULE_ID(MOD_UPCM_2)
+IPC_MODULE_PREFIX(upcm)
+#if (GEMINI_PLUS >= 3)
+IPC_MODULE_ID(MOD_UPCM_3)
+IPC_MODULE_PREFIX(upcm)
+#if (GEMINI_PLUS >= 4)
+IPC_MODULE_ID(MOD_UPCM_4)
+IPC_MODULE_PREFIX(upcm)
+#endif /* GEMINI_PLUS >= 4 */
+#endif /* GEMINI_PLUS >= 3 */
+#endif /* __GEMINI__ */
+
+
+/************************* IP Core Modue End ******************/
+/************************* IP Core Modue Begin ******************/
+#if defined(__LTM_SIMULATION_SUPPORT__)
+IPC_MODULE_ID(MOD_LTM_SIM)
+IPC_MODULE_PREFIX(lms)
+#endif
+/************************* IP Core Modue End ******************/
+/************************* IP Core Modue Begin ******************/
+#if defined(__LTM_EPDCP_SIMULATION_SUPPORT__)
+IPC_MODULE_ID(MOD_EPDCP)
+IPC_MODULE_PREFIX(ltm_epdcp)
+#endif
+/************************* IP Core Modue End ******************/
+/************************* IP Core Modue Begin ******************/
+#if defined(__TMC_SUPPORT__)
+IPC_MODULE_ID(MOD_TMC)
+IPC_MODULE_PREFIX(tmc)
+#endif
+/************************* IP Core Modue End ******************/
+/************************* IP Core Modue Begin ******************/
+#if defined(__ETHERCORE_SUPPORT__)
+IPC_MODULE_ID(MOD_ETHERCORE)
+IPC_MODULE_PREFIX(ethc_core)
+#endif
+/************************* IP Core Modue End ******************/
+/************************* IP Core Modue Begin ******************/
+#if defined(__DPFM_SUPPORT__)
+IPC_MODULE_ID(MOD_DPFM)
+IPC_MODULE_PREFIX(dpfm)
+#endif
+/************************* IP Core Modue End ******************/
+/************************* IP Core Modue Begin ******************/
+IPC_MODULE_ID(MOD_IPC_FRAGMENT)
+IPC_MODULE_PREFIX(ipc_fragment)
+/************************* IP Core Modue End ******************/
+/************************* IP Core Modue Begin ******************/
+#if defined(__DISPATCHER_SUPPORT__)
+IPC_MODULE_ID(MOD_DISPATCHER)
+IPC_MODULE_PREFIX(dispatcher)
+#ifdef __GEMINI__
+IPC_MODULE_ID(MOD_DISPATCHER_2)
+IPC_MODULE_PREFIX(dispatcher)
+#if (GEMINI_PLUS >= 3)
+IPC_MODULE_ID(MOD_DISPATCHER_3)
+IPC_MODULE_PREFIX(dispatcher)
+#if (GEMINI_PLUS >= 4)
+IPC_MODULE_ID(MOD_DISPATCHER_4)
+IPC_MODULE_PREFIX(dispatcher)
+#endif /* GEMINI_PLUS >= 4 */
+#endif /* GEMINI_PLUS >= 3 */
+#endif /* __GEMINI__ */
+#endif
+/************************* IP Core Modue End ******************/
+#endif /* __L1_STANDALONE__ || __L1EDPS_ENABLE__ */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_data.h b/mcu/middleware/hif/ipcore/include/ipc_data.h
new file mode 100644
index 0000000..846b928
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_data.h
@@ -0,0 +1,912 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2016
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_data.h
+ *
+ * Project:
+ * --------
+ *   UMOLYA
+ *
+ * Description:
+ * ------------
+ *   IP Core Uplink/Downlink data path implementation.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_DATA_H
+#define __INC_IPC_DATA_H
+
+#include "kal_public_api.h"
+#include "upcm.h"
+#include "upcm_did.h"
+#include "dpcopro_custom.h"
+#include "dispatcher_if.h"
+
+#include "ipc_defs.h"
+#include "ipc_struct.h"
+#include "lms_api.h"
+#include "el2_public_api.h"
+
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+#define IPC_PROXY_IPV6_RA_POOL_SIZE 256
+
+/* Free Copro vrb helper macro */
+#define IPC_FREE_META_VRB(_meta) \
+    do { \
+        IPC_ASSERT(_meta); \
+        IPC_UL_PKT_DUMP(_meta->vrb_addr, _meta->length); \
+        copro_vrb_release(_meta->vrb_addr, _meta->length, VRB_USER_IPCORE_TASK); \
+    } while (0)
+
+/* Free DID list w/ data ptr helper macro */
+#define IPC_FREE_DID_W_DATABUF(_did_head, _did_tail, _hif_type) \
+    do { \
+        ipc_utils_pkt_dump_did(_did_head, _did_tail, _hif_type); \
+        upcm_did_dest_q_free_buf(_did_head, _did_tail); \
+    } while (0);
+
+/* Allocate & Free prb helper macro */
+#define IPC_PRB_DL_ID PRB_TYPE_DL_IP_FRAG
+#define IPC_ALLOCATE_PRBM prbm_allocate
+#define IPC_FREE_PRBM prbm_release
+
+#if IPC_PEER==IPC_PEER_LTM_SIM
+    #if defined(__LTM_SIMULATION_SUPPORT__)
+        #define _IPC_REG_CBK_DLVR_DL_SDU lms_reg_cbk_dlvr_dl_sdu
+        #define _IPC_REG_CBK_NOTIFY_LTE_TICK_SOURCE lms_reg_cbk_notify_tick_source
+        #define _IPC_FORWARD_UL_SDU lms_rcv_ul_sdu
+        #define _IPC_FORWARD_UL_SDU_BY_EBI lms_rcv_ul_sdu_by_ebi
+        #define _IPC_FORWARD_UL_META lms_rcv_ul_sdu_meta
+        #define _IPC_QUERY_META_TABLE lhif_query_meta_table
+        #define _IPC_FORCED_SW_PATH_BY_PDN lms_forced_sw_path_by_pdn
+        #define _IPC_FORCED_SW_PATH_BY_EBI lms_forced_sw_path_by_ebi
+        #define _IPC_FORCED_SW_PATH_ALL lms_forced_sw_path_all
+        #define _IPC_NOTIFY_L2_STATS enpdcp_ipcore_unknown_header_statistics
+        #define _IPC_SEND_RA_DL(_p_head_gpd, _netif_id)     ipc_send_dl_pkt_enqueue(_p_head_gpd, _netif_id, IPC_IP_TYPE_IPV6)
+    #else
+        #define "Please define turn on LTM_SIMULATION_SUPPORT while setting IPC_PEER as IPC_PEER_LTM_SIM!"
+    #endif
+#elif IPC_PEER==IPC_PEER_UPCM
+    #define _IPC_REG_CBK_DLVR_DL_SDU upcm_reg_cbk_dlvr_dl_sdu
+    #define _IPC_REG_CBK_NOTIFY_LTE_TICK_SOURCE upcm_reg_cbk_notify_lte_tick
+    #define _IPC_FORWARD_UL_SDU upcm_rcv_ul_sdu_93_gpd
+    #define _IPC_FORWARD_UL_SDU_BY_EBI upcm_rcv_ul_sdu_by_ebi_93_gpd
+    #define _IPC_FORWARD_UL_META upcm_rcv_ul_sdu_93
+    #define _IPC_QUERY_META_TABLE lhif_query_meta_table
+    #define _IPC_FORCED_SW_PATH_BY_PDN upcm_forced_sw_path_by_pdn
+    #define _IPC_FORCED_SW_PATH_BY_EBI upcm_forced_sw_path_by_ebi
+    #define _IPC_FORCED_SW_PATH_ALL upcm_forced_sw_path_all
+    #define _IPC_NOTIFY_L2_STATS enpdcp_ipcore_unknown_header_statistics
+    #define _IPC_SEND_RA_DL(_p_head_gpd, _netif_id)     tcpip_rsra_proxy_bind_complete(_p_head_gpd, _netif_id)
+#elif IPC_PEER==IPC_PEER_UT
+    #define _IPC_REG_CBK_DLVR_DL_SDU ipc_ut_reg_cbk_dlvr_dl_sdu
+    #define _IPC_REG_CBK_NOTIFY_LTE_TICK_SOURCE ipc_ut_reg_cbk_notify_tick_source
+    #define _IPC_FORWARD_UL_SDU ipc_ut_rcv_ul_sdu
+    #define _IPC_FORWARD_UL_SDU_BY_EBI ipc_ut_rcv_ul_sdu_by_ebi
+    #define _IPC_FORWARD_UL_META ipc_ut_rcv_ul_sdu_meta
+    #define _IPC_QUERY_META_TABLE ipc_ut_query_meta_table
+    #define _IPC_FORCED_SW_PATH_BY_PDN(...)
+    #define _IPC_FORCED_SW_PATH_BY_EBI(...)
+    #define _IPC_FORCED_SW_PATH_ALL(...)
+    #define _IPC_NOTIFY_L2_STATS ipc_ut_notify_l2
+    #define _IPC_SEND_RA_DL(_p_head_gpd, _netif_id)     ipc_send_dl_pkt_enqueue(_p_head_gpd, _netif_id, IPC_IP_TYPE_IPV6)
+
+    #undef IPC_FREE_META_VRB
+    #define IPC_FREE_META_VRB
+    #define upcm_did_dest_q_free_buf upcm_did_dest_q
+#elif IPC_PEER==IPC_PEER_NULL_DROP || IPC_PEER==IPC_PEER_NULL_LOOPBACK
+    #define _IPC_REG_CBK_DLVR_DL_SDU(...)
+    #define _IPC_REG_CBK_NOTIFY_LTE_TICK_SOURCE(...)
+    #define _IPC_FORWARD_UL_SDU(...)
+    #define _IPC_FORWARD_UL_SDU_BY_EBI(...)
+    #define _IPC_FORWARD_UL_META(...)
+    #define _IPC_QUERY_META_TABLE(...)
+    #define _IPC_FORCED_SW_PATH_BY_PDN(...)
+    #define _IPC_FORCED_SW_PATH_BY_EBI(...)
+    #define _IPC_FORCED_SW_PATH_ALL(...)
+    #define _IPC_NOTIFY_L2_STATS enpdcp_ipcore_unknown_header_statistics
+    #define _IPC_SEND_RA_DL(_p_head_gpd, _netif_id)     ipc_send_dl_pkt_enqueue(_p_head_gpd, _netif_id, IPC_IP_TYPE_IPV6)
+#elif IPC_PEER==IPC_PEER_DISPATCHER
+    #define _IPC_REG_CBK_DLVR_DL_SDU ipc_reg_cbk_dlvr_dl_did
+    #define _IPC_REG_CBK_NOTIFY_LTE_TICK_SOURCE upcm_reg_cbk_notify_lte_tick
+    #define _IPC_FORWARD_UL_SDU dispatcher_rcv_ul_gpd_by_pdn
+    #define _IPC_FORWARD_UL_SDU_BY_EBI dispatcher_rcv_ul_gpd_by_ebi
+    #define _IPC_FORWARD_UL_META dispatcher_rcv_ul_meta_queue
+    #define _IPC_QUERY_META_TABLE lhif_query_meta_table
+    #define _IPC_FORCED_SW_PATH_BY_PDN upcm_forced_sw_path_by_pdn
+    #define _IPC_FORCED_SW_PATH_BY_EBI upcm_forced_sw_path_by_ebi
+    #define _IPC_FORCED_SW_PATH_ALL upcm_forced_sw_path_all
+    #define _IPC_NOTIFY_L2_STATS enpdcp_ipcore_unknown_header_statistics
+    #define _IPC_SEND_RA_DL(_p_head_gpd, _netif_id)     tcpip_rsra_proxy_bind_complete(_p_head_gpd, _netif_id)
+#else
+    #error "Unknown peer module of IPCORE!"
+#endif
+
+#define IPC_REG_CBK_DLVR_DL_SDU _IPC_REG_CBK_DLVR_DL_SDU
+#define IPC_REG_CBK_NOTIFY_LTE_TICK_SOURCE _IPC_REG_CBK_NOTIFY_LTE_TICK_SOURCE
+#define IPC_FORWARD_UL_SDU(_ip_type, _pdn_id, _p_head, _p_tail) \
+    do { \
+        kal_uint32 _pdn_id_tmp = _pdn_id; \
+        kal_uint8 _proto_idx; \
+        IPC_RETRIEVE_PROTOID_FROM_PDNID(_pdn_id_tmp, _proto_idx); \
+        IPC_UNMASK_PROTOID_FROM_PDNID(_pdn_id_tmp); \
+        ipc_utils_pkt_dump_buff_gpd_list(_p_head, _p_tail, KAL_TRUE); \
+        _IPC_FORWARD_UL_SDU(_ip_type, _pdn_id_tmp, _p_head, _p_tail, _proto_idx); \
+    } while (0)
+#define IPC_FORWARD_UL_SDU_BY_EBI(_ebi, _p_head, _p_tail) \
+    do { \
+        kal_uint32 _ebi_tmp = _ebi; \
+        kal_uint8 _proto_idx; \
+        IPC_RETRIEVE_PROTOID_FROM_PDNID(_ebi_tmp, _proto_idx); \
+        IPC_UNMASK_PROTOID_FROM_PDNID(_ebi_tmp); \
+        ipc_utils_pkt_dump_buff_gpd_list(_p_head, _p_tail, KAL_TRUE); \
+        _IPC_FORWARD_UL_SDU_BY_EBI(_ebi_tmp, _p_head, _p_tail, _proto_idx); \
+    } while (0)
+#define IPC_FORWARD_UL_META(_start_idx, _end_idx, _q_type) \
+    do { \
+        _IPC_FORWARD_UL_META(_start_idx, _end_idx, _q_type); \
+    } while (0)
+#define IPC_QUERY_META_TABLE _IPC_QUERY_META_TABLE
+#define IPC_FORCED_SW_PATH_BY_PDN(_pdn_id, _is_set) \
+    do { \
+        kal_uint32 _pdn_id_tmp = _pdn_id; \
+        kal_uint8 _proto_idx; \
+        IPC_RETRIEVE_PROTOID_FROM_PDNID(_pdn_id_tmp, _proto_idx); \
+        IPC_UNMASK_PROTOID_FROM_PDNID(_pdn_id_tmp); \
+        _IPC_FORCED_SW_PATH_BY_PDN(_pdn_id_tmp, _is_set, _proto_idx); \
+    } while (0)
+#define IPC_FORCED_SW_PATH_BY_EBI(_ebi, _is_set) \
+    do { \
+        kal_uint32 _ebi_tmp = _ebi; \
+        kal_uint8 _proto_idx; \
+        IPC_RETRIEVE_PROTOID_FROM_PDNID(_ebi_tmp, _proto_idx); \
+        IPC_UNMASK_PROTOID_FROM_PDNID(_ebi_tmp); \
+        _IPC_FORCED_SW_PATH_BY_EBI(_ebi_tmp, _is_set, _proto_idx); \
+    } while (0)
+#define IPC_FORCED_SW_PATH_ALL _IPC_FORCED_SW_PATH_ALL
+#define IPC_SEND_RA_DL(_p_head_gpd, _netif_id) \
+do { \
+    _IPC_SEND_RA_DL(_p_head_gpd, _netif_id); \
+} while (0)
+
+/*------------------------------------------------------------------------------
+ * Internal data structure defintion.
+ *----------------------------------------------------------------------------*/
+typedef struct _ipc_internal_ior_t {
+    ipc_io_request_t    io_req;
+    union {
+        ipc_netif_t    *netif;
+        kal_uint8       ebi;
+        kal_uint8       pdn;
+        kal_uint32      netif_id;
+    };
+} ipc_internal_ior_t;
+
+typedef struct _ipc_dlq_ior_t {
+    ipc_netif_t    *netif;
+    ipc_session_t  *session;
+    kal_uint32      netif_id;
+    kal_uint32      session_type;
+} ipc_dlq_ior_t;
+
+typedef enum _ipc_ul_queue_type_e {
+    IPC_UL_QUEUE_TYPE_IOR,
+    IPC_UL_QUEUE_TYPE_META,
+    IPC_UL_QUEUE_TYPE_MAX,
+} ipc_ul_queue_type_e;
+
+typedef enum _ipc_ul_queue_priority_e {
+    IPC_UL_QUEUE_PRIORITY_HIGH,
+    IPC_UL_QUEUE_PRIORITY_LOW,
+    IPC_UL_QUEUE_PRIORITY_MAX,
+} ipc_ul_queue_priority_e;
+
+typedef struct _ipc_ul_queue_t ipc_ul_queue_t;
+typedef struct _ipc_ul_queue_t {
+    IPC_DECLARE_OBJECT
+
+    ipc_ul_queue_type_e     queue_type;
+    ipc_ul_queue_priority_e priority;
+    kal_uint32              cnt; // Totol count of IOR/meta in this queue.
+    kal_uint32              pending_cnt; // Pending count of IOR/meta in this queue.
+    union {
+        struct {
+            ipc_internal_ior_t *ior_head;
+            ipc_internal_ior_t *ior_tail;
+        };
+        struct {
+            kal_int32           meta_head;
+            kal_int32           meta_tail;
+            kal_int32           meta_queue_size;
+            LHIF_QUEUE_TYPE     meta_queue_type;
+        };
+    };
+    void                    (*ipc_clear_callback_t)(ipc_ul_queue_t *ul_queue);
+    void                    (*ipc_process_callback_t)(ipc_ul_queue_t *ul_queue);
+} ipc_ul_queue_t;
+
+#define _IPC_GET_UL_QUEUE_INDEX(_q_type, _q_priority) ((_q_type * IPC_UL_QUEUE_PRIORITY_MAX) + _q_priority)
+
+#define IPC_UL_QUEUE_NUM             (IPC_UL_QUEUE_TYPE_MAX * IPC_UL_QUEUE_PRIORITY_MAX)
+#define IPC_QUEUE_META_INVALID_VALUE -1
+#define IPC_DL_QUEUE_NUM             (IPC_MAX_SESSION_CNT + 1)
+#define IPC_DL_NON_PDN_QUEUE_IDX     (IPC_DL_QUEUE_NUM - 1)
+#define IPC_DL_QUEUE_DID_MAP_SIZE    3
+
+typedef enum _ipc_did_queue_type_e {
+    IPC_DID_QUEUE_TYPE_DEFAULT,    /*< it was normal DL path, it will enter filter stage */
+    IPC_DID_QUEUE_TYPE_WO_FILTER,  /*< it will not entered filter stage */
+    IPC_DID_QUEUE_TYPE_DPFM,        /*< it was ued for DPFM */
+    IPC_DID_QUEUE_TYPE_USB_PATH,   /*< it was MD internal DL path, it was not entered filter stage */
+    IPC_DID_QUEUE_TYPE_MAX,
+} ipc_did_queue_type_e;
+
+typedef struct _ipc_did_queue_t {
+    upcm_did       *did_head;
+    upcm_did       *did_tail;
+    kal_uint32     si_index;      //current si index for tail DID
+} ipc_did_queue_t;
+
+typedef struct _ipc_dl_queue_t {
+    ipc_did_queue_t did_queues[IPC_DID_QUEUE_TYPE_MAX];
+} ipc_dl_queue_t;
+
+typedef enum _ipc_test_loopback_mode_e {
+    IPC_TEST_LOOPBACK_MODE_OFF,
+    IPC_TEST_LOOPBACK_MODE_A,
+    IPC_TEST_LOOPBACK_MODE_B,
+} ipc_test_loopback_mode_e;
+
+typedef struct _ipc_meta_info_des {
+    kal_uint32 len;
+    kal_uint16 psn_countL;
+    void *addr;
+} ipc_meta_info_des;
+
+#if defined(__MD97__)
+
+#define IPC_DATA_RQ_INFO_TABLE_NUM 128                   /*< Assume "MTBL_ENTRY_NUM_DL_IPF = 1" */
+#define IPC_DATA_GET_QFI(val)      (val & 0x3F)
+#define IPC_DATA_GET_RQI(val)      ((val & 0x40) >> 6)
+
+typedef enum _ipc_data_src_qfi_e {
+    IPC_DATA_QFI_SRC_IPF_META,
+    IPC_DATA_QFI_SRC_DL_DID,
+} ipc_data_src_qfi_e;
+
+typedef struct _ipc_data_rq_info_list {
+    kal_uint32 cnt;
+    ipc_rq_info_t rq_info_list[IPC_DATA_RQ_INFO_TABLE_NUM];
+} ipc_data_rq_info_list;
+
+#endif
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+extern kal_uint32               ipc_em_on_s;
+extern ipc_test_loopback_mode_e ipc_test_loopback_mode_s;
+extern kal_uint32               ipc_test_loopback_a_netif_id_s;
+extern kal_uint32               ipc_test_loopback_b_netif_id_s;
+extern kal_bool                 ipc_ul_processing_s;
+extern kal_bool                 ipc_ul_reload_retrying_s;
+extern event_scheduler         *ipc_es_ul_throttle_s; /* Timer for UL throttle mechanism. */
+
+/*------------------------------------------------------------------------------
+ * General Function prototype.
+ *----------------------------------------------------------------------------*/
+
+/**
+ * Init uplink and downlink queue structures
+ *
+ * @return return KAL_TRUE when succeeded, otherwise return KAL_FALSE.
+ */
+kal_bool ipc_queue_init();
+
+/*
+ * Check whether uplink queues are empty or not.
+ *
+ * @return  return KAL_TRUE if empty, otherwise return KAL_FALSE.
+ *
+ * @note    ipc_spinlock_g is acquired. This function should be very light. MUST NOT do any heavy jobs.
+ */
+kal_bool ipc_are_ul_queues_empty();
+
+/*
+ * Get IP TYPE from packet header (do cache invalidation automatically).
+ *
+ * @return  return IPC_IP_TYPE_IPV4 / IPC_IP_TYPE_IPV6 according to IP_TYPE. Otherwise return IPC_IP_TYPE_INVALID.
+ *
+ * @note
+ */
+kal_uint8 ipc_get_ip_type_from_meta(lhif_meta_tbl_t *meta);
+
+/*
+ * Obtain netif id from UL LHIF meta info (net_type & channel_id).
+ *
+ * @return  return netif_id.
+ *
+ * @note
+ */
+kal_uint32 ipc_get_netif_id_from_meta(kal_uint8 net_type, kal_uint8 channel_id);
+
+/*
+ * Get session context based on netif id.
+ *
+ * @return  void.
+ *
+ * @note
+ */
+void ipc_get_pdn_id_from_netif(kal_uint32 *ipv4_pdn_id, kal_uint32 *ipv6_pdn_id, ipc_netif_t *netif);
+
+/*------------------------------------------------------------------------------
+ * Uplink Function prototype.
+ *----------------------------------------------------------------------------*/
+
+/**
+ * Fill PDN id into Uplink META.
+ *
+ * @param   ip_type [IN] The IP type of the packet.
+ * @param   ipv4_pdn_id [IN] The PDN id of IPv4 session.
+ * @param   ipv6_pdn_id [IN] The PDN id of IPv6 session.
+ * @param   netif_id [IN] the identify of the NETIF which the META comes from.
+ * @param   meta [IN] The META descriptor pointer of the packet.
+ */
+void ipc_fill_session_info_into_meta(kal_uint8 ip_type, kal_uint32 ipv4_pdn_id, kal_uint32 ipv6_pdn_id, kal_uint32 netif_id, lhif_meta_tbl_t *meta);
+
+/**
+ * Enqueue IOR list to Uplink IOR queue.
+ * This function will be called by ipc_uplink().
+ *
+ * @param   head_ior [IN] The head of the IOR list.
+ * @param   tail_ior [IN] The tail of the IOR list.
+ * @param   ior_cnt [IN] The number of the IOR in IOR list.
+ * @param   q_priority [IN] The priority of the IOR queue.
+ */
+void ipc_push_ior_list_to_ior_queue(ipc_io_request_t *head_ior, ipc_io_request_t *tail_ior, kal_uint32 ior_cnt, ipc_ul_queue_priority_e q_priority);
+
+/**
+ * Enqueue META list to Uplink META queue.
+ * This function will be called by ipc_meta_uplink().
+ *
+ * @param   start_idx [IN] The started index of the META list.
+ * @param   end_idx [IN] The ended index of the META list.
+ * @param   q_type [IN] The type of the LHIF queue where the META comes from.
+ */
+void ipc_push_meta_list_to_meta_queue(kal_uint16 start_idx, kal_uint16 end_idx, LHIF_QUEUE_TYPE q_type);
+
+/**
+ * Uplink data path entrance function of IPCore context.
+ * Check, process and forward each uplink queue.
+ */
+void ipc_on_process_ul_queue(void);
+
+/**
+ * Retry reloading uplink RxGPD queue of netifs
+ */
+void ipc_on_retry_ul_reload(void);
+
+/*------------------------------------------------------------------------------
+ * Downlink Function prototype.
+ *----------------------------------------------------------------------------*/
+
+/**
+ * Dequeue DID list from internal Downlink DID queue.
+ *
+ * @param   pp_did_head [OUT] Head of a list of DIDs.
+ * @param   pp_did_tail [OUT] Tail of a list of DIDs.
+ * @param   pp_si_idx [OUT] sit index of DIDs.
+ * @param   pdn_id [IN] queue index.
+ * @param   queue_type [IN] Downlink queue type of the queue.
+ */
+void ipc_did_internal_queue_dequeue(upcm_did **pp_did_head, upcm_did **pp_did_tail, kal_uint32 **pp_si_idx, kal_uint8 pdn_id, ipc_did_queue_type_e queue_type);
+
+/**
+ * Enqueue DID list to Downlink DID IPC_DID_QUEUE_TYPE_WO_FILTER queue.
+ *
+ * @param   did_head  [IN] Head of a list of DIDs.
+ * @param   did_tail  [IN] Tail of a list of DIDs.
+ * @param   queue_idx [IN] Downlink queue index of the queue.
+ * @param   position  [IN] enqueue did to tail or head.
+ */
+void ipc_did_enqueue_wo_filter_queue(upcm_did *did_head, upcm_did *did_tail, kal_uint32 queue_idx, ipc_data_enq_position_e position);
+
+/**
+ * Enqueue DID list to Downlink DID IPC_DID_QUEUE_TYPE_DPFM queue.
+ *
+ * @param   did_head  [IN] Head of a list of DIDs.
+ * @param   did_tail  [IN] Tail of a list of DIDs.
+ * @param   queue_idx [IN] Downlink queue index of the queue.
+ * @param   position  [IN] enqueue did to tail or head.
+ */
+void ipc_did_enqueue_dpfm_queue(upcm_did *did_head, upcm_did *did_tail, kal_uint32 queue_idx, ipc_data_enq_position_e position);
+
+
+/**
+ * Enqueue DID list to Downlink DID IPC_DID_QUEUE_TYPE_DEFAULT queue.
+ *
+ * @param   did_head  [IN] Head of a list of DIDs.
+ * @param   did_tail  [IN] Tail of a list of DIDs.
+ * @param   queue_idx [IN] Downlink queue index of the queue.
+ * @param   position  [IN] enqueue did to tail or head.
+ */
+void ipc_did_enqueue_default_queue(upcm_did *did_head, upcm_did *did_tail, kal_uint32 queue_idx, ipc_data_enq_position_e position);
+
+/**
+ * Downlink retry function.
+ * Try to re-send DID to netif which can't receive DID in last time.
+ */
+void ipc_on_process_dl_queue(void);
+
+/**
+ * Downlink data path entrance function.
+ *
+ * @param   pdn_id [IN] PDN ID where the GPD's come from.
+ * @param   p_head [IN] Head of a list of GPDs.
+ * @param   p_tail [IN] Tail of a list of GPDs.
+ */
+void ipc_on_downlink(kal_uint32 pdn_id, qbm_gpd *p_head, qbm_gpd *p_tail);
+
+/**
+ * Downlink data path entrance function (Multiple PS version).
+ *
+ * @param   pdn_id [IN] PDN ID where the GPD's come from.
+ * @param   p_head [IN] Head of a list of GPDs.
+ * @param   p_tail [IN] Tail of a list of GPDs.
+ * @param   proto_idx [IN] The index to distinquish from different SIM Card.
+ */
+void ipc_on_downlink_multiple_ps(kal_uint32 pdn_id, qbm_gpd *p_head, qbm_gpd *p_tail, kal_uint8 proto_idx);
+
+/**
+ * Downlink data path entrance function (Gen93).
+ *
+ * @param   pdn_id [IN] PDN ID where the DID's come from.
+ * @param   queue_type [IN] The type of DID queue.
+ * @param   did_head [IN] Head of a list of DIDs.
+ * @param   did_tail [IN] Tail of a list of DIDs.
+ */
+void ipc_on_did_downlink(kal_uint32 pdn_id, ipc_did_queue_type_e queue_type, upcm_did *did_head, upcm_did *did_tail);
+
+/**
+ * Downlink data path entrance function (Gen93 Multiple PS version).
+ *
+ * @param   pdn_id [IN] PDN ID where the DID's come from.
+ * @param   did_head [IN] Head of a list of DIDs.
+ * @param   did_tail [IN] Tail of a list of DIDs.
+ * @param   proto_idx [IN] The index to distinquish from different SIM Card.
+ */
+void ipc_on_did_downlink_multiple_ps(kal_uint32 pdn_id, upcm_did *did_head, upcm_did *did_tail, kal_uint8 proto_idx);
+
+/**
+ * Downlink data path entrance function (Gen93).
+ *
+ * @param   pdn_id [IN] PDN ID where the DID's come from.
+ * @param   did_head [IN] Head of a list of DIDs.
+ * @param   did_tail [IN] Tail of a list of DIDs.
+ * @param   proto_idx [IN] The index to distinquish from different SIM Card.
+ */
+void ipc_on_did_downlink_test_mode(kal_uint32 pdn_id, upcm_did *did_head, upcm_did *did_tail, kal_uint8 proto_idx);
+
+/**
+ * Downlink data path entrance function (Gen93).
+ *
+ * @param   pdn_id [IN] PDN ID where the DID's come from.
+ * @param   did_head [IN] Head of a list of DIDs.
+ * @param   did_tail [IN] Tail of a list of DIDs.
+ */
+void ipc_did_downlink_enqueue(kal_uint32 pdn_id, upcm_did *did_head, upcm_did *did_tail);
+
+/**
+ * Downlink data path entrance function (Gen93).
+ */
+void ipc_did_downlink_dequeue();
+
+/**
+ * Downlink data path entrance function (QBM).
+ *
+ * @param   pdn_id [IN] PDN ID where the GPD's come from.
+ * @param   head [IN] Head of a list of GPDs.
+ * @param   tail [IN] Tail of a list of GPDs.
+ */
+void ipc_on_downlink_qbm_enqueue(qbm_gpd *head, qbm_gpd *tail);
+
+/**
+ * Downlink data path entrance function (QBM).
+ */
+void ipc_data_qbm_downlink_dequeue(void);
+
+/**
+ * Clear downlink ILM request flag (take/give spinlock).
+ */
+void ipc_data_clear_dl_ilm_flag();
+
+/**
+ * Check whether sending downlink ILM request (take/give spinlock).
+ * @retval  KAL_FALSE   no need to send ILM
+ * @retval  KAL_TRUE    need to send ILM
+ */
+kal_bool ipc_data_check_and_set_dl_ilm_flag();
+
+#if defined(__MD97__)
+/**
+ * Updated rq_info with packet desciptor (Gen97).
+ *
+ * @param   p_rq_info  updated rq_info struct
+ * @param   pdn_id     PDN ID
+ * @param   p_pkt_info packet descriptor
+ * @param   src_qfi    QFI source from meta or did
+ * @return  return KAL_FALSE if parameters are invalid
+ */
+kal_bool ipc_data_set_rq_info(ipc_rq_info_t *p_rq_info, kal_uint32 pdn_id, ipc_pkt_des_t *p_pkt_info, ipc_data_src_qfi_e src_qfi);
+
+/**
+ * Insert rq_info into rq_info list (Gen97).
+ *
+ * @param   p_rq_list  updated rq_info list struct
+ * @param   p_rq_info  updated rq_info struct
+ */
+void ipc_data_saved_rq_info_list(ipc_data_rq_info_list *p_rq_list, ipc_rq_info_t *p_rq_info);
+
+/**
+ * Sent did list to the netif (Gen97).
+ *
+ * @param   netif_id    sent prepared did list to the netif_id
+ * @param   p_did_head  did head pointer
+ * @param   p_did_tail  did tail pointer
+ */
+void ipc_data_dl_enq_by_netif(kal_uint32 netif_id, upcm_did *p_did_head, upcm_did *p_did_tail);
+
+/**
+ * Sent rq_info list to NAS (Gen97).
+ *
+ * @param   p_rq_list   rq_info struct
+ * @return  return KAL_FALSE if parameters are invalid
+ */
+kal_bool ipc_data_send_rq_info(ipc_data_rq_info_list *p_rq_list);
+#endif
+
+/*------------------------------------------------------------------------------
+ * Uplink Data Throttling Function prototype.
+ *----------------------------------------------------------------------------*/
+
+/**
+ * Init throttling timer.
+ */
+void ipc_timer_init();
+
+/**
+ * Function to control throttling states.
+ *
+ * @param   local_para_ptr [IN] local parameters of ILM.
+ */
+void ipc_set_ul_throttle(local_para_struct *local_para_ptr);
+
+/**
+ * Function to update throttling status on EM.
+ */
+void ipc_em_send_ul_throttle_status(void);
+
+/**
+ * Function to indicate the status change of IMS emergency call.
+ *
+ * @param   local_para_ptr [IN] local parameters of ILM.
+ */
+void ipc_ims_emergency_call_ind_handler(local_para_struct *local_para_ptr);
+
+/**
+ * Function to drop the UL packets when PDN is unbinded and UL is throttled.
+ *
+ * @param   pdn_id [IN] unbinded PDN ID.
+ */
+void ipc_data_drop_ul_meta_by_pdn(kal_uint8 pdn_id);
+
+#ifdef ATEST_SYS_IPCORE
+/**
+ * Function to handle timeout event of throttling.
+ *
+ * @param   event_hf_param [IN] parameter from event handler callback function
+ */
+void ipc_ul_throttle_timeout(void *event_hf_param);
+#endif
+
+/**
+ * Function to pop RA packet.
+ *
+ * @param   pdn_id [IN] queued RA packet's PDN ID.
+ *
+ * @return  RA packet's GPD.
+ */
+qbm_gpd* ipc_data_ipv6_ra_pool_pop(kal_uint32 pdn_id);
+
+/**
+ * Function to push RA packet.
+ *
+ * @param   pdn_id [IN] queued RA packet's PDN ID.
+ * @param   gpd    [IN] queued RA packet's GPD.
+ *
+ */
+void ipc_data_ipv6_ra_pool_push(kal_uint32 pdn_id, qbm_gpd* gpd);
+
+/**
+ * Function to get data-usage for pdn_sim_id
+ *
+ * @param   pdn_sim_id [IN] PDN ID + SIM_ID.
+ *
+ * @return pdn_sim_id's data usage.
+ *
+ */
+ipc_data_usage_info_t* ipc_get_data_usage_by_pdn_sim_id(kal_uint32 pdn_sim_id);
+
+/**
+ * Function to store data-usage for netif_id
+ *
+ * @param   data_path_direct [IN] data packet's direction
+ * @param   ip_type [IN] ip type of packet
+ * @param   netif_id [IN] Netif id sent packet
+ * @param   data_usage [IN] Data bytes and packet count of sent packet
+ *
+ */
+kal_bool ipc_set_data_usage_by_netif_id(ipc_data_path_direction_e data_path_direct, kal_uint8 ip_type, kal_uint32 netif_id, ipc_data_usage_info_t *data_usage);
+
+/**
+ * Function to store data-usage for pdn_sim_id
+ *
+ * @param   data_path_direct [IN] data packet's direction
+ * @param   pdn_sim_id [IN] PDN_ID + SIM_Idx of packet
+ * @param   data_usage [IN] Data bytes and packet count of sent packet
+ *
+ */
+kal_bool ipc_set_data_usage_by_pdn_sim_id(ipc_data_path_direction_e data_path_direct, kal_uint32 pdn_sim_id, ipc_data_usage_info_t* data_usage);
+
+/**
+ * Function to reset data-usage for pdn_sim_id
+ *
+ * @param   pdn_sim_id [IN] PDN ID + SIM_ID.
+ *
+ */
+void ipc_reset_data_usage_by_pdn_sim_id(kal_uint8 pdn_sim_id);
+
+#endif /* __INC_IPC_DATA_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_data_ipf.h b/mcu/middleware/hif/ipcore/include/ipc_data_ipf.h
new file mode 100644
index 0000000..d7d4953
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_data_ipf.h
@@ -0,0 +1,296 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2016
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_hpc.h
+ *
+ * Project:
+ * --------
+ *   UMOLYA
+ *
+ * Description:
+ * ------------
+ *   IP Core Uplink/Downlink data path implementation with HPC.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_DATA_IPF_H
+#define __INC_IPC_DATA_IPF_H
+
+#include "ipfc_export_plugin_dl_filter.h"
+#include "ipc_dpfm.h"
+
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+
+#if IPC_PEER==IPC_PEER_LTM_SIM
+    #if defined(__LTM_SIMULATION_SUPPORT__)
+        #define _IPC_QUERY_IPF_META_TABLE ipfc_plugin_dl_filter_query_meta_info
+        #define _IPC_FREE_IPF_META ipfc_plugin_dl_filter_release_meta_entry
+        #define _IPC_QUERY_FILTER_ID_BY_IDX ipfc_plugin_dl_filter_query_id_by_index
+        #define _IPC_TAKE_HW_FILTER_TABLE ipfc_plugin_dl_filter_take_tlb
+        #define _IPC_SUBMIT_HW_FILTER_TABLE ipfc_plugin_dl_filter_submit_tlb
+        #define _IPC_PN_MATCH_SETTING ipfc_plugin_dl_filter_set_pn_match
+        #define _IPC_ENABLE_IPF_DL_FILTER ipfc_plugin_dl_filter_enable
+        #define _IPC_IPF_DL_META_THRESHOLD 500
+    #else
+        #define "Please define turn on LTM_SIMULATION_SUPPORT while setting IPC_PEER as IPC_PEER_LTM_SIM!"
+    #endif
+#elif IPC_PEER==IPC_PEER_UPCM || IPC_PEER==IPC_PEER_DISPATCHER
+    #if defined(__IPF_SUPPORT__)
+        #define _IPC_PN_MATCH_SETTING ipfc_plugin_dl_filter_set_pn_match
+        #define _IPC_QUERY_IPF_META_TABLE ipfc_plugin_dl_filter_query_meta_info
+        #define _IPC_FREE_IPF_META ipfc_plugin_dl_filter_release_meta_entry
+        #define _IPC_QUERY_FILTER_ID_BY_IDX ipfc_plugin_dl_filter_query_id_by_index
+        #define _IPC_TAKE_HW_FILTER_TABLE ipfc_plugin_dl_filter_take_tlb
+        #define _IPC_SUBMIT_HW_FILTER_TABLE ipfc_plugin_dl_filter_submit_tlb
+        #define _IPC_ENABLE_IPF_DL_FILTER ipfc_plugin_dl_filter_enable
+        #define _IPC_IPF_DL_META_THRESHOLD 500
+    #else
+        #define _IPC_QUERY_IPF_META_TABLE(...)
+        #define _IPC_FREE_IPF_META(...)
+        #define _IPC_QUERY_FILTER_ID_BY_IDX(...)
+        #define _IPC_TAKE_HW_FILTER_TABLE(...)
+        #define _IPC_SUBMIT_HW_FILTER_TABLE(...)
+        #define _IPC_PN_MATCH_SETTING(...)
+        #define _IPC_ENABLE_IPF_DL_FILTER(...)
+        #define _IPC_IPF_DL_META_THRESHOLD 500
+    #endif
+#elif IPC_PEER==IPC_PEER_UT
+    #define _IPC_QUERY_IPF_META_TABLE ipc_ut_query_ipf_meta_info
+    #define _IPC_FREE_IPF_META ipc_ut_release_ipf_meta_entry
+    #define _IPC_QUERY_FILTER_ID_BY_IDX ipc_ut_ipf_query_filter_id_by_index
+    #define _IPC_TAKE_HW_FILTER_TABLE ipc_ut_ipf_take_filter_tlb
+    #define _IPC_SUBMIT_HW_FILTER_TABLE ipc_ut_ipf_submit_filter_tlb
+    #define _IPC_PN_MATCH_SETTING ipc_ut_ipf_pn_match_setting
+    #define _IPC_ENABLE_IPF_DL_FILTER(...)
+    #define _IPC_IPF_DL_META_THRESHOLD 5
+
+#elif IPC_PEER==IPC_PEER_NULL_DROP || IPC_PEER==IPC_PEER_NULL_LOOPBACK
+    #define _IPC_QUERY_IPF_META_TABLE(...)
+    #define _IPC_FREE_IPF_META(...)
+    #define _IPC_QUERY_FILTER_ID_BY_IDX(...)
+    #define _IPC_TAKE_HW_FILTER_TABLE(...)
+    #define _IPC_SUBMIT_HW_FILTER_TABLE(...)
+    #define _IPC_PN_MATCH_SETTING(...)
+    #define _IPC_ENABLE_IPF_DL_FILTER(...)
+    #define _IPC_IPF_DL_META_THRESHOLD 500
+#else
+    #error "Unknown peer module of IPCORE!"
+#endif
+
+#define IPC_QUERY_IPF_META_TABLE _IPC_QUERY_IPF_META_TABLE
+#define IPC_FREE_IPF_META _IPC_FREE_IPF_META
+#define IPC_QUERY_FILTER_ID_BY_IDX _IPC_QUERY_FILTER_ID_BY_IDX
+#define IPC_TAKE_HW_FILTER_TABLE _IPC_TAKE_HW_FILTER_TABLE
+#define IPC_SUBMIT_HW_FILTER_TABLE _IPC_SUBMIT_HW_FILTER_TABLE
+#define IPC_PN_MATCH_SETTING _IPC_PN_MATCH_SETTING
+#define IPC_ENABLE_IPF_DL_FILTER _IPC_ENABLE_IPF_DL_FILTER
+#define IPC_IPF_DL_META_THRESHOLD _IPC_IPF_DL_META_THRESHOLD
+
+#if IPC_PEER==IPC_PEER_UT || IPC_PEER==IPC_PEER_NULL_DROP || IPC_PEER==IPC_PEER_NULL_LOOPBACK
+#define IPC_FREE_DL_META_PRB ipc_ut_free_ipf_meta_buf
+#else
+#define IPC_FREE_DL_META_PRB(_meta, _dump_len) \
+    do { \
+        kal_uint8* _addr; \
+        kal_uint32 _len; \
+        IPC_ASSERT(_meta); \
+        _addr = (void*)(_meta->addr);\
+        _len = _meta->len;\
+        IPC_DL_PKT_DUMP(_addr, _dump_len); \
+        dpcopro_rbuf_release(_addr, _len);\
+    } while (0)
+#endif
+
+/*------------------------------------------------------------------------------
+ * Internal data structure definition.
+ *----------------------------------------------------------------------------*/
+#define IPC_DL_META_QUEUE_NUM          (IPFC_META_QUEUE_MAX)
+#define IPC_UL_META_INVALID_PDN_SIM_ID (0)     /*< HW will fill 0 when UL PN match failed */
+#define IPC_HPC_ENTRY_SIZE             (128)   /*< Number should sync with platform driver */
+#define IPC_PN_NCID_DEFAULT            (0x7FF)
+#define IPC_PKT_DUMP_LIMITED_LEN       (64)
+
+typedef enum _ipc_hpc_match_result_e {
+    IPC_HPC_MR_MATCH = 0,
+    IPC_HPC_MR_NEW,
+    IPC_HPC_MR_DPFM_MATCH,
+    IPC_HPC_MR_DPFM_MATCH_BUT_NO_NAT,
+    IPC_HPC_MR_DPFM_DEL_CMD_MATCH,
+    IPC_HPC_MR_DPFM_DEL_CMD_MISS,
+    IPC_HPC_MR_DPFM_ADD_CMD,
+    IPC_HPC_MR_UNKNOWN,
+    IPC_HPC_MR_MAX,
+}ipc_hpc_match_result_e;
+
+typedef enum _ipc_hpc_match_action_e {
+    IPC_HPC_MA_INVALID,
+    IPC_HPC_MA_DEFAULT,
+    IPC_HPC_MA_FILTER_MATCH,
+    IPC_HPC_MA_FILTER_DPFM_MATCH,
+    IPC_HPC_MA_MAX,
+}ipc_hpc_match_action_e;
+
+typedef enum _ipc_ipf_dl_match_result_e {
+    IPC_IPF_MR_DIRECT_TO_AP = 0,
+    IPC_IPF_MR_FILTER_MATCH,
+    IPC_IPF_MR_UNKNOWN_HEADER,
+    IPC_IPF_MR_NET_INVALID,
+    IPC_IPF_MR_PN_NO_MATCH,
+    IPC_IPF_MR_DPFM_MATCH,
+    IPC_IPF_MR_DPFM_OPEN_AND_DPFM_NOT_MATCH,
+    IPC_IPF_MR_DPFM_MATCH_BUT_NO_NAT,
+    IPC_IPF_MR_MAX = 8,
+}ipc_ipf_dl_match_result_e;
+
+typedef struct _ipc_hpc_info_tbl_t {
+    kal_bool is_dirty;
+    ipc_packet_info_t packet_info;
+}ipc_hpc_info_tbl_t;
+
+typedef struct _ipc_dl_meta_queue_t ipc_dl_meta_queue_t;
+typedef struct _ipc_dl_meta_queue_t {
+    IPC_DECLARE_OBJECT
+
+    kal_uint32 meta_head;
+    kal_uint32 meta_tail;
+    kal_uint32 meta_size;
+    kal_uint32 cnt;
+    kal_uint32 pending_cnt;
+    ipfc_dl_filter_queue_type meta_queue_type;
+    void  (*ipc_clear_callback_t)(ipc_dl_meta_queue_t *queue);
+    void  (*ipc_process_callback_t)(ipc_dl_meta_queue_t *queue);
+} ipc_dl_meta_queue_t;
+
+typedef enum _ipc_ipf_pn_match_cmd_e {
+    IPC_IPF_PN_MATCH_BIND = 0,
+    IPC_IPF_PN_MATCH_UNBIND,
+}ipc_ipf_pn_match_cmd_e;
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * General Function prototype.
+ *----------------------------------------------------------------------------*/
+void ipc_meta_downlink_dequeue();
+void ipc_update_pn_match_setting(kal_uint8 pdn_sim_id, kal_uint32 network_interface_id, kal_uint32 ip_type, ipc_ipf_pn_match_cmd_e pnm_cmd);
+void ipc_dl_meta_queue_init();
+kal_uint16 ipc_on_process_ul_hpc_result(kal_uint8 *ip_type, kal_uint32 meta_idx, lhif_meta_tbl_t *meta, kal_uint32 netif_id, ipc_dpfm_mirror_des_t *dpfm_mirror_des);
+kal_bool ipc_on_process_dpfm_cmd_result(kal_uint32 meta_idx, lhif_meta_tbl_t *meta);
+void ipc_hpc_init();
+void ipc_check_and_fill_session_info(kal_uint8 ip_type, kal_uint32 ipv4_pdn_id, kal_uint32 ipv6_pdn_id, kal_uint32 netif_id, lhif_meta_tbl_t *meta);
+void ipc_ipf_drop_packet_handler(kal_uint8* p_packet, kal_uint32 len, kal_uint8 pdn_sim_id);
+void ipc_ipf_dhlr_for_tcp_rst(kal_uint8 *p_packet, ipc_packet_info_t packet_info, kal_uint8 pdn_sim_id);
+void ipc_ipf_dhlr_for_udp_rst(kal_uint8 *p_packet, kal_uint8 pdn_sim_id);
+#endif
diff --git a/mcu/middleware/hif/ipcore/include/ipc_debug.h b/mcu/middleware/hif/ipcore/include/ipc_debug.h
new file mode 100644
index 0000000..02450f8
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_debug.h
@@ -0,0 +1,35 @@
+#ifndef __INC_IPC_DEBUG_H
+#define __INC_IPC_DEBUG_H
+
+#define HIF_DATA_TRACE_ENABLED          1
+
+#if defined(__MTK_TARGET__)
+    #define HIF_CONSOLE_TRACE_ENABLED   0
+#else
+    #define HIF_CONSOLE_TRACE_ENABLED   0
+#endif
+
+#include "hif_trace.h"
+#include "ipc_trace.h"
+#include "TrcMod.h"
+#include "hif_swla.h"
+
+/**
+ * SWLA TAG Notes : only support 3 charactors. each tag should be unique.
+ * IU0 : ipc_uplink
+ * IU1 : ipc_meta_uplink
+ * IU2 : ipc_on_process_ul_queue
+ * IU3 : ipc_on_process_ul_ior_list
+ * IU4 : ipc_on_process_ul_meta_table
+ * IU5 : IPC_FORWARD_UL_META
+ * IDO : ipc_on_downlink
+ * ID1 : ipc_on_did_downlink
+ * ID2 : ipc_meta_downlink
+ * ID3 : ipc_dlink_callback_t
+ * ID4 : ipc_on_process_dl_meta
+ * IF1 : ipc_call_filter_cbk
+ * IM1 : IPC_MDT_TRACK_PACKET
+ * IM2 : IPC_QUERY_MDT_ROUTE
+ */
+
+#endif /* __INC_IPC_DEBUG_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_defs.h b/mcu/middleware/hif/ipcore/include/ipc_defs.h
new file mode 100644
index 0000000..abe670f
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_defs.h
@@ -0,0 +1,479 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_defs.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IP Core internal configuration and data structure definition.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_DEFS_H
+#define __INC_IPC_DEFS_H
+
+#include "kal_public_api.h"
+#include "sim_public_enum.h"
+#include "dispatcher_if.h"
+#include "ipc_session.h"
+#include "ipc_api.h"
+#include "ipc_ut.h"
+
+#define IPC_PEER_NULL_DROP          1
+#define IPC_PEER_NULL_LOOPBACK      2
+#define IPC_PEER_LTM_SIM            3
+#define IPC_PEER_UPCM               4
+#define IPC_PEER_UT                 5
+#define IPC_PEER_DISPATCHER         6
+
+#define IPC_DBG_DL_PKT_DUMP_ENABLE     0   /*< Debug and test only */
+#define IPC_DBG_UL_PKT_DUMP_ENABLE     0   /*< Debug and test only */
+
+/*------------------------------------------------------------------------------
+ * Configuration.
+ *----------------------------------------------------------------------------*/
+#ifdef IPC_PEER_LOOPBACK
+    #define IPC_PEER              IPC_PEER_NULL_LOOPBACK
+#else
+    #ifdef __DISPATCHER_SUPPORT__
+        #define IPC_PEER              IPC_PEER_DISPATCHER
+    #else
+        #define IPC_PEER              IPC_PEER_UPCM
+    #endif
+#endif
+
+#if defined(__LTM_SIMULATION_SUPPORT__)
+    #undef IPC_PEER
+    #define IPC_PEER          IPC_PEER_LTM_SIM
+#endif
+
+#ifdef ATEST_SYS_IPCORE
+    #undef  IPC_PEER
+    #define IPC_PEER          IPC_PEER_UT
+    #define IPCORE_SRC_MOD    MOD_NIL
+    #define NAS_DST_MOD       MOD_IPCORE
+    #define REBIND_DST_MOD    MOD_IPCORE
+    #define QUERY_DST_MOD     MOD_IPCORE
+    #define FILTER_SRC_MOD    MOD_NIL
+#else
+    #define IPCORE_SRC_MOD    MOD_IPCORE
+    #define NAS_DST_MOD       MOD_TFTLIB
+    #define REBIND_DST_MOD    src_mod_id
+    #define QUERY_DST_MOD     src_mod_id
+    #define FILTER_SRC_MOD    kal_get_active_module_id()
+#endif
+
+#if 1//defined(__MTK_MD_DIRECT_TETHERING_SUPPORT__) || defined(__MDT_MDONLY_SUPPORT__)
+    #define __MD_DIRECT_TETHERING_SUPPORT__
+#endif
+
+#define IPC_95_ACK_REDUCTION_ENABLE     0
+
+#if (CUR_GEN >= MD_GEN95)
+    #define __IPF_SUPPORT__
+    #if (IPC_95_ACK_REDUCTION_ENABLE == 1)
+        #define __IPC_95_ACK_REDUCTION_SUPPORT__
+    #endif
+#endif
+
+#define IPC_IPV6_RA_WORKAROUND 1
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+/*
+ * pdn_id use 0~5 bits (from the LSB) and proto_idx use 6~7
+ * which means IPCore only support pdn_id from 0 to 63 and proto_idx from 0 to 3
+ */
+#define IPC_CHECK_PDNID(_pdn_id)         (((kal_uint32)_pdn_id) & 0xFFFFFFC0)
+#define IPC_CHECK_EBI(_ebi)              (((kal_uint32)_ebi) & 0xFFFFFFC0)
+#define IPC_CHECK_PROTOID(_proto_idx)    (((kal_uint8)_proto_idx) & 0xFC)
+
+#define IPC_MASK_PROTOID_ON_PDNID(_pdn_id, _proto_idx) \
+    _pdn_id = ( ((kal_uint32)_pdn_id) | (((kal_uint32)_proto_idx) << 6) )
+
+#define IPC_UNMASK_PROTOID_FROM_PDNID(_pdn_id) \
+    _pdn_id = (((kal_uint32)_pdn_id) & 0x0000003F)
+
+#define IPC_RETRIEVE_PROTOID_FROM_PDNID(_pdn_id, _proto_idx) \
+    _proto_idx = ( (kal_uint8)((((kal_uint32)_pdn_id) & 0x000000C0) >> 6) )
+
+#define IPC_GET_PROTOID_FROM_MODID(_mod_id, _proto_idx) \
+    if ((_mod_id >= MOD_UPCM) && (_mod_id <= MOD_UPCM + MAX_SIM_NUM)) { \
+        _proto_idx = _mod_id - MOD_UPCM; \
+    } else if ((_mod_id >= MOD_DISPATCHER) && (_mod_id <= MOD_DISPATCHER + MAX_SIM_NUM)) { \
+        _proto_idx = _mod_id - MOD_DISPATCHER; \
+    } else { \
+        IPC_ASSERT(KAL_FALSE); \
+    }
+
+#if defined(__MTK_TARGET__)
+/*
+ * 2017/08/03 Peter.Hsu
+ * kal_mem_cpy() will read source memory exceed the length we provided, which may access to invalid VRB page.
+ * Therefore, we will use dpcopro_vrb_copy() instead if the source memory is bank 5 (VRB).
+ */
+
+#ifndef __MD97__
+
+#define VRB_ADDR_BANK               (0x5)
+#define VRB_CHECK_VADDR(vrb_addr)   (VRB_ADDR_BANK==(((kal_uint32)(vrb_addr))>>28))
+#define VRB_GET_VADDR_OFS(addr)     (((kal_uint32)(addr))&(~(0xf<<28)))
+
+#else
+
+#define VRB_ADDR_BANK                (0xe)
+#define VRB_CHECK_VADDR(__vrb_addr)  ({kal_uint32 __ret=0,__addr_bank=((kal_uint32)(__vrb_addr))>>27,__vrb_bank=VRB_ADDR_BANK<<1; \
+                                     if(__vrb_bank<=__addr_bank && __addr_bank<(__vrb_bank+3)){__ret=1;} __ret;})
+#define VRB_GET_VADDR_OFS(addr)      (((kal_uint32)(addr))-(VRB_ADDR_BANK<<28))
+
+#endif
+
+extern void dpcopro_vrb_copy(kal_uint8 *des, kal_uint8 *src, kal_uint32 len);
+#undef kal_mem_cpy
+#define kal_mem_cpy(_p_dst, _p_src, _len) \
+    do { \
+        if (VRB_CHECK_VADDR(_p_src)) { \
+            dpcopro_vrb_copy((kal_uint8 *)_p_dst, (kal_uint8 *)_p_src, (kal_uint32)_len); \
+        } else { \
+            kal_mem_cpy(_p_dst, _p_src, _len); \
+        } \
+    } while (0)
+#endif
+/*------------------------------------------------------------------------------
+ * Constant definition.
+ *----------------------------------------------------------------------------*/
+#define IPC_ASSERT  ASSERT      /* To completely bypass the overhead of ASSERT(), we could define IPC_ASSERT(...) to nothing. */
+
+#define IPC_DL_INVALID_LEN_DROP_EN      0     /*< 0: disable, 1: enable */
+#define IPC_DL_INVALID_LEN_DEFAULT      3568
+
+#define IPC_LOCK_NAME    "IPCORE_LOCK"
+#define IPC_UL_LOCK_NAME "IPCORE_UL_LOCK"
+
+#define IPC_ES_INDEX_UL_THROTTLE 2
+
+#define IPC_INVALID_FILTER_ID -1
+#define IPC_INVALID_NETIF_ID 0xFFFFFFFF
+#define IPC_INVALID_PDN_ID 0xFFFFFFFF
+#define IPC_INVALID_EBI_ID 0xFF
+
+#define IPC_DUMP_ENABLE 0
+#define IPC_DUMP_SIZE 48
+#define IPC_IPV6_DUMP 1
+#define IPC_HAS_GPD_MASK (1 << 15)
+
+/*------------------------------------------------------------------------------
+ * Internal data structure definition.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+extern kal_uint32       ipc_dl_valid_packet_len_s;
+extern kal_bool         ipc_is_support_ccci_fast_header_s;
+extern kal_spinlockid   ipc_spinlock_g;
+extern kal_bool         ipc_ul_enable_g;
+extern kal_spinlockid   g_ul_spinlock;
+
+/*------------------------------------------------------------------------------
+ * Internal function prototype.
+ *----------------------------------------------------------------------------*/
+kal_bool ipc_init(void);
+void ipc_on_ilm(ilm_struct *ilm);
+kal_bool ipc_reset(void);
+kal_bool ipc_is_in_reset(void);
+void ipc_set_ul_throttle(local_para_struct *local_para_ptr);
+kal_bool ipc_send_dl_pkt_in_did_internal(ipc_pkt_t *pkt, ipc_hdr_t *hdr, kal_uint32 netif_id);
+void ipc_module_clean(void);
+void ipc_clean_private_data(void);
+
+#ifdef __DISPATCHER_SUPPORT__
+void ipc_reg_cbk_dlvr_dl_did(dispatcher_dlvr_dl_did_f pf_dlvr_did);
+#endif
+
+#endif /* __INC_IPC_DEFS_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_dhcp_adp.h b/mcu/middleware/hif/ipcore/include/ipc_dhcp_adp.h
new file mode 100644
index 0000000..c847fee
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_dhcp_adp.h
@@ -0,0 +1,122 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_dhcp_adp.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   DHCP adaption.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_DHCP_ADP_H
+#define __INC_IPC_DHCP_ADP_H
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Function prototype.
+ *----------------------------------------------------------------------------*/
+/*!
+ * Enable DHCPv4 client for a IPv4 or IPv4v6 session.
+ *
+ * @param   session_ptr [IN] The session object.
+ */
+void ipc_enable_dhcp4c(void *session_ptr);
+
+/*!
+ * Handler of the message MSG_ID_DHCP4C_ACTIVATE_RSP.
+ *
+ * @param   activate_rsp_ptr [IN] Pointer to a dhcp4c_activate_rsp_struct object.
+ */
+void ipc_on_dhcp4c_activate_rsp(void *activate_rsp_ptr);
+
+/*!
+ * Disable DHCPv4 client for a IPv4 or IPv4v6 session.
+ *
+ * @param   session_ptr [IN] The session object.
+ */
+void ipc_disable_dhcp4c(void *session_ptr);
+
+/*!
+ * Handler of the message MSG_ID_DHCP4C_DEACTIVATE_RSP.
+ *
+ * @param   deactivate_rsp_ptr [IN] Pointer to a dhcp4c_deactivate_rsp_struct object.
+ */
+void ipc_on_dhcp4c_deactivate_rsp(void *deactivate_rsp_ptr);
+
+/*!
+ * Handler of the message MSG_ID_DHCP4C_IP_UP_IND.
+ *
+ * @param   dhcp4c_ip_up_ind_ptr [IN] Pointer to a dhcp4c_ip_up_ind_struct object.
+ */
+void ipc_on_dhcp4c_ip_up_ind(void *dhcp4c_ip_up_ind_ptr);
+
+/*!
+ * Handler of the message MSG_ID_DHCP4C_IP_DOWN_IND.
+ *
+ * @param   dhcp4c_ip_down_ind_ptr [IN] Pointer to a dhcp4c_ip_down_ind_struct object.
+ */
+void ipc_on_dhcp4c_ip_down_ind(void *dhcp4c_ip_down_ind_ptr);
+
+/*!
+ * Handler of the message MSG_ID_DHCP4C_PACKET_IND.
+ *
+ * @param   dhcp4c_packet_ind_ptr [IN] Pointer to a dhcp4c_packet_ind_struct object.
+ */
+void ipc_on_dhcp4c_packet_ind(void *dhcp4c_packet_ind_ptr);
+
+#endif /* __INC_IPC_DHCP_ADP_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_dpfm.h b/mcu/middleware/hif/ipcore/include/ipc_dpfm.h
new file mode 100644
index 0000000..7fdc53a
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_dpfm.h
@@ -0,0 +1,248 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2017
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_data.h
+ *
+ * Project:
+ * --------
+ *   UMOLYA
+ *
+ * Description:
+ * ------------
+ *   IP Core Uplink/Downlink data path implementation.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_DPFM_H
+#define __INC_IPC_DPFM_H
+
+#include "kal_public_api.h"
+#include "ipc_defs.h"
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    #include "dpfm_api.h"
+#endif
+
+#include "ipc_session.h"
+
+/*------------------------------------------------------------------------------
+ * Internal data structure defintion.
+ *----------------------------------------------------------------------------*/
+#define IPC_DPFM_MAX_DEVICE_NUM 2 /* USB and WiFi */
+#define IPC_DPFM_DEFAULT_ROUTE_DEVICE_NUM IPC_MAX_SESSION_CNT
+
+typedef struct _ipc_dpfm_mirror_des_t {
+    kal_uint32          netif_id;
+    union {
+        struct {
+            kal_uint8           dpfm_matched_num;
+            kal_bool            mirror_spd_pie_idx[QBM_SPD_MAX_PKTNUM];
+        };
+        struct {
+            kal_uint32          pdn_ids[IPC_SESSION_MAP_SIZE];
+        };
+        struct {
+            kal_uint8           pkt_num;
+            kal_uint8           seg_num;
+            ipc_si_hif_type_e   hif_type;
+            upcm_did           *mirror_did_head;
+            upcm_did           *mirror_did_tail;
+        };
+    };
+} ipc_dpfm_mirror_des_t;
+
+typedef struct _ipc_dpfm_routing_packet_list_t {
+    qbm_gpd *first_gpd;
+    qbm_gpd *last_gpd;
+} ipc_dpfm_routing_packet_list_t;
+
+typedef struct _ipc_dpfm_lan_des_t {
+    kal_bool            is_did;
+    kal_bool            is_need_adjust_seq;
+    kal_uint32          dst_netif_id;
+    kal_uint32          src_netif_id;
+    ipc_si_hif_type_e   hif_type;
+    upcm_did           *did;
+    kal_uint32          curr_si_idx;
+} ipc_dpfm_lan_des_t;
+
+typedef struct _ipc_dpfm_default_route_des_t
+{
+    kal_uint32  netif_id;
+    upcm_did    *head_did;
+    upcm_did    *tail_did;
+}ipc_dpfm_default_route_des_t;
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+extern ipc_dpfm_routing_packet_list_t   ipc_dpfm_packet_routing_queue[2][IPC_MAX_NETIF_CNT];
+extern kal_bool                         ipc_dpfm_queue_non_empty[2];
+
+#if IPC_PEER==IPC_PEER_UT
+    #define IPC_QUERY_DPFM_ROUTE ipc_ut_dpfm_check_route
+    #define IPC_DPFM_IS_ACTIVE ipc_ut_dpfm_is_activated
+    #define IPC_DPFM_PROCESS_FILTER_CMD(...)
+    #define IPC_DPFM_TRACK_PACKET(...)
+#else
+    #define IPC_QUERY_DPFM_ROUTE dpfm_check_route
+    #define IPC_DPFM_IS_ACTIVE dpfm_is_active
+    #define IPC_DPFM_PROCESS_FILTER_CMD dpfm_process_filter_cmd_result
+    #define IPC_DPFM_TRACK_PACKET dpfm_track_packet
+#endif
+
+/*------------------------------------------------------------------------------
+ * General Function prototype.
+ *----------------------------------------------------------------------------*/
+
+/*!
+ * Downlink data path entrance function for lan NETIF.
+ *
+ * @param   lan_des_array [IN] lan_des array of all DPFM devices.
+ */
+void ipc_dpfm_lan_on_did_downlink(ipc_dpfm_lan_des_t *lan_des_array);
+
+/*
+ * Fill the DID/SIT descriptor from the META.
+ *
+ * @param   lan_des_array [IN] lan_des array of all DPFM devices.
+ * @param   src_meta [IN] The META of the packet.
+ * @param   src_netif_id [IN] The id of the netif of the source lan device.
+ * @param   src_netif [IN] The pointer of the source netif.
+ *
+ * @return  KAL_TRUE if successful, KAL_FALSE otherwise.
+ */
+kal_bool ipc_dpfm_fill_did_si_from_meta(ipc_dpfm_lan_des_t *lan_des_array, lhif_meta_tbl_t *src_meta, kal_uint32 src_netif_id, ipc_netif_t *src_netif);
+
+/*!
+ * Set the corresponding PDN id into META of the packet which is about to use DPFM Direct Path.
+ *
+ * @param   mirror_des_array [IN] mirror_des array of all DPFM devices.
+ * @param   META [IN] The META of the packet.
+ * @param   netif_id [IN] The id of the netif of the routed DPFM device.
+ * @param   ip_type [IN] The IP type of the packet.
+ *
+ * @return  return KAL_TRUE for the packet is available to use the direct path, otherwise return KAL_FALSE.
+ */
+kal_bool ipc_dpfm_set_pdn_id_in_meta(ipc_dpfm_mirror_des_t *mirror_des_array, lhif_meta_tbl_t *meta, kal_uint32 netif_id, kal_uint8 ip_type);
+
+/*!
+ * Mark the mirror descriptor and DID to indicate the packet is about to use DPFM Direct Path.
+ *
+ * @param   mirror_des_array [IN] mirror_des array of all DPFM devices.
+ * @param   did [IN] DID of the packet.
+ * @param   p_curr_si_idx [IN|OUT] The started SIT index of the packet.
+ * @param   netif_id [IN] The id of the netif of the routed DPFM device.
+ *
+ * @return  return KAL_TRUE for the packet is marked to use the direct path, otherwise return KAL_FALSE.
+ */
+kal_bool ipc_dpfm_set_pkt_in_did_mirror_des(ipc_dpfm_mirror_des_t *mirror_des_array, upcm_did *did, kal_uint32 *p_curr_si_idx, kal_uint32 netif_id);
+
+/*!
+ * Fill the mirror descriptor and DID to indicate the packet is about to use DPFM Direct Path.
+ *
+ * @param   mirror_des_array [IN] mirror_des array of all DPFM devices.
+ * @param   packet_des [IN] IPCore internal packet descriptor.
+ * @param   netif_id [IN] The id of the netif of the routed DPFM device.
+ *
+ * @return  return KAL_TRUE for the packet is marked to use the direct path, otherwise return KAL_FALSE.
+ */
+kal_bool ipc_dpfm_set_ipf_pkt_in_did_mirror_des(ipc_dpfm_mirror_des_t *mirror_des_array, ipc_pkt_des_t *packet_des, kal_uint32 netif_id);
+
+/*!
+ * Mirror the DID with the correct packet and segment numbers of the corresponding hif type.
+ *
+ * @param   mirror_des [IN] mirror_des of the DPFM device.
+ * @param   src_did [IN] The source DID.
+ */
+void ipc_dpfm_mirror_did(ipc_dpfm_mirror_des_t *mirror_des, upcm_did *src_did);
+
+/*!
+ * Push the DID to Downlink IPC_DID_QUEUE_TYPE_DPFM queue.
+ *
+ * @param   did [IN] DID of the packet.
+ * @param   pdn_id [IN] PDN ID where the DID comes from.
+ */
+void ipc_dpfm_push_did_to_dpfm_queue(upcm_did *did, kal_uint32 pdn_id);
+
+kal_bool ipc_dpfm_check_route(kal_bool uplink, ipc_pkt_des_t *pkt_des, kal_uint32 netif_id);
+
+qbm_spd * ipc_dpfm_mirror_spd(qbm_spd *p_origin_spd, kal_bool *mirror_spd_pie_idx, kal_uint8 dpfm_matched_num);
+
+void ipc_dpfm_push_gpd_to_routing_queue(kal_bool uplink, kal_uint32 netif_id, qbm_gpd *gpd);
+
+kal_bool ipc_dpfm_need_pkt_info(kal_bool is_uplink, ipc_pkt_des_t *pkt_des);
+
+#endif /* __MD_DIRECT_TETHERING_SUPPORT__) */
+#endif /* __INC_IPC_DPFM_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_filter.h b/mcu/middleware/hif/ipcore/include/ipc_filter.h
new file mode 100644
index 0000000..2cfa5eb
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_filter.h
@@ -0,0 +1,489 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_filter.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   Packet filtering.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_FILTER_H
+#define __INC_IPC_FILTER_H
+
+#include "kal_public_api.h"
+
+#include "ipc_struct.h"
+#include "ipc_dpfm.h"
+
+typedef enum _ipc_match_result_e {
+    IPC_MATCH_RESULT_NOT_MATCHED    = 0x0000,
+    IPC_MATCH_RESULT_MATCHED        = 0x0001,
+    IPC_MATCH_RESULT_FRAG_MATCHED   = 0x0010,
+} ipc_match_result_e;
+
+typedef enum _ipc_pkt_do_filter_result_e {
+    IPC_PKT_DO_FILTER_NOT_MATCHED  = 0,
+    IPC_PKT_DO_FILTER_MATCHED      = 1,
+    IPC_PKT_DO_FILTER_BWM_MATCHED  = 2,
+    IPC_PKT_DO_FILTER_DPFM_MATCHED = 3,
+    IPC_PKT_DO_FILTER_INVALID_LEN  = 4,
+    IPC_PKT_DO_FILTER_HANDLE_FRAG  = 5,
+    IPC_PKT_DO_FILTER_HANDLE_CLONE = 6,
+    IPC_PKT_DO_FILTER_ERROR,
+    IPC_PKT_DO_FILTER_NONE
+} ipc_pkt_do_filter_result_e;
+
+#define IPF_HW_FILTER_ENTRY_NUM 64
+
+/* IPF HW Filter IP Type */
+#define IPF_HW_FILTER_IPV4      (0x4)
+#define IPF_HW_FILTER_IPV6      (0x6)
+#define IPF_HW_FILTER_IPV6_1    (0x7)
+
+/* IPF HW Filter Valid Field */
+#define IPF_HW_FILTER_V_FRAG            ( 0x1 << 0)
+#define IPF_HW_FILTER_V_PROTO           ( 0x1 << 1)
+#define IPF_HW_FILTER_V_PDNSIM_ID       ( 0x1 << 2)
+#define IPF_HW_FILTER_V_R_ADDR          ( 0x1 << 3)
+#define IPF_HW_FILTER_V_L_ADDR          ( 0x1 << 7)
+#define IPF_HW_FILTER_V_F_WORD_DONTC    ( 0x0 << 4)     // First word don't care
+#define IPF_HW_FILTER_V_F_WORD_TYPE     ( 0x1 << 4)     // only compare least significant byte of first word
+#define IPF_HW_FILTER_V_F_WORD_TYPE2    ( 0x2 << 4)     // only compare low half-word of first word
+#define IPF_HW_FILTER_V_F_WORD_TYPE3    ( 0x3 << 4)     // only compare high half-word of first word
+#define IPF_HW_FILTER_V_F_WORD_TYPE4    ( 0x4 << 4)     // compare whole first word
+
+#define IPF_HW_FILTER_SET_VALID(_p, _value) \
+    ((_p) = (_p) | _value)
+
+
+typedef enum {
+    IPC_HW_DL_MODE = 0,
+    IPC_SW_DL_MODE_STR = (1 << 0),
+    IPC_SW_DL_MODE_PCI = (1 << 1),
+    IPC_SW_DL_MODE_MAX = (1 << 7),
+    IPC_HW_DL_MODE_PCI = (~IPC_SW_DL_MODE_PCI),
+    IPC_HW_DL_MODE_STR = (~IPC_SW_DL_MODE_STR)
+} ipc_sw_dl_mode_e;
+
+#define IPC_SW_DL_FILTER_ID 0xFF
+/*------------------------------------------------------------------------------
+ * Data structure definition.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Function prototype.
+ *----------------------------------------------------------------------------*/
+
+/**
+ * Initialize IP packet filtering resources.
+ */
+void ipc_filter_init(void);
+
+/**
+ * Send ILM to indicate registering a filter for uplink or downlink traffic.
+ *
+ * @param   data_path_direct [IN] UL_DATA_PATH for uplink filter rule. DL_DATA_PATH for downlink filter rule
+ * @param   rules [IN] Rules to filter of downlink IP datagrams.
+ * @param   p_ntfy_ctxt [IN] Context to pass in the callback function.
+ *
+ * @return Zero or positive value as filter ID if registration succeeded, negative value otherwise.
+ */
+kal_int32 ipc_filter_reg_filter_by_ilm(ipc_data_path_direction_e data_path_direct,
+                                       ipc_filter_rules_t *p_rules,
+                                       ipc_filter_ntfy_ctxt_t *p_ntfy_ctxt);
+
+/**
+ * ILM handler for MSG_ID_IPCORE_REGISTER_FILTER_REQ.
+ *
+ * @param   local_para_ptr [IN] local parameter for the ILM.
+ */
+void ipc_filter_reg_handler(local_para_struct *local_para_ptr);
+
+/**
+ * Send ILM to remove the filter from uplink or downlink traffic.
+ *
+ * @param   filter_id [IN] filter ID to remove.
+ *
+ * @return KAL_TRUE for success, KAL_FALSE for failed.
+ */
+kal_bool ipc_filter_dereg_filter_by_ilm(kal_int32 filter_id);
+
+/**
+ * ILM handler for MSG_ID_IPCORE_DEREGISTER_FILTER_REQ.
+ *
+ * @param   local_para_ptr [IN] local parameter for the ILM.
+ */
+void ipc_filter_dereg_handler(local_para_struct *local_para_ptr);
+
+/**
+ * Do filter for uplink traffic.
+ *
+ * @param   session_type [IN] Type of PDN session where the GPDs are (only V4 or V6 are allowed).
+ * @param   netif_id [IN] Network interface ID where the GPD's come from.
+ * @param   pp_head [IN|OUT] header of a list of GPD's.
+ * @param   pp_tail [IN|OUT] tail of a list of GPD's.
+ *
+ * @return  the number of remained packets, which are not filterd out.
+ */
+kal_uint16
+ipc_do_ul_filter(
+    kal_uint8       session_type,
+    kal_uint32      netif_id,
+    qbm_gpd       **pp_head,
+    qbm_gpd       **pp_tail);
+
+/**
+ * Do filter for downlink traffic.
+ *
+ * @param   session_type [IN] Type of PDN session where the GPD's come from.
+ * @param   netif_id [IN] Network interface ID where the GPD's come to.
+ * @param   pdn_id [IN] PDN ID where the GPD's come from.
+ * @param   pp_head [IN|OUT] header of a list of GPD's.
+ * @param   pp_tail [IN|OUT] tail of a list of GPD's.
+ *
+ * @return  the number of remained packets, which are not filterd out.
+ */
+kal_uint16
+ipc_do_dl_filter(
+    kal_uint8       session_type,
+    kal_uint32      netif_id,
+    kal_uint32      pdn_id,
+    qbm_gpd       **pp_head,
+    qbm_gpd       **pp_tail);
+
+/**
+ * Do filter for uplink traffic in META format.
+ *
+ * @param   ip_type [IN] The IP type of the packet.
+ * @param   netif_id [IN] Network interface ID where the META's come from.
+ * @param   meta [IN] the META of the packet.
+ * @param   mirror_des [IN] mirror_des array of all DPFM devices.
+ *
+ * @return  1 if the packet is not filtered out, 0 otherwise.
+ */
+kal_uint16
+ipc_meta_do_filter(
+    kal_uint8               ip_type,
+    kal_uint32              netif_id,
+    lhif_meta_tbl_t        *meta,
+    ipc_dpfm_mirror_des_t  *dpfm_mirror_des,
+    ipc_pkt_des_t          *packet_des_p);
+
+/**
+ * Do filter for downlink traffic in DID format.
+ *
+ * @param   session_type [IN] Type of PDN session where the GPDs are (only V4 or V6 are allowed).
+ * @param   netif_id [IN] Network interface ID where the GPD's come from.
+ * @param   pdn_id [IN] PDN ID where the GPD's come from.
+ * @param   did [IN|OUT] the DID of the packet.
+ *
+ * @return  the number of remained packets, which are not filterd out.
+ */
+kal_uint16
+ipc_did_do_filter(
+    kal_uint8               session_type,
+    kal_uint32              netif_id,
+    kal_uint32              pdn_id,
+    upcm_did               *did);
+
+/**
+ * Forward packet filtered to specified module.
+ * Note that, it's for IPCORE internal use only.
+ */
+void
+ipc_forward_packet_by_msg(
+        msg_type        msg_id,
+        void           *context,
+        kal_int32       filter_id,
+        qbm_gpd        *head_gpd,
+        qbm_gpd        *tail_gpd,
+        kal_uint32      length);
+
+/**
+ * Forward uplink packet filtered to specified module.
+ * Note that, it's for IPCORE internal use only.
+ */
+void ipc_filter_fwd_ul_pkt_by_msg(void *context,
+                                  kal_int32 filter_id,
+                                  qbm_gpd *head_gpd,
+                                  qbm_gpd *tail_gpd,
+                                  kal_uint32 length);
+
+/**
+ * Forward downlink packet filtered to specified module.
+ * Note that, it's for IPCORE internal use only.
+ */
+void ipc_filter_fwd_dl_pkt_by_msg(void *context,
+                                  kal_int32 filter_id,
+                                  qbm_gpd *head_gpd,
+                                  qbm_gpd *tail_gpd,
+                                  kal_uint32 length);
+
+/**
+ * Forward packet filtered to specified module (with information).
+ * Note that, it's for IPCORE internal use only.
+ */
+void ipc_forward_packet_with_info_by_msg(msg_type           msg_id,
+                                         ipc_filter_info_t *info_p,
+                                         void              *context,
+                                         kal_int32          filter_id,
+                                         qbm_gpd           *head_gpd,
+                                         qbm_gpd           *tail_gpd,
+                                         kal_uint32         length);
+
+/**
+ * Forward uplink packet filtered to specified module (with information).
+ * Note that, it's for IPCORE internal use only.
+ */
+void ipc_filter_fwd_ul_pkt_with_info_by_msg(ipc_filter_info_t *info_p,
+                                            void *context,
+                                            kal_int32 filter_id,
+                                            qbm_gpd *head_gpd,
+                                            qbm_gpd *tail_gpd,
+                                            kal_uint32 length);
+
+/**
+ * Forward downlink packet filtered to specified module (with information).
+ * Note that, it's for IPCORE internal use only.
+ */
+void ipc_filter_fwd_dl_pkt_with_info_by_msg(ipc_filter_info_t *info_p,
+                                            void *context,
+                                            kal_int32 filter_id,
+                                            qbm_gpd *head_gpd,
+                                            qbm_gpd *tail_gpd,
+                                            kal_uint32 length);
+
+/**
+ * Updated IPF HW filter
+ */
+void ipc_filter_update_hw_filter();
+
+/**
+ * Updated IPF one HW filter
+ */
+kal_bool ipc_update_one_hw_filter(kal_int32 filter_id,
+                                  ipc_filter_rules_t* rules,
+                                  void* p_cur_base);
+
+/**
+ * IPF meta filter
+ */
+void ipc_ipf_meta_do_filter(kal_int32 filter_id,
+                            ipc_pkt_des_t *packet_des,
+                            kal_uint8 ip_type,
+                            kal_uint8 pdn_sim_id,
+                            kal_uint32 netif_id,
+                            ipc_dpfm_mirror_des_t *dpfm_mirror_des,
+                            kal_bool *is_mirror_did,
+                            kal_bool *is_saved);
+
+#endif /* __INC_IPC_FILTER_H */
+
+/**
+ * Check for current DID list contains special content before drop
+ *
+ * @param   pdn_id          [IN] pdn_sim_id
+ * @param   p_head          [IN] DID head
+ * @param   p_tail          [IN] DID tail
+ *
+ */
+void ipc_filter_did_drop_pkt_handler(kal_uint32 pdn_id, upcm_did *p_head, upcm_did *p_tail);
+
+/**
+ * Switch DL mode by installing IPF HW rule
+ *
+ * @param   mode          [IN] IPC_HW_DL_MODE or IPC_SW_DL_MODE
+ *
+ */
+void ipc_filter_switch_dl_mode(kal_uint8 mode);
diff --git a/mcu/middleware/hif/ipcore/include/ipc_fragment_def.h b/mcu/middleware/hif/ipcore/include/ipc_fragment_def.h
new file mode 100644
index 0000000..60d3642
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_fragment_def.h
@@ -0,0 +1,18 @@
+#ifndef _IPC_FRAGMENT_DEF_INC
+#define _IPC_FRAGMENT_DEF_INC
+
+#define IPC_FRAG_AFM_BUFFER_SIZE (64 * 1024)
+#if !defined(__GEN97_ESL_SPEEDUP__)
+#define IPC_FRAG_HASH_TABLE_BUCK_NUM 256  // must be power of 2
+#else
+#define IPC_FRAG_HASH_TABLE_BUCK_NUM 64
+#endif
+#define IPC_FRAG_HASH_NODE_NUM 128
+#define IPC_FRAG_PKT_META_NODE_NUM 512
+
+#define IPC_FRAG_EXPIRE_CB_NUM 64
+#define IPC_FRAG_POLLING_EXPIRE_SEC KAL_TICKS_5_SEC_REAL
+#define IPC_FRAG_QUEUING_EXPIRE_SEC (KAL_TICKS_5_SEC_REAL * 1)
+#define IPC_FRAG_ES_IDX_QUEUE_EXPIRE 10
+
+#endif /* _IPC_FRAGMENT_DEF_INC */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_fragment_export.h b/mcu/middleware/hif/ipcore/include/ipc_fragment_export.h
new file mode 100644
index 0000000..a61a173
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_fragment_export.h
@@ -0,0 +1,17 @@
+#ifndef _IPC_FRAGMENT_EXPORT_INC
+#define _IPC_FRAGMENT_EXPORT_INC
+
+#include "ipc_api.h"
+#include "kal_public_api.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+
+kal_bool ipc_fragment_init();
+kal_bool ipc_fragment_deinit();
+kal_bool ipc_fragment_reset();
+void ipc_fragment_on_ilm(ilm_struct* ilm);
+void ipc_fragment_defrag(qbm_gpd* new_gpd, ipc_frag_refilter_info_t* info, kal_bool is_v4);
+kal_uint32 ipc_fragment_frag(void* buff, kal_uint32 buff_len, qbm_gpd** frag_gpd_head, qbm_gpd** frag_gpd_tail, kal_bool is_v4);
+void ipc_fragment_test();
+
+#endif /* _IPC_FRAGMENT_EXPORT_INC */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_notify.h b/mcu/middleware/hif/ipcore/include/ipc_notify.h
new file mode 100644
index 0000000..1d6bb22
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_notify.h
@@ -0,0 +1,123 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_notify.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IPCore notification.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_NOTIFY_H
+#define __INC_IPC_NOTIFY_H
+
+#include "kal_public_api.h"
+#include "ipc_enums.h"
+
+/** Initialize IPCore notification resources. */
+void ipc_ntfy_init(void);
+
+/**
+ * Create a notification.
+ *
+ * @param   callback_func [IN] Callback function pointer.
+ * @param   callback_context [IN] Context to pass in the callback function.
+ *
+ * @return Zero or positive value as notification ID if registration succeeded, negative value otherwise.
+ */
+kal_int32 ipc_ntfy_new_cbk(ipc_ntfy_callback_t cbk_func, void *p_cbk_args);
+
+/**
+ * Remove the notification entry.
+ *
+ * @param   ntfy_id [IN] notification ID to remove.
+ */
+void ipc_ntfy_del_cbk(kal_int32 ntfy_id);
+
+/**
+ * Execute IPCore notification callback.
+ *
+ * @param   netif [IN] Corresponding network interface for the notification.
+ * @param   ntfy_type [IN] Notification type to indicate.
+ */
+void ipc_ntfy_do_event_cbk(ipc_netif_t *p_netif, ipc_ntfy_type_e ntfy_type);
+
+#endif /* __INC_IPC_NOTIFY_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_object.h b/mcu/middleware/hif/ipcore/include/ipc_object.h
new file mode 100644
index 0000000..9a48a2e
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_object.h
@@ -0,0 +1,287 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_object.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   Helper for object management and synchronization.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_OBJECT_H
+#define __INC_IPC_OBJECT_H
+
+#include "kal_public_api.h"
+
+struct _ipc_object_template;
+extern kal_spinlockid ipc_spinlock_g;
+static INLINE kal_bool ipc_is_object_valid(struct _ipc_object_template *object);
+
+/*------------------------------------------------------------------------------
+ * Data structure definition.
+ *----------------------------------------------------------------------------*/
+#define IPC_SPIN_LOCK(_lock)    kal_take_spinlock(_lock, KAL_INFINITE_WAIT)
+#define IPC_SPIN_UNLOCK(_lock)  kal_give_spinlock(_lock)
+
+#define IPC_DECLARE_OBJECT \
+            kal_int32       ref_count; \
+            kal_int32       reader_cnt; \
+            kal_int32       writer_cnt;
+
+#define IPC_IS_VALID_OBJECT_WO_LOCK(_object) \
+            ((_object) != NULL && (_object)->ref_count == 2)
+
+#define IPC_IS_VALID_OBJECT(_object) \
+            ipc_is_object_valid((struct _ipc_object_template *)_object)
+
+#define IPC_R_LOCK_OBJECT(_object, _lock) \
+            IPC_SPIN_LOCK(_lock); \
+            if (IPC_IS_VALID_OBJECT_WO_LOCK(_object) && ((_object)->writer_cnt == 0)) { \
+                ++((_object)->reader_cnt); \
+            } else { \
+                (_object) = NULL; \
+            } \
+            IPC_SPIN_UNLOCK(_lock)
+
+#define IPC_R_UNLOCK_OBJECT(_object, _lock) \
+            ASSERT((_object)); \
+            IPC_SPIN_LOCK(_lock); \
+            ASSERT((_object)->reader_cnt > 0); \
+            --((_object)->reader_cnt); \
+            IPC_SPIN_UNLOCK(_lock)
+
+#define IPC_INIT_OBJECT_BEGIN(_object, _lock) \
+            IPC_ASSERT(_object); \
+            IPC_SPIN_LOCK(_lock); \
+            IPC_ASSERT((_object)->ref_count == 0); \
+            (_object)->ref_count = 1; \
+            IPC_SPIN_UNLOCK(_lock)
+
+#define IPC_INIT_OBJECT_END(_object, _lock) \
+            IPC_ASSERT(_object); \
+            IPC_SPIN_LOCK(_lock); \
+            IPC_ASSERT(_object->ref_count == 1); \
+            (_object)->ref_count = 2; \
+            (_object)->reader_cnt = 0; \
+            (_object)->writer_cnt = 0; \
+            IPC_SPIN_UNLOCK(_lock)
+
+#define IPC_DEINIT_OBJECT_BEGIN(_object, _lock) \
+            IPC_ASSERT(kal_if_hisr() == KAL_FALSE); \
+            IPC_SPIN_LOCK(_lock); \
+            if (IPC_IS_VALID_OBJECT_WO_LOCK(_object)) { \
+                --((_object)->ref_count); \
+                while ((_object)->reader_cnt != 0 || (_object)->writer_cnt != 0) { \
+                    IPC_SPIN_UNLOCK(_lock); \
+                    kal_sleep_task(IPC_DEL_OBJECT_SLEEP_TICKS); \
+                    IPC_SPIN_LOCK(_lock); \
+                } \
+                IPC_ASSERT((_object)->ref_count == 1); \
+            } else { \
+                (_object) = NULL; \
+            } \
+            IPC_SPIN_UNLOCK(_lock)
+
+#define IPC_DEINIT_OBJECT_END(_object, _lock) \
+            IPC_SPIN_LOCK(_lock); \
+            IPC_ASSERT((_object)->ref_count == 1); \
+            IPC_ASSERT((_object)->reader_cnt == 0); \
+            IPC_ASSERT((_object)->writer_cnt == 0); \
+            (_object)->ref_count = 0; \
+            IPC_SPIN_UNLOCK(_lock)
+
+#define IPC_W_LOCK_OBJECT(_object, _lock) \
+            IPC_ASSERT(kal_if_hisr() == KAL_FALSE || KAL_TRUE == kal_query_systemInit()); \
+            IPC_SPIN_LOCK(_lock); \
+            if (IPC_IS_VALID_OBJECT_WO_LOCK(_object)) { \
+                while ((_object)->reader_cnt != 0 || (_object)->writer_cnt != 0) { \
+                    IPC_SPIN_UNLOCK(_lock); \
+                    kal_sleep_task(IPC_W_LOCK_OBJECT_SLEEP_TICKS); \
+                    IPC_SPIN_LOCK(_lock); \
+                } \
+                if (IPC_IS_VALID_OBJECT_WO_LOCK(_object)) { \
+                    ++((_object)->writer_cnt); \
+                } else { \
+                    (_object) = NULL; \
+                    IPC_SPIN_UNLOCK(_lock); \
+                } \
+            } else { \
+                (_object) = NULL; \
+                IPC_SPIN_UNLOCK(_lock); \
+            }
+
+#define IPC_W_UNLOCK_OBJECT(_object, _lock) \
+            IPC_ASSERT((_object)); \
+            IPC_ASSERT((_object)->writer_cnt == 1); \
+            --((_object)->writer_cnt); \
+            IPC_SPIN_UNLOCK(_lock)
+
+/* Safely convert between Read & Write lock at the same time. */
+#define IPC_R_TO_W_LOCK_OBJECT(_object, _lock) \
+            IPC_ASSERT(kal_if_hisr() == KAL_FALSE); \
+            IPC_SPIN_LOCK(_lock); \
+            if (IPC_IS_VALID_OBJECT_WO_LOCK(_object)) { \
+                ASSERT((_object)->reader_cnt > 0); \
+                --((_object)->reader_cnt); \
+                while ((_object)->reader_cnt != 0 || (_object)->writer_cnt != 0) { \
+                    IPC_SPIN_UNLOCK(_lock); \
+                    kal_sleep_task(IPC_W_LOCK_OBJECT_SLEEP_TICKS); \
+                    IPC_SPIN_LOCK(_lock); \
+                } \
+                if (IPC_IS_VALID_OBJECT_WO_LOCK(_object)) { \
+                    ++((_object)->writer_cnt); \
+                } else { \
+                    (_object) = NULL; \
+                    IPC_SPIN_UNLOCK(_lock); \
+                } \
+            } else { \
+                (_object) = NULL; \
+                IPC_SPIN_UNLOCK(_lock); \
+            }
+
+#define IPC_W_TO_R_LOCK_OBJECT(_object, _lock) \
+            IPC_ASSERT((_object)); \
+            IPC_ASSERT((_object)->reader_cnt == 0); \
+            IPC_ASSERT((_object)->writer_cnt == 1); \
+            --((_object)->writer_cnt); \
+            ++((_object)->reader_cnt); \
+            IPC_SPIN_UNLOCK(_lock)
+
+/*------------------------------------------------------------------------------
+ * Functions for Synchronization
+ *----------------------------------------------------------------------------*/
+struct _ipc_object_template {
+    IPC_DECLARE_OBJECT
+};
+
+static INLINE kal_bool ipc_is_object_valid(struct _ipc_object_template *object)
+{
+    kal_bool ret;
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    ret = IPC_IS_VALID_OBJECT_WO_LOCK(object)? KAL_TRUE:KAL_FALSE;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    return ret;
+}
+
+#endif /* __INC_IPC_OBJECT_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_packet_parser.h b/mcu/middleware/hif/ipcore/include/ipc_packet_parser.h
new file mode 100644
index 0000000..52df1b4
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_packet_parser.h
@@ -0,0 +1,79 @@
+#ifndef __INC_IPC_PACKET_PARSER_H
+#define __INC_IPC_PACKET_PARSER_H
+
+#include "ipc_api.h"
+#include "kal_public_api.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+
+kal_bool ipc_get_packet_info(kal_uint8 *p_packet, kal_uint16 packet_len, ipc_packet_info_t *p_info);
+kal_bool ipc_get_packet_info_gpd(kal_uint8 *p_packet, qbm_gpd *gpd, qbm_gpd *base_bd, ipc_packet_info_t *p_info);
+kal_bool ipc_get_packet_info_did(kal_uint8 *p_packet, upcm_did *did, kal_uint32 base_si_idx, ipc_packet_info_t *p_info);
+
+/*!
+ * Get new address in GPD with shift for specific offset.
+ *
+ * @param   base_addr_p [IN] Basic address pointer from GPD/BD payload content.
+ * @param   gpd [IN] GPD of input packet.
+ * @param   base_bd [IN] Corresponding BD for base_addr_p. It might be NULL if the GPD does not have BD list.
+ * @param   offset [IN] Offset to shift.
+ * @param   offset_addr_pp [OUT] Pointer of packet content after shift.
+ * @param   offset_bd_p [OUT] Pointer of corresponding BD for *offset_addr_pp.
+ *
+ * @return true if the process is success.
+ * @return false if the process is failed.
+ */
+kal_bool ipc_shift_content_ptr(kal_uint8 *base_addr_p, qbm_gpd *gpd, qbm_gpd *base_bd, kal_uint32 offset, kal_uint8 **offset_addr_pp, qbm_gpd **offset_bd_p);
+
+/*!
+ * Return pointer with "continous content" with specific length.
+ * If original GPD/BD is already continuous within gotten length, this procedure will return pointer from it.
+ * If packet content of original GPD/BD is divided in multiple pieces, this procedure will use "cont_addr_p" buffer to collect continous content to return.
+ *
+ * @param   base_addr_p [IN] Basic address pointer from GPD/BD payload content.
+ * @param   offset [IN] Offset to get payload content.
+ * @param   gpd [IN] GPD of input packet.
+ * @param   base_bd [IN] Corresponding BD for base_addr_p. It might be NULL if the GPD does not have BD list.
+ * @param   len [IN] Length of return continuous content.
+ * @param   cont_addr_pp [OUT] Pointer of returned continuous content. It might point to GPD payload or cont_buff_p if process SUCCESS.
+ * @param   cont_buff_p [IN] Alternative buffer used if GPD content is not continuous. Caller should guarantee its size >= length.
+ *
+ * @return true if the process is success.
+ * @return false if the process is failed.
+ */
+kal_bool ipc_get_continuous_content(kal_uint8 *base_addr_p, kal_uint32 offset, qbm_gpd *gpd, qbm_gpd *base_bd, kal_uint32 len, kal_uint8 **cont_addr_pp, kal_uint8 *cont_buff_p);
+
+/*!
+ * Get new address in DID with shift for specific offset.
+ *
+ * @param   base_addr_p [IN] Basic address pointer from DID/SIT payload content.
+ * @param   did [IN] DID of input packet.
+ * @param   base_si_idx [IN] Corresponding SIT index for base_addr_p.
+ * @param   offset [IN] Offset to shift.
+ * @param   offset_addr_pp [OUT] Pointer of packet content after shift.
+ * @param   offset_si_idx_p [OUT] Pointer of corresponding SIT idx for *offset_addr_pp.
+ *
+ * @return true if the process is success.
+ * @return false if the process is failed.
+ */
+kal_bool ipc_shift_did_content_ptr(kal_uint8 *base_addr_p, upcm_did *did, kal_uint32 base_si_idx, kal_uint32 offset, kal_uint8 **offset_addr_pp, kal_uint32 *offset_si_idx_p);
+
+/*!
+ * Return pointer with "continous content" with specific length.
+ * If original DID/SIT is already continuous within gotten length, this procedure will return pointer from it.
+ * If packet content of original DID/SIT is divided in multiple pieces, this procedure will use "cont_addr_p" buffer to collect continous content to return.
+ *
+ * @param   base_addr_p [IN] Basic address pointer from DID/SIT payload content.
+ * @param   offset [IN] Offset to get payload content.
+ * @param   did [IN] DID of input packet.
+ * @param   base_si_idx [IN] Corresponding SIT index for base_addr_p.
+ * @param   len [IN] Length of return continuous content.
+ * @param   cont_addr_pp [OUT] Pointer of returned continuous content. It might point to DID/SIT payload or cont_buff_p if process SUCCESS.
+ * @param   cont_buff_p [IN] Alternative buffer used if DID/SIT content is not continuous. Caller should guarantee its size >= length.
+ *
+ * @return true if the process is success.
+ * @return false if the process is failed.
+ */
+kal_bool ipc_get_continuous_content_did(kal_uint8 *base_addr_p, kal_uint32 offset, upcm_did *did, kal_uint32 base_si_idx, kal_uint32 len, kal_uint8 **cont_addr_pp, kal_uint8 *cont_buff_p);
+
+#endif  // INC_IPC_PACKET_PARSER_H
diff --git a/mcu/middleware/hif/ipcore/include/ipc_session.h b/mcu/middleware/hif/ipcore/include/ipc_session.h
new file mode 100644
index 0000000..35cff11
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_session.h
@@ -0,0 +1,451 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_session.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IP session management.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_SESSION_H
+#define __INC_IPC_SESSION_H
+
+#include "ipc_struct.h"
+#include "ipc_object.h"
+
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+#define ipc_session_type_hash(_session_type) \
+            ((_session_type) & 0x1)
+
+/*------------------------------------------------------------------------------
+ * Data structure definition.
+ *----------------------------------------------------------------------------*/
+#define IPC_SESSION_MAP_SIZE        2
+
+typedef enum _ipc_session_state_e {
+    IPC_SESSION_STATE_MIN = 0,
+    IPC_SESSION_STATE_UNBIND,
+    IPC_SESSION_STATE_PRE_BIND,
+    IPC_SESSION_STATE_BIND,
+    IPC_SESSION_STATE_PRE_LINKUP,
+    IPC_SESSION_STATE_PRE_LINKUP_IPV4_LEASE,
+    IPC_SESSION_STATE_LINKUP,
+    IPC_SESSION_STATE_IPV4_LEASE,
+    IPC_SESSION_STATE_PRE_IPV4_RELOCATE,
+    IPC_SESSION_STATE_IP_REVOKE,
+    IPC_SESSION_STATE_MAX,
+    IPC_SESSION_STATE_INVALID,
+} ipc_session_state_e;
+
+typedef enum _ipc_session_transition_action_case_e {
+    IPC_SST_NULL = 0,
+    IPC_SST_MIN,
+    IPC_SST_NA,     /* Do nothing excepting state transition */
+    IPC_SST_LUI,    /* Send Link up indication to handler */
+    IPC_SST_LUR,    /* Send Link up request to network interface */
+    IPC_SST_LDR,    /* Send Link down request to network interface */
+    IPC_SST_IUI,    /* Send IPv4 up indication to handler */
+    IPC_SST_IUR,    /* Send IPv4 up request to network interface */
+    IPC_SST_IDR,    /* Send IPv4 down request to network interface */
+    IPC_SST_MAX,
+} ipc_session_transition_action_case_e;
+
+typedef struct _ipc_netif_t ipc_netif_t;
+typedef struct _ipc_netif_t {
+    IPC_DECLARE_OBJECT
+    kal_uint32      object_idx;
+    ipc_conf_t      config;
+    kal_uint64      bit_id;
+    void           *session_map[IPC_SESSION_MAP_SIZE];
+    kal_uint32      session_cnt;
+    ipc_netif_t    *lan_netif;
+} ipc_netif_t;
+
+typedef struct _ipc_session_t {
+    IPC_DECLARE_OBJECT
+
+    kal_uint32      context; /**< Key to identify the IP session. */
+    ipc_session_state_e state;  /**< FSM state of session */
+    kal_uint8       type; /**< Type of the IP session, including IPC_IP_TYPE_IPV4, IPC_IP_TYPE_IPV6, IPC_IP_TYPE_MIXED. */
+    kal_uint8       dhcp4c_id; /**< DHCPv4 client instance ID if dhcp4c_running is KAL_TRUE. */
+    kal_uint8       reserved[2];
+    kal_bool        dhcp4c_running; /**< Indicate if DHCPv4 client is running or not. */
+    kal_int32       dhcp4c_dl_filter_id; /**< Zero or positive value for a downlink filter installed DHCPv4; Negative value otherwise. */
+
+    kal_int32       ip_id; /**< An ID for an HIF network interface to tell the associated IP session(s). */
+    ipc_netif_t    *netif; /**< Associated HIF network interface. */
+} ipc_session_t;
+
+/*------------------------------------------------------------------------------
+ * Function prototype.
+ *----------------------------------------------------------------------------*/
+
+/**
+ * Initialize all objects.
+ */
+void ipc_object_init(void);
+
+/**
+ * Find an HIF network interface.
+ * Note that, caller MUST release the control to network interface
+ * through IPC_R_UNLOCK_OBJECT() once done with it.
+ *
+ * @param   netif_id [IN] ID of the network interface interested.
+ *
+ * @return An ipc_netif_t object if found, NULL otherwise.
+ */
+ipc_netif_t *ipc_find_netif(kal_uint32 netif_id);
+
+/**
+ * Find an HIF network interface through a bit index.
+ * Note that, caller MUST release the control to network interface
+ * through IPC_R_UNLOCK_OBJECT() once done with it.
+ *
+ * @param   bit_id [IN] bit index.
+ *
+ * @return An ipc_netif_t object if found, NULL otherwise.
+ */
+ipc_netif_t *ipc_find_netif_by_bit_id(kal_uint64 bit_id);
+
+/**
+ * Find an HIF network interface through a object index.
+ * Note that, caller MUST release the control to network interface
+ * through IPC_R_UNLOCK_OBJECT() once done with it.
+ *
+ * @param   object_idx [IN] bit index.
+ *
+ * @return An ipc_netif_t object if found, NULL otherwise.
+ */
+ipc_netif_t *ipc_find_netif_by_object_id(kal_uint32 object_id);
+
+/**
+ * Create an ipc_netif_t object for an HIF network interface attached.
+ * Note that, if the network interface is already attached, this function will return NULL.
+ *
+ * @param   config [IN] Configuration of the netowrk interface attached.
+ *
+ * @return An ipc_netif_t object if succeeded, NULL otherwise.
+ */
+ipc_netif_t *ipc_new_netif(ipc_conf_t *config);
+
+/**
+ * Destroy the ipc_netif_t object for the HIF network interface to detach.
+ * Note that, if the netowrk interface is not a valid one, this function wll fail.
+ *
+ * @param   netif [IN] The netowrk interface to detach.
+ *
+ * @return  KAL_TRUE if succeed, KAL_FALSE otherwise.
+ */
+kal_bool ipc_del_netif(ipc_netif_t *netif);
+
+/**
+ * Query netif list to get latest status.
+ *
+ * @param   netif_list_p [IN] The network interface list strcture to collect status.
+ *
+ * @return  KAL_TRUE if succeed, KAL_FALSE otherwise.
+ */
+kal_bool ipc_query_netif_list(ipc_netif_list_t *netif_list_p);
+
+/**
+ * Update handling module of LINK_UP_IND ILM
+ *
+ * @param   module_id [IN] Module ID to handle MSG_ID_IPCORE_LINK_UP_IND and send MSG_ID_IPCORE_LINK_UP_RSP as response.
+ */
+void ipc_update_link_up_ind_handler(module_type module_id);
+
+/**
+ * Update handling module of IP_UP_IND ILM
+ *
+ * @param   module_id [IN] Module ID to handle MSG_ID_IPCORE_IP_UP_IND and send MSG_ID_IPCORE_IP_UP_RSP as response.
+ */
+void ipc_update_ip_up_ind_handler(module_type module_id);
+
+/**
+ * Indicate the HIF network interface link/IP status changed for handler process. Real IPCORE operation will done after handler response for the indication.
+ *
+ * @param   netif [IN] The netowrk interface.
+ * @param   ip_type [IN] Type of the PDN, IPC_IP_TYPE_IPV4, IPC_IP_TYPE_IPV6, or IPC_IP_TYPE_MIXED.
+ * @param   link_update[IN] KAL_TRUE if an IP session is established/deactived and link status is changed. KAL_FALSE if an IP information is updated for an activated IP session.
+ * @param   link_up [IN] (If link_update is KAL_TRUE) KAL_TRUE if an IP session is established, KAL_FALSE if an IP session is deactived ;
+                                    (If link_update is KAL_FALSE) KAL_TRUE if new IP information is available, KAL_FALSE if original IP information is obsoleted
+ */
+void ipc_indicate_netif_link_change(ipc_netif_t *netif, kal_uint8 ip_type, kal_bool link_update, kal_bool is_up);
+
+/**
+ * Notify the HIF network interface link/IP status changed.
+ *
+ * @param   netif [IN] The netowrk interface.
+ * @param   ip_type [IN] Type of the PDN, IPC_IP_TYPE_IPV4, IPC_IP_TYPE_IPV6, or IPC_IP_TYPE_MIXED.
+ * @param   link_update[IN] KAL_TRUE if an IP session is established/deactived and link status is changed. KAL_FALSE if an IP information is updated for an activated IP session.
+ * @param   link_up [IN] (If link_update is KAL_TRUE) KAL_TRUE if an IP session is established, KAL_FALSE if an IP session is deactived ;
+                                    (If link_update is KAL_FALSE) KAL_TRUE if new IP information is available, KAL_FALSE if original IP information is obsoleted
+ */
+void ipc_notify_netif_link_change(ipc_netif_t *netif, kal_uint8 ip_type, kal_bool link_update, kal_bool is_up);
+
+/**
+ * Find index of the associated IP session.
+ *
+ * @param   netif [IN] The netowrk interface.
+ *
+ * @return Index of the associated IP session, <0 means no associated IP session is found.
+ */
+kal_int32 ipc_map_netif_to_ip_id(ipc_netif_t *netif);
+
+/**
+ * Find PDN ID of the associated IP session.
+ *
+ * @param   netif [IN] The netowrk interface.
+ * @param   ip_type [IN] The IP type of the session.
+ *
+ * @return PDN ID of the associated IP session, IPC_INVALID_PDN_ID means no associated IP session is found.
+ */
+kal_int32 ipc_map_netif_to_pdn_id(ipc_netif_t *netif, kal_uint8 ip_type);
+
+/**
+ * Specify the network interface needs UL reload retry or not.
+ *
+ * @param   netif [IN] The netowrk interface.
+ * @param   need_ul_reload [IN] KAL_TRUE if it needs UL reload retry, KAL_FALSE otherwise.
+ */
+void ipc_set_netif_ul_reload_retry(ipc_netif_t *netif, kal_bool need_ul_reload);
+
+/**
+ * Specify if the network interface calls ipc_need_ul_retry between netif's reload cbk and ul_reload_retry be set.
+ *
+ * @param   netif [IN] The netowrk interface.
+ * @param   need_ul_reload [IN] KAL_TRUE if it needs UL reload retry, KAL_FALSE otherwise.
+ */
+void ipc_set_netif_ul_set_need_reload(ipc_netif_t *netif, kal_bool need_ul_reload);
+
+/**
+ * Get UL reload status of all network interfaces.
+ *
+ * @return Each bit indicate if the corresponding network interface needs UL reload retry.
+ */
+kal_uint64 ipc_get_all_netif_ul_reload_retry(void);
+
+/**
+ * Execute session state transition and corresponding behavior.
+ *
+ * @param   session [IN] The netowrk session.
+ * @param   session_state [IN] New session type to translate.
+ * @return KAL_TRUE if succeed, KAL_FALSE otherwise.
+ */
+kal_bool ipc_update_session_state(ipc_session_t *session, ipc_session_state_e session_state);
+
+/**
+ * Find an IP session with specified session_context.
+ * Note that, caller MUST release the control to IP session
+ * through IPC_R_UNLOCK_OBJECT() once done with it.
+ *
+ * @param   session_context [IN] Key to identify the IP session.
+ *
+ * @return An ipc_session_t object if found, NULL otherwise.
+ */
+ipc_session_t *ipc_find_session_by_context(kal_uint32 session_context);
+
+/**
+ * Find the session object associated with specified HIF network interface and session_type.
+ * Note that, caller MUST release the control to IP session
+ * through IPC_R_UNLOCK_OBJECT() once done with it.
+ *
+ * @param   netif [IN] The netowrk interface.
+ * @param   session_type [IN] Type of the IP session, either IPC_IP_TYPE_IPV4 or IPC_IP_TYPE_IPV6.
+ *
+ * @return An ipc_session_t object if found, NULL otherwise.
+ */
+ipc_session_t *ipc_find_session_by_netif(ipc_netif_t *netif, kal_uint8 session_type);
+
+/**
+ * Find the session object associated with specified ip_id and session type.
+ * Note that, caller MUST release the control to IP session
+ * through IPC_R_UNLOCK_OBJECT() once done with it.
+ *
+ * @param   ip_id [IN] An ID for an HIF network interface to tell the associated IP session(s).
+ * @param   session_type [IN] Type of the IP session, either IPC_IP_TYPE_IPV4 or IPC_IP_TYPE_IPV6.
+ *
+ * @return An ipc_session_t object if found, NULL otherwise.
+ */
+ipc_session_t *ipc_find_session_by_ip_id(kal_int32 ip_id, kal_uint8 session_type);
+
+/**
+ * Create an ipc_session_t object for the IP session established.
+ *
+ * @param   netif [IN] HIF network interface associated with the IP sesion.
+ * @param   session_context [IN] Key to identify the IP session.
+ * @param   session_type [IN] Type of the IP session: IPC_IP_TYPE_IPV4, IPC_IP_TYPE_IPV6, or IPC_IP_TYPE_MIXED.
+ * @param   session_state [IN] Initial state of the IP session.
+ *
+ * @return An ipc_session_t object if succeeded, NULL otherwise.
+ */
+ipc_session_t *ipc_new_session(ipc_netif_t *netif, kal_uint32 session_context, kal_uint8 session_type, ipc_session_state_e session_state);
+
+/**
+ * Destroy the ipc_session_t object for the IP session deactivated.
+ *
+ * @param   session [IN] IP session deactivated.
+ */
+void ipc_del_session(ipc_session_t *session);
+
+/**
+ * Destroy the old session and replace with the new IP session.
+ * Note that the ip_id will remain the same as before.
+ *
+ * @param   netif [IN] HIF network interface associated with the IP session.
+ * @param   old_session [IN] IP session deactivated.
+ * @param   new_session_context [IN] Key to identify the IP session.
+ * @param   new_session_type [IN] Type of the IP session: IPC_IP_TYPE_IPV4, IPC_IP_TYPE_IPV6, or IPC_IP_TYPE_MIXED.
+ * @param   new_session_state [IN] Initial state of the IP session.
+ *
+ * @return An ipc_session_t object if succeeded, NULL otherwise.
+ */
+ipc_session_t *ipc_replace_session(ipc_netif_t *netif, ipc_session_t *old_session, kal_uint32 new_session_context, kal_uint8 new_session_type, ipc_session_state_e new_session_state);
+
+/**
+ * restore netif / session mapping
+ *
+ * @param   p_netif   [IN] which netif should restore session
+ * @param   p_ip_type [IN] session type
+ *
+ * @return KAL_TRUE / KAL_FALSE
+ */
+kal_bool ipc_session_restore_netif_map(ipc_netif_t *p_netif, kal_uint8 *p_ip_type);
+
+/**
+ * send restore ind to IPCore context
+ *
+ * @param   netif_id       [IN] which netif_id should restore
+ * @param   ip_type        [IN] session ip type
+ * @param   is_link_update [IN] link_update status
+ * @param   is_up          [IN] up status
+ *
+ * @return KAL_TRUE / KAL_FALSE
+ */
+void ipc_session_send_restore_netif_ind(kal_uint32 netif_id, kal_uint8 ip_type, kal_bool is_link_update, kal_bool is_up);
+
+#endif /* __INC_IPC_SESSION_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_trace.h b/mcu/middleware/hif/ipcore/include/ipc_trace.h
new file mode 100644
index 0000000..498cc74
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_trace.h
@@ -0,0 +1,17 @@
+#ifndef __INC_IPC_TRACE_H
+#define __INC_IPC_TRACE_H
+#if HIF_CONSOLE_TRACE_ENABLED != 1
+#ifndef GEN_FOR_PC
+ #include "kal_public_defs.h"
+#endif /* GEN_FOR_PC */
+#include "dhl_trace.h"
+#include "dhl_def.h"
+#if !defined(GEN_FOR_PC)
+#if defined(__DHL_MODULE__) || defined(__CUSTOM_RELEASE__)
+#endif /* TST Trace Defintion */
+#endif
+#endif /* HIF_CONSOLE_TRACE_ENABLED != 1 */
+#if !defined(GEN_FOR_PC)
+#include"ipc_trace_mod_ipcore_utmd.h"
+#endif
+#endif /* __INC_IPC_TRACE_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_trace_mod_ipcore_utmd.json b/mcu/middleware/hif/ipcore/include/ipc_trace_mod_ipcore_utmd.json
new file mode 100644
index 0000000..465b99c
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_trace_mod_ipcore_utmd.json
@@ -0,0 +1,2870 @@
+{
+  "legacyParameters": {},
+  "module": "MOD_IPCORE",
+  "startGen": "Legacy",
+  "endGen": "-",
+  "traceClassDefs": [
+    {
+      "TRACE_DEBUG": {
+        "debugLevel": "Low",
+        "tag": [
+          "Baseline",
+          "TRACE_DEBUG"
+        ],
+        "traceType": "DesignInfo"
+      }
+    },
+    {
+      "TRACE_INFO": {
+        "debugLevel": "Ultra-High",
+        "tag": [
+          "Baseline",
+          "TRACE_INFO"
+        ],
+        "traceType": "Public"
+      }
+    },
+    {
+      "TRACE_WARNING": {
+        "debugLevel": "High",
+        "tag": [
+          "Baseline",
+          "TRACE_WARNING"
+        ],
+        "traceType": "Public"
+      }
+    },
+    {
+      "TRACE_SENSITIVE_USIR": {
+        "debugLevel": "Ultra-High", 
+        "tag": [
+          "Baseline", 
+          "TRACE_SENSITIVE_USIR",
+          "USIR"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "TRACE_ERROR": {
+        "debugLevel": "Ultra-High",
+        "tag": [
+          "Baseline",
+          "TRACE_ERROR"
+        ],
+        "traceType": "Public"
+      }
+    }
+  ],
+  "traceDefs": [
+    {
+      "IPC_TR_ILM_WRONG_DEST_MOD": {
+        "format": "[IPCORE] ipc_on_ilm(): wrong dest_mod_id(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NETIF_ATTACHING": {
+        "format": "[IPCORE] ipc_attach(): module_id(%d), netif_id(%d), callback_context(0x%x), features(0x%x)...",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NETIF_ATTACHED": {
+        "format": "[IPCORE] ipc_new_netif(): module_id(%d), netif_id(%d) has attached successfully",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NETIF_ATTACH_OUT_OF_SPACE": {
+        "format": "[IPCORE] ipc_new_netif(): module_id(%d), netif_id(%d) failed for out of space!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NETIF_ATTACH_DUPLICATED": {
+        "format": "[IPCORE] ipc_new_netif(): module_id(%d), netif_id(%d) has attached before!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NETIF_DETACHING": {
+        "format": "[IPCORE] ipc_detach(): handle(0x%x)...",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NETIF_DETACHED": {
+        "format": "[IPCORE] ipc_detach(): module_id(%d), netif_id(%d) has detached successfully",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NETIF_DETACH_INVALID": {
+        "format": "[IPCORE] ipc_del_netif(): invalid netif to detach!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_RESET_START": {
+        "format": "[IPCORE] ipc_reset(): Start to handle IPCore reset",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GET_QBM_DATAHEAD_ZERO_LENGTH_BD": {
+        "format": "[IPCORE] ipc_get_qbm_datahead(): Found non-zero length GPD with all-zero length BD list, this should not happen: gpd(0x%x), gpd_len(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEL_SESSION": {
+        "format": "[IPCORE] ipc_reset(): Delete session[0x%x] for idx[%d]",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEL_SESSION_INFO": {
+        "format": "[IPCORE] ipc_reset(): Delete session information(type[%d], ip_id[%d]) for idx[%d]",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEL_NETIF": {
+        "format": "[IPCORE] ipc_reset(): Delete netif[0x%x] for idx[%d]",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_RESET_END": {
+        "format": "[IPCORE] ipc_reset(): Handle IPCore reset is done",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_START": {
+        "format": "[IPCORE] ipc_on_pdn_bind_top(): binding request received",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_INFO": {
+        "format": "[IPCORE] ipc_on_pdn_bind_top(): network_interface_id(0x%X), pdn_id(0x%X), ip_addr_type(%d)...",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IP_INFO": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Configure IP information for network_interface_id(0x%X), pdn_id(0x%X), ip_addr_type(%d):Mapped NMU ip_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV6_DNS_USIR": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Add IPv6 DNS to NMU ip_id(%d):[%02X] %S%S:%S%S:%S%S:%S%S:%S%S:%S%S:%S%S:%S%S",
+        "traceClass": "TRACE_SENSITIVE_USIR"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV6_DNS_NUM": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Set IPv6 DNS number(%d) to NMU ip_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV6_ZERO_IID_LEN": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Set IPv6 IID length of NMU ip_id(%d) to ZERO",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV6_IID_USIR": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Set IPv6 IID to NMU ip_id(%d):IID length(%d) %S%S:%S%S:%S%S:%S%S:%S%S:%S%S:%S%S:%S%S",
+        "traceClass": "TRACE_SENSITIVE_USIR"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV6_DOWN": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): NMU ip_id(%d) - IPv6 DOWN",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV6_UP": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): NMU ip_id(%d) - IPv6 UP",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV4_DNS_USIR": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Add IPv4 DNS to NMU ip_id(%d):[%02X] %S.%S.%S.%S",
+        "traceClass": "TRACE_SENSITIVE_USIR"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV4_DNS_NUM": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Set IPv4 DNS number(%d) to NMU ip_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV4_ADDR_USIR": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Set IPv4 address to NMU ip_id(%d): %S.%S.%S.%S",
+        "traceClass": "TRACE_SENSITIVE_USIR"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV4_FAKE_INFO_USIR": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): NMU ip_id(%d) - Trigger IPv4 fake info generation for IPv4 address %S.%S.%S.%S",
+        "traceClass": "TRACE_SENSITIVE_USIR"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV4_UP": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): NMU ip_id(%d) - IPv4 UP",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_CFG_IPV4_DOWN": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): NMU ip_id(%d) - IPv4 DOWN",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_DHCP4C": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Enable DHCP4C for netif_id(%d), features(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_SESSION_RLOCK_FAIL": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): session readlock is failed for network_card(0x%X), pdn_id(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_DYNAMIC_Q_ERROR": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): dynamic HW queue setting error : network_card(0x%X), pdn_id(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_NEW_SESSION_FAIL": {
+        "format": "[IPCORE] ipc_on_pdn_bind_top(): session allocation is failed for network_card(0x%X), pdn_id(0x%X), ip_type(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_INVALID_NETIF": {
+        "format": "[IPCORE] ipc_on_pdn_bind_top(): no netif found for network_card(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_UNSUPPORTED_IP_ADDR_TYPE": {
+        "format": "[IPCORE] ipc_on_pdn_bind_top(): unsupported ip_addr_type(%d)! pdn_id(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_NULL_PARAM": {
+        "format": "[IPCORE] ipc_on_pdn_bind_top(): NULL parameter!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_START": {
+        "format": "[IPCORE] ipc_new_session(): New session - session_context(0x%X), session_type(0x%X), session_state(0x%X).",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_NETIF_BOUND_MIXED": {
+        "format": "[IPCORE] ipc_new_session():(IPV4V6) netif(0x%x)/netif_id(%d) has already bound with session (map[v4]=0x%x, map[v6]=0x%x)! session_context(0x%X), session_type(0x%X), session_state(0x%X) bind fail.",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_NETIF_BOUND_SPECIFIC_IP_VER": {
+        "format": "[IPCORE] ipc_new_session():(v4_or_v6) netif(0x%x)/netif_id(%d) has already bound with session (map[v4]=0x%x, map[v6]=0x%x)! session_context(0x%X), session_type(0x%X), session_state(0x%X) bind fail.",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_DUPLICATED": {
+        "format": "[IPCORE] ipc_new_session(): session_context(0x%X), session_type(0x%X), session_state(0x%X) has already bound!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BIND_OUT_OF_SPACE": {
+        "format": "[IPCORE] ipc_new_session(): session_context(0x%X), session_type(0x%X), session_state(0x%X) failed for out of space!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_RESULT": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): binding request handling - result(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_RSP_PARAM_GEN": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): Generate binding response parameter - network_interface_id(%d), pdn_id(%d), sizeof(ip_addr_struct)=%d, sizeof(dns_struct)=%d, sizeof(upcm_ipcore_back_info_t)=%d",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BINDING_RSP": {
+        "format": "[IPCORE] ipc_on_pdn_bind_bot(): sending response for binding request - result(0x%X), dst_module(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_BOUND": {
+        "format": "[IPCORE] ipc_new_session(): session_context(0x%X), session_type(0x%X), session_state(0x%X) has bound successfully => ip_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_DEACTIVATING": {
+        "format": "[IPCORE] ipc_on_pdn_unbind(): pdn_id(0x%X)...",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_DEACTIVATE_NO_SESSION_FOUND": {
+        "format": "[IPCORE] ipc_on_pdn_unbind(): no session found for pdn_id(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_DEACTIVATE_NULL_PARAM": {
+        "apiType": "index",
+        "format": "[IPCORE] ipc_on_pdn_unbind(): NULL parameter!",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_TR_SESSION_DEACTIVATE_INVALID_SESSION": {
+        "format": "[IPCORE] ipc_del_session(): it's not a valid session!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_DEACTIVATED": {
+        "format": "[IPCORE] ipc_del_session(): session_context(0x%X), session_type(0x%X), ip_id(%d) has deactivated successfully",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBINDING_INFO": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): network_interface_id(0x%X), old_pdn_id(0x%X), new_pdn_id(0x%X), ip_addr_type(%d)...",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBIND_UNSUPPORTED_IP_ADDR_TYPE": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): unsupported ip_addr_type(%d)! new_pdn_id(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBIND_REPLACE_SESSION_FAIL": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): old session deletion or session allocation is failed for network_card(0x%X), old_pdn_id(0x%X), new_pdn_id(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBIND_SESSION_RLOCK_FAIL": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): session readlock is failed for network_card(0x%X), old_pdn_id(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBIND_INVALID_NETIF": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): no netif found for network_card(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBIND_NULL_PARAM": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): NULL parameter!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBINDING_RESULT": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): binding request handling - result(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBINDING_RSP_PARAM_GEN": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): Generate rebinding response parameter - network_interface_id(%d), old_pdn_id(%d), new_pdn_id(%d), sizeof(ip_addr_struct)=%d, sizeof(dns_struct)=%d, sizeof(upcm_ipcore_back_info_t)=%d",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBINDING_RSP": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): sending response for binding request - result(0x%X), dst_module(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REBIND_START": {
+        "format": "[IPCORE] ipc_replace_session(): Replace session - netif(0x%X), old_session(0x%X), new_session_context(0x%X), new_session_type(0x%X), new_session_state(0x%X).",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REPLACED": {
+        "apiType": "index",
+        "format": "[IPCORE] ipc_replace_session(): session_context(0x%X), session_type(0x%X), session_state(0x%X) has been replaced successfully => ip_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REPLACE_NETIF_RLOCK_FAIL": {
+        "format": "[IPCORE] ipc_replace_session(): netif readlock is failed!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SESSION_REPLACE_SESSION_RLOCK_FAIL": {
+        "format": "[IPCORE] ipc_on_pdn_rebind(): session readlock is failed!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_START": {
+        "format": "[IPCORE] ipc_update_session_state(): Update session_context(0x%X) to state(%d) start",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_ORG_AND_NEW": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X) session_type(0x%X) of netif_context(0x%X) from org_state(%d) to new_state(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_TRANSITION_SUCCESS": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X) update to state(%d) successfully",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_WRITE_FAIL": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X) update to state(%d) fail",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_SST_NA": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), state(%d)->(%d), do nothing else",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_SST_LUI": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), state(%d)->(%d), LinkUpIndication",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_SST_LUR": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), state(%d)->(%d), LinkUpRequest(netif[0x%X], IPType[%d])",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_SST_LDR": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), state(%d)->(%d), LinkDownRequest(netif[0x%X], IPType[%d])",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_SST_IUI": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), state(%d)->(%d), IpUpIndication",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_SST_IUR": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), state(%d)->(%d), IpUpRequestion(netif[0x%X], IPType[%d])",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_SST_IDR": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), state(%d)->(%d), IpDownRequestion(netif[0x%X], IPType[%d])",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_ILLEGAL_TRANSITION": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), state(%d)->(%d), Unknown action(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_OUT_OF_RANGE": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), state(%d)->(%d), Illegal transaction!(Min state[%d], Max state[%d])",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_READ_FAIL": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), session state read error !",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_CHK_FAIL": {
+        "format": "[IPCORE] ipc_update_session_state(): Session_context(0x%X), session check error !",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_SESSION_STATE_END": {
+        "format": "[IPCORE] ipc_update_session_state(): Update session_context(0x%X) to state(%d) end with retval(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_INVALID_PARAM": {
+        "format": "[IPCORE] invalid parameters for uplink handle(0x%X), ior (0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_DROP_FOR_SESSION_DEACT": {
+        "format": "[IPCORE] netif_id(%d) drops ior(0x%X) ip_type(%d) uplink packets for session deactivated!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_DROP_FOR_INVALID_NETIF": {
+        "format": "[IPCORE] netif(0x%X) drops uplink packets [ior(0x%X)] for invalid netif!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_UL_DROP_FOR_SESSION_DEACT": {
+        "format": "[IPCORE] netif_id(0x%X) drops uplink packet META(0x%x) ip_type(%d) for session deactivated!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_UL_DROP_FOR_INVALID_NETIF": {
+        "format": "[IPCORE] netif_id(0x%X) drops uplink packet [META: idx(%d), q_type(%d)] for invalid netif!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_UL_DROP_FOR_NONE_IP_PKT": {
+        "format": "[IPCORE] netif_id(0x%X) Found non-IPv4/IPv6 packet [META: idx(%d), q_type(%d)], drop!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_UL_DROP_FOR_NONE_IP_PKT2": {
+        "format": "[IPCORE] netif_id(0x%X) Found non-IPv4/IPv6 packet META: idx(%d), drop!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_UL_DROP_FOR_LAN_DID_ALLOC_FAIL": {
+        "format": "[IPCORE] lan netif_id(%d) drops uplink packet META(0x%x) read_idx(%d) for lan DID allocation failed!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_UL_DROP_FOR_LAN_DID_ALLOC_FAIL_CAUSE_DID_NULL": {
+        "format": "[IPCORE] lan netif is_DID is NULL, lan src_netif_id(0x%x), is_DID(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_UL_DROP_FOR_LAN_DID_ALLOC_FAIL_DID_ALLOC_NG": {
+        "format": "[IPCORE] lan DID allocation failed, lan src_netif_id(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_UL_DROP_FOR_LAN_DID_ALLOC_FAIL_NETIF_NULL": {
+        "format": "[IPCORE] lan DID allocation failed, lan src_netif_id(0x%x), lan_netif(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_UL_DROP_FOR_LAN_DEVICE_NG": {
+        "format": "[IPCORE] lan device is out of bound, lan src_netif_id(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_DROP_FOR_INVALID_IOR": {
+        "format": "[IPCORE] netif_id(%d) drops uplink packets for invalid ior(0x%X) first_gpd(0x%X) last_gpd(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DPFM_DROP_FOR_LAN_NETIF_DETACH": {
+        "format": "[IPCORE] drops type(%d) head_ior(0x%X) downlink packets for lan netif detached!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_DROP_FOR_NETIF_INFO_LOCK_FAIL": {
+        "format": "[IPCORE] pdn_id(%d) ip_id(%d) drops type(%d) [p_head(0x%X), p_tail(0x%X)] downlink packets : netif detach found during getting netif information!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_DID_DROP_FOR_NETIF_INFO_LOCK_FAIL": {
+        "format": "[IPCORE] pdn_id(%d) ip_id(%d) drops type(%d) [did_head(0x%X), did_tail(0x%X)] downlink packets : netif detach found during getting netif information!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_DROP_FOR_NETIF_INFO_LOCK_FAIL": {
+        "format": "[IPCORE] pdn_id(%d) ip_id(%d) drops type(%d) [meta_idx(0x%X)] downlink packets : netif detach found during getting netif information!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_DROP_FOR_NETIF_DETACH": {
+        "format": "[IPCORE] pdn_id(%d) ip_id(%d) drops type(%d) [p_head(0x%X), p_tail(0x%X)] downlink packets for netif detached!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_DID_DROP_FOR_NETIF_DETACH": {
+        "format": "[IPCORE] pdn_id(%d) ip_id(%d) drops type(%d) [did_head(0x%X), did_tail(0x%X)] downlink packets for netif detached!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_PENDING_DID_DROP_FOR_NETIF_DETACH": {
+        "format": "[IPCORE] drops type(%d) Pending DID:[did_head(0x%X), did_tail(0x%X)] downlink packets for netif detached!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_DROP_FOR_INVALID_SESSION": {
+        "format": "[IPCORE] pdn_id(%d) drops downlink packets [p_head(0x%X), p_tail(0x%X)] for invalid session!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_DID_DROP_FOR_INVALID_SESSION": {
+        "format": "[IPCORE] pdn_id(%d) drops downlink packets [did_head(0x%X), did_tail(0x%X)] for invalid session!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_DROP_FOR_INVALID_SESSION": {
+        "format": "[IPCORE] pdn_id(%d) drops downlink packets [meta_idx(0x%X)] for invalid session!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_PENDING_DID_DROP_FOR_INVALID_SESSION": {
+        "format": "[IPCORE] netif(0x%X) drops downlink pending packets [did_head(0x%X), did_tail(0x%X)] for invalid session!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NOTIFY_LINK_CHANGE_BEGIN": {
+        "format": "[IPCORE] ipc_notify_link_change(): Link change notification start: netif_id(%d) ip_type(%d) link_update(%d) is_up(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NOTIFY_LINK_CHANGE_FOR_NETIF_BEGIN": {
+        "format": "[IPCORE] ipc_notify_link_change(): Link change for found netif(0x%x) for netif_id(%d) start",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NOTIFY_LINK_CHANGE_FOR_NETIF_END": {
+        "format": "[IPCORE] ipc_notify_link_change(): Link change for found netif(0x%x) for netif_id(%d) done",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NOTIFY_LINK_CHANGE_UNKNOWN_NETIF": {
+        "format": "[IPCORE] ipc_notify_link_change(): Unknown netif_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NOTIFY_LINK_CHANGE_END": {
+        "format": "[IPCORE] ipc_notify_link_change(): Link change notification done: netif_id(%d) ip_type(%d) link_update(%d) is_up(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_UL_FILTER_CBK_BEGIN": {
+        "format": "[IPCORE] ipc_register_ul_filter_cbk(): rules(0x%X) callback_func(0x%X) callback_context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_DL_FILTER_CBK_BEGIN": {
+        "format": "[IPCORE] ipc_register_dl_filter_cbk(): rules(0x%X) callback_func(0x%X) callback_context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_UL_FILTER_MSG_BEGIN": {
+        "format": "[IPCORE] ipc_register_ul_filter_msg(): rules(0x%X) callback_module(0x%X) callback_context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_DL_FILTER_MSG_BEGIN": {
+        "format": "[IPCORE] ipc_register_dl_filter_msg(): rules(0x%X) callback_module(0x%X) callback_context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_UL_FILTER_WITH_INFO_CBK_BEGIN": {
+        "format": "[IPCORE] ipc_register_ul_filter_with_info_cbk(): rules(0x%X) callback_func(0x%X) callback_context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_DL_FILTER_WITH_INFO_CBK_BEGIN": {
+        "format": "[IPCORE] ipc_register_dl_filter_with_info_cbk(): rules(0x%X) callback_func(0x%X) callback_context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_UL_FILTER_WITH_INFO_MSG_BEGIN": {
+        "format": "[IPCORE] ipc_register_ul_filter_with_info_msg(): rules(0x%X) callback_module(0x%X) callback_context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_DL_FILTER_WITH_INFO_MSG_BEGIN": {
+        "format": "[IPCORE] ipc_register_dl_filter_with_info_msg(): rules(0x%X) callback_module(0x%X) callback_context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREG_UL_FILTER_BEGIN": {
+        "format": "[IPCORE] ipc_deregister_ul_filter(): filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREG_DL_FILTER_BEGIN": {
+        "format": "[IPCORE] ipc_deregister_dl_filter(): filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_ZERO_VALID_FIELD": {
+        "format": "[IPCORE] ipc_validate_rules(): valid_fields cannot be 0!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_FOR_UL": {
+        "format": "[IPCORE] ipc_validate_rules(): uplink(%d), valid_fields(0x%X) and ip_type(%d) are invalid for uplink filter!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_FOR_DL": {
+        "format": "[IPCORE] ipc_validate_rules(): uplink(%d), valid_fields(0x%X) and ip_type(%d) are invalid for downlink filter!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_FOR_L4_INFO": {
+        "format": "[IPCORE] ipc_validate_rules(): uplink(%d), valid_fields(0x%X) and ip_type(%d) are invalid for L4 INFO!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_FOR_IPV4": {
+        "format": "[IPCORE] ipc_validate_rules(): uplink(%d), valid_fields(0x%X) and ip_type(%d) are invalid for IPv4 or MIXED type!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_FOR_IPV6": {
+        "format": "[IPCORE] ipc_validate_rules(): uplink(%d), valid_fields(0x%X) and ip_type(%d) are invalid for IPv6 or MIXED type!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_FOR_UNSUPPORTED_PROTOCOL": {
+        "format": "[IPCORE] ipc_validate_rules(): unsupported protocol(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_FOR_FRAG": {
+        "format": "[IPCORE] ipc_validate_rules(): uplink(%d), valid_fields(0x%X), ip_type(%d) and features(0x%X) are invalid for fragment!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NEW_FILTER_INVALID_PARAMS": {
+        "format": "[IPCORE] ipc_new_filter_id(): failed with invalid parameters: rules(0x%X), callback_func(0x%X), module_id(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NEW_FILTER_UNAVAILABLE": {
+        "format": "[IPCORE] ipc_new_filter_id(): failed with all filters are busy now!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_HW_FILTER_OK": {
+        "format": "[IPCORE] ipc_update_hw_filter(): update to HW total_entry(%d) v6_unknown_check(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_HW_FILTER_COUNT": {
+        "format": "[IPCORE] ipc_update_hw_filter(): ip_type(%d) count(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_HW_FILTER_TOO_MUCH": {
+        "format": "[IPCORE] ipc_update_hw_filter(): too much filter, ip_type(%d) filter_num(%d) entry_num(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_HW_FILTER_TABLE_INFO": {
+        "format": "[IPCORE] ipc_update_hw_filter(): table base addr(0x%X) max_entry_num (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REGISTER_FILTER_VALIDATE_FAIL": {
+        "format": "[IPCORE] ipc_register_filter_by_ilm(): filter rule validate fail: uplink?(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REGISTER_FILTER_OK": {
+        "format": "[IPCORE] ipc_register_filter(): created a new filter successfully: uplink?(%d), filter_id(%d), features(0x%X), ip_type(%d) valid_fields(0x%X), with_ipv4(%d), with_ipv6(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REGISTER_FILTER_NG": {
+        "format": "[IPCORE] ipc_register_filter_by_ilm(): failed to create a new filter!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REGISTER_FILTER_ADD_TO_LIST": {
+        "format": "[IPCORE] ipc_register_filter(): add filter_id(%d) to IPv%d filter list. uplink?(%d). v4_de_pending_cnt (0x%x), v6_de_pending_cnt (0x%x), reserved_cnt (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILTER_CNT": {
+        "format": "[IPCORE] ipc_filter_list_dump_all(): total filter num : v4_ul(%d) v4_dl(%d) v6_ul(%d) v6_dl(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILTER_ID_DUMP_4": {
+        "format": "[IPCORE] ipc_filter_list_dump(): filter ID dump : (%d) (%d) (%d) (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILTER_ID_DUMP_3": {
+        "format": "[IPCORE] ipc_filter_list_dump(): filter ID dump : (%d) (%d) (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILTER_ID_DUMP_2": {
+        "format": "[IPCORE] ipc_filter_list_dump(): filter ID dump : (%d) (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILTER_ID_DUMP_1": {
+        "format": "[IPCORE] ipc_filter_list_dump(): filter ID dump : (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILTER_ID_DUMP_INFO_v4": {
+        "format": "[IPCORE] ipc_filter_list_dump_all(): IPv4 filter ID number info : is_uplink(%d) number(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILTER_ID_DUMP_INFO_v6": {
+        "format": "[IPCORE] ipc_filter_list_dump_all(): IPv6 filter ID number info : is_uplink(%d) number(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEL_FILTER_INVALID_OBJECT": {
+        "format": "[IPCORE] ipc_del_filter(): filter (0x%x) an invalid object!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREGISTER_FILTER_WITH_INVALID_ID": {
+        "format": "[IPCORE] ipc_deregister_filter_by_ilm(): this filter invalid filter_id(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREGISTER_FILTER_NOT_FOUND": {
+        "format": "[IPCORE] ipc_deregister_filter(): filter_id(%d) is not found!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREGISTER_FILTER_INFO": {
+        "format": "[IPCORE] ipc_deregister_filter(): deleting a filter: filter_id(%d), features(0x%X), valid_fields(0x%X), with_ipv4(%d), with_ipv6(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REMOVE_DL_FILTER_FROM_LIST": {
+        "format": "[IPCORE] ipc_deregister_filter(): remove filter_id(%d) from IPv%d filter list",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REMOVE_DL_FILTER_RETRY": {
+        "format": "[IPCORE] ipc_deregister_filter(): need retry remove filter_id(%d) ",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_EN_REG_DL_FILTER_OK": {
+        "format": "[IPCORE] ipc_enable_dhcp4c(): session context(%d) type(%d) registered DL filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_EN_REG_DL_FILTER_NG": {
+        "format": "[IPCORE] ipc_enable_dhcp4c(): session context(%d) type(%d) failed to register DL filter(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_EN_FAILED_WITH_INVALID_PARAMETER": {
+        "format": "[IPCORE] ipc_enable_dhcp4c(): invalid session_ptr!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_DIS_INFO": {
+        "format": "[IPCORE] ipc_disable_dhcp4c(): session context(%d) type(%d) dhcp4c: running(%d)/dhcp_id(%d)/filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_DIS_DEREG_DL_FILTER_OK": {
+        "format": "[IPCORE] ipc_disable_dhcp4c(): session context(%d) type(%d) deregistered DL filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_DIS_FAILED_WITH_INVALID_PARAMETER": {
+        "format": "[IPCORE] ipc_disable_dhcp4c(): invalid session_ptr!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_ACT_RSP_FIND_NO_SESSION": {
+        "format": "[IPCORE] ipc_on_dhcp4c_activate_rsp(): failed to find session for ip_id(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_ACT_RSP_OK": {
+        "format": "[IPCORE] ipc_on_dhcp4c_activate_rsp(): session context(%d) type(%d) gets dhcp4c_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_ACT_RSP_INVALID_SESSION": {
+        "format": "[IPCORE] ipc_on_dhcp4c_activate_rsp(): the session for ip_id(%d) became invalid!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_ACT_RSP_NG": {
+        "format": "[IPCORE] ipc_on_dhcp4c_activate_rsp(): session context(%d) type(%d) failed to activate DHCPv4!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_UP_IND_START": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_up_ind(): Start to handle DHCPv4 IP up indication : dhcp4c_ip_up_ind_ptr(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_UP_IND_FIND_SESSION_RESULT": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_up_ind(): Result of finding session to for ip up indication : session(0x%x), ip_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_UP_IND_SESSION_STATE": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_up_ind(): Current session state : session(0x%x), session_state(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_UP_IND_END": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_up_ind(): Handle DHCPv4 IP up indication is done : dhcp4c_ip_up_ind_ptr(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_UP_IND_SESSION_STATE_INCORRECT": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_up_ind(): session state is incorrect for ip_id(%d) : session(0x%x), state(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_UP_IND_FIND_NO_SESSION": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_up_ind(): failed to find session for ip_id(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_DOWN_IND_START": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_down_ind(): Start to handle DHCPv4 IP down indication : dhcp4c_ip_down_ind_ptr(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_DOWN_IND_FIND_SESSION_RESULT": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_down_ind(): Result of finding session to for ip down indication : session(0x%x), ip_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_DOWN_IND_SESSION_STATE": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_down_ind(): Current session state : session(0x%x), session_state(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_DOWN_IND_END": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_down_ind(): Handle DHCPv4 IP down indication is done : dhcp4c_ip_down_ind_ptr(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_DOWN_IND_SESSION_STATE_INCORRECT": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_down_ind(): session state is incorrect for ip_id(%d) : session(0x%x), state(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_DOWN_IND_FIND_NO_SESSION": {
+        "format": "[IPCORE] ipc_on_dhcp4c_ip_down_ind(): failed to find session for ip_id(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_PACKET_IND_UPLINK_NG": {
+        "format": "[IPCORE] ipc_on_dhcp4c_packet_ind(): failed to send the uplink GPD with ip_id(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_IP_PACKET_IND_FIND_NO_SESSION": {
+        "format": "[IPCORE] ipc_on_dhcp4c_packet_ind(): failed to find session for ip_id(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_ON_DL_PACKET_FIND_NO_SESSION": {
+        "format": "[IPCORE] ipc_on_dl_dhcp4_packet(): failed to find the session(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DHCP4C_ON_DL_PACKET_INVALID_GPD_LIST": {
+        "format": "[IPCORE] ipc_on_dl_dhcp4_packet(): discard the downlink IP datagram since head_gpd(0x%x) != tail_gpd(0x%x), length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_PACK_PKT_UDP_SIZE_NG": {
+        "format": "[IPCORE] ipc_pack_pkt(): uplink(%d) : ip_header(%u)+udp_header(%u)+data_len(%u) exceeds %u-byte!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_PACK_PKT_ALLOC_GPD_NG": {
+        "format": "[IPCORE] ipc_pack_pkt(): failed to allocate NET_UL_GPD for %u-byte of packet to send!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_PACK_PKT_SKIP_INVALID_GPD": {
+        "format": "[IPCORE] ipc_pack_pkt(): skip header pack for invalid GPD : gpd(0x%x), gpd_len(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_PACK_PKT_PUBLIC_FAILED": {
+        "format": "[IPCORE] ipc_pack_pkt_public(): failed to pack packet : isGPD(%d), hdr(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_PKT_PKT_PACK_FAILED": {
+        "format": "[IPCORE] ipc_send_ul_pkt(): failed to pack uplink packet : isGPD(%d), hdr(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_PKT_BY_PDN_PKT_PACK_FAILED": {
+        "format": "[IPCORE] ipc_send_ul_pkt_by_pdn(): failed to pack uplink packet : isGPD(%d), hdr(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_PKT_BY_PDN_SESSION_NOT_FOUND": {
+        "format": "[IPCORE] ipc_send_ul_pkt_by_pdn(): destination sesssion for pdn(%d), ip_type(%d) is not found!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_PKT_BY_NETIF_ID_PKT_PACK_FAILED": {
+        "format": "[IPCORE] ipc_send_ul_pkt_by_netif_id(): failed to pack uplink packet : isGPD(%d), hdr(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_PKT_BY_NETIF_ID_SESSION_NOT_FOUND": {
+        "format": "[IPCORE] ipc_send_ul_pkt_by_netif_id(): destination sesssion for netif_id(%d), ip_type(%d) is not found!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_PKT_BY_NETIF_ID_NETIF_NOT_FOUND": {
+        "format": "[IPCORE] ipc_send_ul_pkt_by_netif_id(): source netif for netif_id(%d) is not found!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_PKT_PKT_PACK_FAILED": {
+        "format": "[IPCORE] ipc_send_dl_pkt(): failed to pack downlink packet : isGPD(%d), hdr(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_PKT_NETIF_NOT_FOUND": {
+        "format": "[IPCORE] ipc_send_dl_pkt(): destination network interface for ID(%d) is not found!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_PKT_NETIF_DID_NOT_FOUND": {
+        "format": "[IPCORE] ipc_send_dl_pkt_in_did(): destination network interface for ID(0x%x) is not found for did_head(0x%x), did_tail(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_PKT_NETIF_DID_ALLOC_DID_NG": {
+        "format": "[IPCORE] ipc_send_dl_pkt_in_did(): Allocating new DID FAILED: head_gpd(0x%x), tail_gpd(0x%x), netif_id(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_PKT_NETIF_GPD_SENDING_FAIL": {
+        "format": "[IPCORE] ipc_data_qbm_downlink_dequeue(): Sending failed: head_gpd(0x%x), tail_gpd(0x%x), netif_id(0x%x), ",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DPFM_DL_ALLOC_DID_NG": {
+        "format": "[IPCORE] ipc_on_process_dl_meta(): Allocating new DID FAILED, Drop DL meta: pdn(%d) channel_id(0x%x) net_type(%d) line(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_NTFY_BEGIN": {
+        "format": "[IPCORE] ipc_register_ntfy(): register notification callback : callback(0x%X), callback context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_NTFY_END": {
+        "format": "[IPCORE] ipc_register_ntfy(): gotten ntfy ID(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREG_NTFY_BEGIN": {
+        "format": "[IPCORE] ipc_deregister_ntfy(): uinstall notification callback : ntfy ID(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREG_NTFY_END": {
+        "format": "[IPCORE] ipc_deregister_ntfy(): uinstall notification callback complete : ntfy ID(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_ALLOCATE_NTFY_INVALID_PARAMS": {
+        "apiType": "index",
+        "format": "[IPCORE] ipc_allocate_ntfy(): failed with invalid parameters: callback(0x%X), callback context(0x%X)",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_TR_ALLOCATE_NTFY_UNAVAILABLE": {
+        "format": "[IPCORE] ipc_allocate_ntfy(): failed with all notification entries are busy now! : callback(0x%X), callback context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FREE_NTFY_INVALID_OBJECT": {
+        "format": "[IPCORE] ipc_free_ntfy(): it's an invalid object!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_ADD_NTFY_TO_LIST_INVALID_LIST": {
+        "format": "[IPCORE] ipc_add_ntfy_to_list(): invalid list(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REMOVE_NTFY_FROM_LIST_INVALID_LIST": {
+        "format": "[IPCORE] ipc_remove_ntfy_from_list(): invalid list(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NTFY_INIT_POOL_INFO": {
+        "format": "[IPCORE] ipc_ntfy_init(): IP CORE ntfy entry pool : addr(0x%X), count(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NTFY_INIT_LIST_INFO": {
+        "format": "[IPCORE] ipc_ntfy_init(): IP CORE ntfy list[%d] : addr(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NEW_NTFY_ADD_TO_LIST": {
+        "format": "[IPCORE] ipc_new_ntfy(): Add new ntfy with ID(%d) successfully for callback(0x%X) context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NEW_NTFY_NG": {
+        "format": "[IPCORE] ipc_new_ntfy(): Add new ntfy for callback(0x%X) context(0x%X) is failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEL_NTFY_WITH_INVALID_ID": {
+        "format": "[IPCORE] ipc_del_ntfy(): ntfy ID(%d) is invalid",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEL_NTFY_INFO": {
+        "format": "[IPCORE] ipc_del_ntfy(): entry with ntfy ID(%d) to delete : callback(0x%X), context(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEL_NTFY_REMOVE_FROM_LIST": {
+        "format": "[IPCORE] ipc_del_ntfy(): Remove entry with ntfy ID(%d) from list",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEL_NTFY_FREE_NTFY": {
+        "format": "[IPCORE] ipc_del_ntfy(): Free entry with ntfy ID(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEL_NTFY_NOT_FOUND": {
+        "apiType": "index",
+        "format": "[IPCORE] ipc_del_ntfy(): Entry with ntfy ID(%d) is not found/already invalid",
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+    {
+      "IPC_TR_DO_NTFY_INFO": {
+        "format": "[IPCORE] ipc_do_ntfy(): Execute callback(0x%X) context(0x%X) for ntfy ID(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DO_NTFY_NTFY_INFO": {
+        "format": "[IPCORE] ipc_do_ntfy(): ntfy type(%d), netif_id(0x%X), ip_id(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_LINK_UP_IND_START": {
+        "format": "[IPCORE] ipc_on_ipcore_link_up_ind(): Start of default LINK_UP_IND handling for netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_LINK_UP_IND_SEND_LINK_UP_RSP": {
+        "format": "[IPCORE] ipc_on_ipcore_link_up_ind(): Send LINK_UP_RSP ILM for netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_LINK_UP_IND_END": {
+        "format": "[IPCORE] ipc_on_ipcore_link_up_ind(): End of default LINK_UP_IND handling for netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_IP_UP_IND_START": {
+        "format": "[IPCORE] ipc_on_ipcore_ip_up_ind(): Start of default IP_UP_IND handling for netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_IP_UP_IND_SEND_IP_UP_RSP": {
+        "format": "[IPCORE] ipc_on_ipcore_ip_up_ind(): Send IP_UP_RSP ILM for netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_IP_UP_IND_END": {
+        "format": "[IPCORE] ipc_on_ipcore_ip_up_ind(): End of default IP_UP_IND handling for netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_UP_RSP_START": {
+        "format": "[IPCORE] ipc_on_ipcore_up_rsp(): Start of LINK/IP_UP_RSP handling for netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_UP_RSP_UPDATE_SESSION_STATE_TO_LINKUP": {
+        "format": "[IPCORE] ipc_on_ipcore_up_rsp(): Update session(0x%X) state to LINKUP",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_UP_RSP_SESSION_NOT_FOUND": {
+        "format": "[IPCORE] ipc_on_ipcore_up_rsp(): Session not found for netif(0x%X), netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_UP_RSP_NETIF_NOT_FOUND": {
+        "format": "[IPCORE] ipc_on_ipcore_up_rsp(): network interface not found for netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_UP_RSP_END": {
+        "format": "[IPCORE] ipc_on_ipcore_up_rsp(): End of LINK/IP_UP_RSP handling for netif_id(0x%X), ip_id(0x%X), ip_type(0x%X)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_LINK_UP_IND_HDLR_BEGIN": {
+        "format": "[IPCORE] ipc_register_link_up_ind_handler(): Register LINK_UP_IND ILM handler : Module (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_LINK_UP_IND_HDLR_END": {
+        "format": "[IPCORE] ipc_register_link_up_ind_handler(): Register LINK_UP_IND ILM handler complete : Module (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREG_LINK_UP_IND_HDLR_BEGIN": {
+        "format": "[IPCORE] ipc_deregister_link_up_ind_handler(): Uninstall registered LINK_UP_IND ILM handler",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREG_LINK_UP_IND_HDLR_END": {
+        "format": "[IPCORE] ipc_deregister_link_up_ind_handler(): Uninstall registered LINK_UP_IND ILM handler complete",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_IP_UP_IND_HDLR_BEGIN": {
+        "format": "[IPCORE] ipc_register_ip_up_handler(): Register IP_UP_IND ILM handler : Module (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SET_UL_THROTTLE_BEGIN": {
+        "format": "[IPCORE] ipc_set_ul_throttle(): Set UL throttle, old_state(%d), new_conf_enabled(%d), new_conf_activate(%d), new_conf_suspend(%d), features(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SET_UL_THROTTLE_END": {
+        "format": "[IPCORE] ipc_set_ul_throttle(): Set UL throttle, new_state(%d), new_conf_enabled(%d), new_conf_activate(%d), new_conf_suspend(%d), is_block_IMS(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_THROTTLE_SYSMSGSRV_CBK": {
+        "format": "[IPCORE] ipc_ul_throttle_sysmsgsvc_cbk(): CCCI_SYSMSG Set UL throttle, new_state(%d), new_conf_enabled(%d), new_conf_activate(%d), new_conf_suspend(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_IP_UP_IND_HDLR_END": {
+        "format": "[IPCORE] ipc_register_ip_up_handler(): Register IP_UP_IND ILM handler complete : Module (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREG_IP_UP_IND_HDLR_BEGIN": {
+        "format": "[IPCORE] ipc_deregister_ip_up_handler(): Uninstall registered IP_UP_IND ILM handler",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEREG_IP_UP_IND_HDLR_END": {
+        "format": "[IPCORE] ipc_deregister_ip_up_handler(): Uninstall registered IP_UP_IND ILM handler complete",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_LINK_UP_IND_HDLR_START": {
+        "format": "[IPCORE] ipc_update_link_up_ind_handler(): Update LINK_UP_IND ILM handler : Module (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATE_IP_UP_IND_HDLR_START": {
+        "format": "[IPCORE] ipc_update_ip_up_ind_handler(): Update IP_UP_IND ILM handler : Module (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_QUERY_INFO_START": {
+        "format": "[IPCORE] ipc_on_query_info(): Start to query information: src_mod_id(%d), local_para_ptr(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_QUERY_INFO_CNF": {
+        "format": "[IPCORE] ipc_on_query_info(): Send confirmation back to src_mod_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_QUERY_INFO_NO_MOD_ID_FOR_CFN": {
+        "format": "[IPCORE] ipc_on_query_info(): No source module ID to send confirmation back ! src_mod_id(%d) is MOD_NIL(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_QUERY_INFO_END": {
+        "format": "[IPCORE] ipc_on_query_info(): Query information handling is done",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_QUERY_NETIF_LIST_START": {
+        "format": "[IPCORE] ipc_query_netif_list(): Query netif list : netif_list_p(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_QUERY_NETIF_LIST_INFO": {
+        "format": "[IPCORE] ipc_query_netif_list(): Attached netif: idx(%d) netif_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_QUERY_NETIF_LIST_SUCCESS": {
+        "format": "[IPCORE] ipc_query_netif_list(): Netif list query success. Total attached netif count(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_QUERY_NETIF_LIST_FAILED": {
+        "format": "[IPCORE] ipc_query_netif_list(): No structure to store netif list status, failed !",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_CLARIFY_ZERO_LENGTH_PKT": {
+        "format": "[IPCORE] ipc_clarify_gpd(): Found zero length packet during clarification : curr_gpd(0x%x), length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_CLARIFY_ZERO_LENGTH_BD": {
+        "format": "[IPCORE] ipc_clarify_gpd(): Found packet with ALL ZERO-length BD list during clarification : curr_gpd(0x%x), gpd length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_CLARIFY_NONE_IP_PKT": {
+        "format": "[IPCORE] ipc_clarify_gpd(): Found non-IPv4/IPv6 packet, drop : curr_gpd(0x%x), gpd length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_CLARIFY_ZERO_LENGTH_PKT_DROP": {
+        "format": "[IPCORE] ipc_clarify_gpd(): Drop packet with invalid payload : curr_gpd(0x%x), gpd length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_CHANGE_GPD_TYPE_ZERO_LENGTH_BD": {
+        "format": "[IPCORE] ipc_gpd_change_gpd_type(): Found packet with ALL ZERO-length BD list during clarification : curr_gpd(0x%x), gpd length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_CHANGE_GPD_TYPE_ALLOC_GPD_NG": {
+        "format": "[IPCORE] ipc_gpd_change_gpd_type(): Allocate new GPD for different type is FAILED: gpd_type(%d), p_gpd(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GPD_COPY_BEGIN": {
+        "format": "[IPCORE] ipc_gpd_copy(): Start to copy GPD: dst_buffer(0x%x), dst_max_len(%d), dst_len_copied(0x%x), src_head_gpd(0x%x), src_tail_gpd(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GPD_COPY_END": {
+        "format": "[IPCORE] ipc_gpd_copy(): GPD copy result: retval(%d), dst_max_len(%d), *dst_len_copied(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GPD_UNITE_NULL_BD_LIST": {
+        "format": "[IPCORE] ipc_gpd_unite(): Null BD list (no BD have data) is found: uplink(%d), p_gpd_in(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GPD_UNITE_ZERO_LENGTH_GPD": {
+        "format": "[IPCORE] ipc_gpd_unite(): zero length GPD is found: uplink(%d), p_gpd_in(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GPD_UNITE_ALLOC_GPD_NG": {
+        "format": "[IPCORE] ipc_gpd_unite(): Allocate new GPD for uniting is FAILED: uplink(%d), p_gpd_in(0x%x), total_len(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GPD_UNITE_GPD_COPY_NG": {
+        "format": "[IPCORE] ipc_gpd_unite(): GPD copy is FAILED: uplink(%d), p_buff(0x%x), total_len(%d), copied_len(%d), p_gpd_in(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GPD_UNITE_FAILED": {
+        "format": "[IPCORE] ipc_gpd_unite(): GPD uniting is FAILED: uplink(%d), p_gpd_in(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SIT_TO_GPD_FAIL": {
+        "format": "[IPCORE] %s(): Allocate new GPD for packet_len(%d) is FAILED: gpd_type(%d), did(0x%x), curr_si_idx(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_TO_GPD_FAIL": {
+        "format": "[IPCORE] %s(): Allocate new GPD for packet_len(%d) is FAILED: gpd_type(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SI_UNITE_ALLOC_GPD_NG": {
+        "format": "[IPCORE] ipc_si_unite_to_gpd(): Allocate new GPD for uniting is FAILED: gpd_type(%d), did(0x%x), curr_si_idx(%d), pkt_len(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SHIFT_OFFSET_FAILED": {
+        "format": "[IPCORE] ipc_shift_gpd_content_ptr(): GPD is too short to get offset! gpd(0x%x) base_bd(0x%x) curr_bd(0x%x) curr_bd_len(%d) remaining_offset(%d) base_addr_p(0x%x) offset(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DID_SHIFT_OFFSET_FAILED": {
+        "format": "[IPCORE] ipc_shift_did_content_ptr(): DID/SIT is too short to get offset! did(0x%x) base_si_idx(%d) curr_si_idx(%d) curr_si_len(%d) remaining_offset(%d) base_addr_p(0x%x) offset(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_CONTENT_LENGTH_TOO_SHORT": {
+        "format": "[IPCORE] ipc_get_continuous_content(): GPD is too short to shift offset! gpd(0x%x) base_bd(0x%x) curr_bd(0x%x) base_addr_p(0x%x) offset(%d) length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_CONTENT_LENGTH_TOO_SHORT_TO_COPY": {
+        "format": "[IPCORE] ipc_get_continuous_content(): GPD is too short to copy specific continuous content! gpd(0x%x) base_bd(0x%x) curr_bd(0x%x) curr_bd_len(%d) remaining_length(%d) base_addr_p(0x%x) offset(%d) length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DID_CONTENT_LENGTH_TOO_SHORT": {
+        "format": "[IPCORE] ipc_get_continuous_content_did(): DID/SIT is too short to shift offset! did(0x%x) base_si_idx(%d) curr_si_idx(%d) base_addr_p(0x%x) offset(%d) length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DID_CONTENT_LENGTH_TOO_SHORT_TO_COPY": {
+        "format": "[IPCORE] ipc_get_continuous_content_did(): DID/SIT is too short to copy specific continuous content! did(0x%x) base_si_idx(%d) curr_si_idx(%d) curr_si_len(%d) remaining_length(%d) base_addr_p(0x%x) offset(%d) length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GET_INFO_FAILED": {
+        "format": "[IPCORE] ipc_get_packet_info(): fail_reason(%Mipc_packet_info_parser_error_code), ip_packet(0x%x), offset(%d), gpd(0x%x), curr_bd(0x%x), length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GET_INFO_SHIFT_FAILED": {
+        "format": "[IPCORE] ipc_get_packet_info(): fail_reason(%Mipc_packet_info_parser_error_code), gpd(0x%x) base_bd(0x%x) ip_packet(0x%x) offset(%d) next_header(0x%x) curr_bd(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GET_INFO_SPD_FAILED": {
+        "format": "[IPCORE] ipc_get_packet_info_spd(): fail_reason(%Mipc_packet_info_parser_error_code),ip_packet(0x%x), data_len(%d), packet_len(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GET_INFO_DID_FAILED": {
+        "format": "[IPCORE] ipc_get_packet_info_did(): fail_reason(%Mipc_packet_info_parser_error_code): ip_packet(0x%x), offset(%d), did(0x%x), base_si_idx(0x%x), length(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GET_INFO_DID_SHIFT_FAILED": {
+        "format": "[IPCORE] ipc_get_packet_info_did(): fail_reason(%Mipc_packet_info_parser_error_code) did(0x%x) base_si_idx(%d) ip_packet(0x%x) offset(%x) next_header(0x%x) curr_si_idx(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DO_FILTER_INVALID_GPD": {
+        "format": "[IPCORE] ipc_do_filter(): got an invalid GPD(0x%X)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DO_FILTER_ALLOC_GPD_NG": {
+        "format": "[IPCORE] ipc_do_filter(): Allocating new GPD for the SPD filtered out packet is FAILED: uplink(%d), QBM_TYPE_NET(%d), spd(0x%x), idx(%d), payload_len(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_META_DO_FILTER_ALLOC_GPD_NG": {
+        "format": "[IPCORE] ipc_meta_do_filter(): Allocating new GPD for the META filtered out packet is FAILED: uplink(%d), META(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_LAN_NETIF_BIND_INVALID_NETIF": {
+        "format": "[IPCORE] ipc_bind_lan_netif(): netifs not found for netif_1(0x%x)/id(0x%x) && netif_2(0x%x)/id(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_LAN_NETIF_UNBIND_INVALID_NETIF": {
+        "format": "[IPCORE] ipc_unbind_lan_netif(): netifs not found for netif_1(0x%x)/id(0x%x) && netif_2(0x%x)/id(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DID_GET_PKT_LENGTH_FAILED": {
+        "format": "[IPCORE] ipc_did_do_filter(): Get first 6B continuous content failed: ip_packet(0x%x), did(0x%x), curr_idx(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_COPY_GPD_TO_DID_ZERO_LENGTH_GPD": {
+        "format": "[IPCORE] ipc_copy_gpd_to_did(): Zero length GPD: curr_gpd(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_COPY_GPD_TO_DID_ZERO_ALLOC_PRB_NG": {
+        "format": "[IPCORE] ipc_copy_gpd_to_did(): Allocating new PRB FAILED: curr_gpd(0x%x), tail_gpd(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_COPY_GPD_TO_DID_GPD_LENGTH_NG": {
+        "format": "[IPCORE] ipc_copy_gpd_to_did(): GPD/BD length is not expected: curr_gpd(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FIND_PDN_BY_NETIF_SESSION_RLOCK_FAILED": {
+        "format": "[IPCORE] ipc_find_pdn_id_by_netif_id(): session RLOCK is FAILED: netif_id(0x%x), ip_type(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FIND_PDN_BY_NETIF_NETIF_RLOCK_FAILED": {
+        "format": "[IPCORE] ipc_find_pdn_id_by_netif_id(): netif RLOCK is FAILED: netif_id(0x%x), ip_type(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILTER_MATCHED_CLONED": {
+        "format": "[IPCORE] ipc_pkt_do_one_filter(): Filter matched cloned !!!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILTER_MATCHED_CLONED_DEFAULT_PATH": {
+        "format": "[IPCORE] ipc_did_do_filter(): Filter matched cloned case, it didn't set ignore bit, keep default data path",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_DROP_FOR_INVALID_NETIF": {
+        "format": "[IPCORE] ipc_on_process_dl_meta(): invalid netif reported by pn_match cur_idx(%d) pdn_id(0x%x) net_type(0x%x) channel_id(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_DROP_FOR_PN_NO_MATCH": {
+        "format": "[IPCORE] ipc_on_process_dl_meta(): packet drop !! pn_no_match cur_idx(%d) rb_id(%d) pdn_id(0x%x) net_type(0x%x) channel_id(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_PN_MATCH_SETTING": {
+        "format": "[IPCORE] ipc_update_pn_match_setting(): pn_match setting param pdn_sim_id(0x%x) nc_id(0x%x) ipv4(%d) ipv6(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UNKNOWN_ILM": {
+        "format": "[IPCORE] ipc_on_ilm(): unknown ilm ID (0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_PN_MATCH_CMD_UNKNOWN": {
+        "format": "[IPCORE] ipc_update_pn_match_setting(): unknown pnm_cmd(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UNBIND_DROP_UL_META": {
+        "format": "[IPCORE] ipc_data_drop_ul_meta_by_pdn(): PDN(0x%x) is unbinding! drop UL meta index(%d), meta_pdn_sim_id(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UL_IGNORE_NET_TYPE_DROP": {
+        "format": "[IPCORE] ipc_on_process_ul_meta_table(): NET_TYPE is IGNORE! drop UL meta index(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_FILL_DID_FROM_META_NG": {
+        "format": "[IPCORE] ipc_utils_fill_did_si_from_meta(): cur_si_idx(%d) exceeds maximum, is_adjust(%d), did_ptr(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SET_RQ_INFO_FAILED_PROTOCOL": {
+        "format": "[IPCORE] ipc_data_set_rq_info(): Set rq info failed : no protocol",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SET_RQ_INFO_FAILED_IP": {
+        "format": "[IPCORE] ipc_data_set_rq_info(): Set rq info failed : no IP address",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SET_RQ_INFO_FAILED_QFI": {
+        "format": "[IPCORE] ipc_data_set_rq_info(): Set rq info failed : no QFI",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_ALLOC_PEER_BUF_FAILED": {
+        "format": "[IPCORE] %s(): Allocate Peer buffer failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPCORE_SESSION_NOT_FOUND": {
+        "format": "[IPCORE] %s(): Session not found for pdn_id(0x%x))",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_TR_NO_PKT_INFO": {
+        "format": "[IPCORE] %s(): Cannot save RQ info since no packet info",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NO_PKT_INFO_DID": {
+        "format": "[IPCORE] ipc_did_do_filter(): ipc_get_packet_info_did failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_NR_RQI_IS_SET": {
+        "format": "[IPCORE] %s(): To save RQ Rule from meta(0x%x) HW filter result(0x%x) SW filter result(0x%x) meta->tcp_flag(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_INPUT_DID": {
+        "format": "[IPCORE] %s(): Invalid argument : p_did_head or p_did_tail is NULL",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_NETIF_ID": {
+        "format": "[IPCORE] %s(): Invalid netif_id : net_type(0x%x) ch_id(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RQ_LIST": {
+        "format": "[IPCORE] %s(): Invalid argument : p_rq_list is NULL",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RQ_LIST_INFO": {
+        "format": "[IPCORE] %s(): Invalid argument : p_rq_list is NULL or p_rq_info is NULL",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RQ_INFO_PKT_DES": {
+        "format": "[IPCORE] %s(): Invalid argument : p_rq_info is NULL or p_pkt_info is NULL",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_ARGS": {
+        "format": "[IPCORE] %s(): Invalid argument : input pointer was NULL",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_PDN_PROTO_IDX": {
+        "format": "[IPCORE] %s(): Invalid argument : invalid pdn (0x%x) proto_idx (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_DESCRIPTOR": {
+        "format": "[IPCORE] %s(): Invalid descriptor des_type (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_NETIF": {
+        "format": "[IPCORE] %s(): Invalid netif_id (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_DATA_PATH_DIR": {
+        "format": "[IPCORE] %s(): Invalid data_path_direct (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_FILTER_RULES": {
+        "format": "[IPCORE] %s(): p_rules was NULL",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_FILTER_CTXT": {
+        "format": "[IPCORE] %s(): p_ntfy_ctxt was NULL",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_FILTER_NTFY_TYPE": {
+        "format": "[IPCORE] %s(): Invalid filter ntfy_type (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },    
+    {
+      "IPC_TR_REGISTER_FILTER": {
+        "format": "[IPCORE] %s(): Register filter data_path_dir (0x%x) ntfy_type (0x%x) filter_id (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DEGISTER_FILTER": {
+        "format": "[IPCORE] %s(): Deregister filter filter_id (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_FOR_SPI": {
+        "format": "[IPCORE] ipc_validate_rules(): uplink(%d), valid_fields(0x%X), ip_type(%d) and features(0x%X) are invalid for spi!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_INVALID_RULES_FOR_CUST_FILTER": {
+        "format": "[IPCORE] ipc_validate_rules(): uplink(%d), valid_fields(0x%X), ip_type(%d) and features(0x%X) are invalid for cust filter!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_B4_DROP_GPD_ALLOC_NG": {
+        "format": "[IPCORE] %s():%d: GPD allocation failed in drop packet handler",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_B4_DROP_GPD_ALLOC_NG_CNT": {
+        "format": "[IPCORE] %s():%d: failed_cnt=%d: GPD allocation failed in drop packet handler",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_B4_DROP_INVALID_PARAM": {
+        "format": "[IPCORE] %s(): Invalid input parameter p_packet(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DROP_HDLR_NG_PROTO": {
+        "format": "[IPCORE] %s(): unknown protocol(0x%x) is not supported in drop packet handler",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_B4_DROP_SEND_UL_GPD": {
+        "format": "[IPCORE] %s(): detect TCP packet before drop, send response 1st GPD(0x%x) and 2nd GPD(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DROP_HDLR_UNKNOWN_IPTYPE": {
+        "format": "[IPCORE] %s(): unknown IP_TYPE is not supported in drop packet handler",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DROP_HDLR_PKT_INFO_NG": {
+        "format": "[IPCORE] %s(): packet info parsing NG in drop packet handler",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DOWNLINK_RA_PROXY_GPD": {
+        "format": "[IPCORE] %s(): pdn_id = 0x%x, copy RA did to GPD 0x%x",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DOWNLINK_RA_PROXY_GPD_ALLOC_NG": {
+        "format": "[IPCORE] %s(): pdn_id - 0x%x, copy RA did to GPD 0x%x",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_GET_PDN_ID_FAILED": {
+        "format": "[IPCORE] %s(): Get pdn by netif failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SEND_RA_GPD_NETIF": {
+        "format": "[IPCORE] %s(): Send RA GPD (0x%x) to RSRA proxy for netif_id (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SEND_RA_GPD_PUSH_BY_PDN": {
+        "format": "[IPCORE] %s(): push RA GPD (0x%x) for PDNID (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPF_DROP_HDR_INVALID_PARAM": {
+        "format": "[IPCORE] %s(): Invalid parameter p_packet(0x%x), len(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DID_DROP_HDR_INVALID_PARAM": {
+        "format": "[IPCORE] %s(): Invalid parameter p_head(0x%x), p_tail(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DROP_HDR_GPD_ALLOC_NG": {
+        "format": "[IPCORE] %s():%d: GPD allocation failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_B4_DROP_UDP_PREPARE_UL_GPD_NG": {
+        "format": "[IPCORE] %s(): rsp not sent, packet len [%d], exceed max gpd size",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_B4_DROP_UDP_PREPARE_UL_GPD": {
+        "format": "[IPCORE] %s(): ICMP port unreachable pkt prepared",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DL_META_B4_DROP_UDP_SEND_UL_GPD": {
+        "format": "[IPCORE] %s(): detect UDP packet before drop, send response 1st GPD(0x%x) and 2nd GPD(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_RESTORE_PDN_MAPPING": {
+        "format": "[IPCORE] %s(): restore pdn session (0x%x) with netif_id (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_DELETE_PDN_MAPPING": {
+        "format": "[IPCORE] %s(): delete pdn session (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_UPDATED_PDN_MAPPING": {
+        "format": "[IPCORE] %s(): updated pdn session (0x%x) with new pdn session (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SAVED_PDN_MAPPING": {
+        "format": "[IPCORE] %s(): saved pdn session (0x%x) with netif_id (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SAVED_PDN_MAPPING_FAILED": {
+        "format": "[IPCORE] %s(): ipc_session_save_netif_map failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_TR_UNEXPECTED_FILTER_CHK_RESULT": {
+        "format": "[IPCORE] %s():%d: pending dereg v4_cnt (0x%x) v6_cnt (0x%x), cannot add ip_type(0x%x) filter, reserved_cnt (0x%x)",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_TR_FILTER_HW_NUM_FULL": {
+        "format": "[IPCORE] %s(): hw filter entry was full (0x%x), pending dereg cnt (0x%x), cannot add ip_type(0x%x) filter, reserved_cnt (0x%x)",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_TR_FILTER_HW_NUM_CHK_FAILED": {
+        "format": "[IPCORE] %s(): hw filter entry check wrong full (0x%x), pending dereg v4_cnt (0x%x) v6_cnt (0x%x), cannot add ip_type(0x%x) filter, reserved_cnt (0x%x)",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_TR_BYPASS_HW_FILTER_SYNC": {
+        "format": "[IPCORE] %s(): bypass sync to HW filter with filter_id (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_SET_BYPASS_HW_FILTER_SYNC": {
+        "format": "[IPCORE] %s(): set bypass sync to HW filter with filter_id (0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_REG_FILTER_FAILED_HW_ENTRY_FULL": {
+        "format": "[IPCORE] %s(): hw filter entry was full",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_TR_IPF_DL_MODE_SWITCH": {
+        "format": "[IPCORE] %s(): IPF DL mode switch, request_is_hw_mode(%d), cur_is_hw_mode(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_TR_IPF_DL_MODE_SWITCH_NOTHING": {
+        "format": "[IPCORE] %s(): IPF DL mode switch, target mode is equal to current mode, do nothing!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GET_FILTER_SET_INVALID_PARAMS": {
+        "format": "[PFM] pfm_get_filter_set_by_id(): Invalid parameters: filter_set_list(0x%x), list_size(%d), filter_set_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GET_FILTER_SET_NEW_FILTER_SET": {
+        "format": "[PFM] pfm_get_filter_set_by_id(): New filter set: filter_set_list(0x%x), filter_set_id(%d), filter_set(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEL_FILTER_SET_BEGIN": {
+        "format": "[PFM] pfm_delete_filter_set(): Delete filter set: filter_set(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DISPATCH_REGISTER_CMD_NULL_PARAMS": {
+        "format": "[PFM] pfm_dispatch_register_cmd(): Invalid parameters: parameters should not be NULL!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DISPATCH_REGISTER_CMD_INVALID_PARAMS": {
+        "format": "[PFM] pfm_dispatch_register_cmd(): Invalid parameters: local_para_ptr(0x%x), filter_set_id(%d), filter_cnt(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DISPATCH_REGISTER_CMD_BEGIN": {
+        "format": "[PFM] pfm_dispatch_register_cmd(): Dispatch register cmd: filter_set_id(0x%x), filter_cnt(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_FILTER_BEGIN": {
+        "format": "[PFM] pfm_deregister_filter(): Deregister the filter: uplink(%d), filter_set(0x%x), filter_id(%d), ipc_filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_FILTER_WITH_INVALID_PARAMS": {
+        "format": "[PFM] pfm_deregister_filter(): Invalid parameters: uplink(%d), filter_set(0x%x), filter_id(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_FILTERS_NULL_PARAMS": {
+        "format": "[PFM] pfm_deregister_filters(): Invalid parameters: parameters should not be NULL!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_FILTERS_INVALID_PARAMS": {
+        "format": "[PFM] pfm_deregister_filters(): Invalid parameters: local_para_ptr(0x%x), filter_set_id(%d), filter_cnt(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_FILTERS_INFO": {
+        "format": "[PFM] pfm_deregister_filters(): Deregister some filters: uplink(%d), filter_set_id(%d), filter_cnt(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_FILTERS_FILTER_SET_NOT_FOUND": {
+        "format": "[PFM] pfm_deregister_filters(): uplink(%d), filter_set_id(%d) is not found!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_REG_FILTER_INVALID_PARAMS": {
+        "format": "[PFM] pfm_register_filter(): Invalid parameters: filter_set_id(%d), filter_id(%d), rules(0x%x)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_REG_FILTER_FAILED": {
+        "format": "[PFM] pfm_register_filter(): Register filter is failed!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_REG_FILTER_FILTER_SET_NOT_FOUND": {
+        "format": "[PFM] pfm_register_filter(): uplink(%d), filter_set_id(%d) is not found!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_REG_FILTER_CBK_BEGIN": {
+        "format": "[PFM] pfm_register_filter_cbk(): filter_set_id(%d), filter_id(%d), uplink(%d), rules(0x%x) callback_func(0x%x) callback_context(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_REG_FILTER_MSG_BEGIN": {
+
+        "format": "[PFM] pfm_register_filter_msg(): filter_set_id(%d), filter_id(%d), uplink(%d), rules(0x%x) callback_module(0x%x) callback_context(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_REG_FILTER_WITH_INFO_CBK_BEGIN": {
+        "format": "[PFM] pfm_register_filter_with_info_cbk(): filter_set_id(%d), filter_id(%d), uplink(%d), rules(0x%x) callback_func(0x%x) callback_context(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_REG_FILTER_WITH_INFO_MSG_BEGIN": {
+        "format": "[PFM] pfm_register_filter_with_info_msg(): filter_set_id(%d), filter_id(%d), uplink(%d), rules(0x%x) callback_module(0x%x) callback_context(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_FILTER_ZERO_LENGTH_GPD": {
+        "format": "[PFM] pfm_garbage_filter_deregister_callback(): Get zero length GPD(0x%x).",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_FILTER_NON_TCP_PACKET": {
+        "format": "[PFM] pfm_garbage_filter_deregister_callback(): Should get TCP packets only! GPD(0x%x), proto(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_FILTER_NON_IPV4_PACKET": {
+        "format": "[PFM] pfm_garbage_filter_deregister_callback(): Should get IPv4 packets only! GPD(0x%x)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_FILTER_REPLY_RST_FAIL": {
+        "format": "[PFM] pfm_garbage_filter_deregister_callback(): Replay TCP RST is failed! Can't alloc HIF_UL_TYPE_S GPD! dst_address(0x%x), src_port(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_FILTER_REPLY_RST": {
+        "format": "[PFM] pfm_garbage_filter_deregister_callback(): Replay TCP RST dst_address(0x%x), src_port(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_FILTER_REG_PARSER": {
+        "format": "[PFM] pfm_garbage_filter_register_parser(): Register filter rules: filter_id(%d), ip_type(%d), protocol(%d), dst_port(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_FILTER_WRONG_MAGIC_CODE": {
+        "format": "[PFM] %s(): Wrong magic code is detected when registering filter(%d)!",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_FILTER_INVALID_PARAMS": {
+        "format": "[PFM] pfm_garbage_filter_register_parser(): Invalid parameters is detected: ip_type(%d), protocol(%d)!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_FILTER_INVALID_FILTER_ID": {
+        "format": "[PFM] %s(): Invalid Filter ID!",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_RECEIVED_AP_STATUS": {
+        "format": "[PFM] pfm_ap_status_parser(): Received AP status (%s)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_RECEIVED_AP_INVALID_STATUS": {
+        "format": "[PFM] pfm_ap_status_parser(): Invalid AP status",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_RECEIVED_AP_SUSPEND_CMD": {
+        "format": "[PFM] pfm_ap_suspend_handler(): Received AP command (%u)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_FIN_ACK_FILTER_REQ": {
+        "format": "[PFM] pfm_ap_fin_ack_reduction_handler(): Send PFM Register ILM with set id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_ALLOCATE_FAILED": {
+        "format": "[PFM] pfm_ap_fin_ack_reduction_handler(): Allocate local para failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_SEND_ILM_FAILED": {
+        "format": "[PFM] pfm_ap_fin_ack_reduction_handler(): Send ILM failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_REGISTER_FILTER_ID_V4": {
+        "format": "[PFM] pfm_fin_ack_filter_register_parser(): Registered fin ack v4 filter with filter id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_REGISTER_FILTER_ID_V6": {
+        "format": "[PFM] pfm_fin_ack_filter_register_parser(): Registered fin ack v6 filter with filter id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_REGISTER_FILTER_FAILED": {
+        "format": "[PFM] pfm_fin_ack_filter_register_parser(): Registered filter failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_DEREGISTER_FILTER": {
+        "format": "[PFM] pfm_fin_ack_filter_deregister_callback(): Deregistered fin ack v4 filter id (%d), v6 filter id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_REPLY_RST": {
+        "format": "[PFM] pfm_fin_ack_filter_cbk(): Replay TCP RST GPD(0x%x), src_port(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_NO_ACTION_V4": {
+        "format": "[PFM] pfm_fin_ack_filter_register_parser(): Already registered v4 filter (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FIN_ACK_FILTER_NO_ACTION_V6": {
+        "format": "[PFM] pfm_fin_ack_filter_register_parser(): Already registered v6 filter (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_UDP_IGMP_FILTER_DROP": {
+        "format": "[PFM] %s(): drop packet with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_IGMP_FILTER_REGISTER_FILTER_ID_V4": {
+        "format": "[PFM] %s(): register v4 IGMP filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_IGMP_FILTER_REGISTER_FILTER_ID_V6": {
+        "format": "[PFM] %s(): register v6 IGMP filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_UDP_FILTER_REGISTER_FILTER_ID_V4": {
+        "format": "[PFM] %s(): register v4 UDP filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_UDP_FILTER_REGISTER_FILTER_ID_V6": {
+        "format": "[PFM] %s(): register v6 UDP filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FILTER_REGISTER_NO_ACTION": {
+        "format": "[PFM] %s(): already registered filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEGISTER_IGMP_FILTER": {
+        "format": "[PFM] %s(): deregistered IGMP filter with v4_filter_id (%d), v6_filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEGISTER_UDP_FILTER": {
+        "format": "[PFM] %s(): deregistered UDP filter with v4_filter_id (%d), v6_filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_FILTER_REGISTER_FAILED": {
+        "format": "[PFM] %s(): register filter failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_CMD_PARSER": {
+        "format": "[PFM] %s(): garbage string filter command parser, is_reg(%d), buf(0x%x), filter_cnt(%d), is_uplink(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_FLT_ID_EXIST": {
+        "format": "[PFM] %s(): garbage string filter_id is in-used, filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_NETIF_ALLOC_NG": {
+        "format": "[PFM] %s(): garbage string netif is exhausted, mask(0x%x), num(%d), netif_id(0x%x)",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_ALLOC_NG": {
+        "format": "[PFM] %s(): garbage string filter is exhausted, mask(0x%x), num(%d), filter_id(%d)",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_REG_PARSER": {
+        "format": "[PFM] %s(): garbage string filter register parser, filter_id(%d), netif_id(0x%x), filter_len(%d), mask_len(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_DEREG_CNT_NG": {
+        "format": "[PFM] %s(): garbage string filter deregister number is un-synced",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_DEREG_DEL": {
+        "format": "[PFM] %s(): garbage string filter set is going to delete, ipc_filter_id(%d)",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): garbage string filter ipc filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMP_PING_FILTER_ALLOCATE_FAILED": {
+        "format": "[PFM] %s(): Allocate local para failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMP_PING_FILTER_SEND_ILM_FAILED": {
+        "format": "[PFM] %s(): Send ILM failed",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV4_PING_REQ_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): ICMPV4 echo request filter ipc filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV4_PING_REPLY_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): ICMPV4 echo reply filter ipc filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_PING_REQ_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): ICMPV6 echo request filter ipc filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_PING_REPLY_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): ICMPV6 echo reply filter ipc filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMP_PING_FILTER_REGISTER_FAILED": {
+        "format": "[PFM] %s():%d: ICMP ping register filter failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_ICMP_PING_FILTER_NO_ACTION": {
+        "format": "[PFM] %s():%d: already registered filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEGISTER_ICMPV4_PING_FILTER": {
+        "format": "[PFM] %s(): deregistered ICMPV4 filters with echo_req_filter_id (%d), echo_reply_filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEGISTER_ICMPV6_PING_FILTER": {
+        "format": "[PFM] %s(): deregistered ICMPV6 filters with echo_req_filter_id (%d), echo_reply_filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DISABLE_ALL_PACKETS_FILTER_REGISTER_FILTER_ID": {
+        "format": "[PFM] %s(): UL disable-all-packets filter filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DISABLE_ALL_PACKETS_FILTER_REGISTER_FAILED": {
+        "format": "[PFM] %s(): UL disable-all-packets filter register failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_DISABLE_ALL_PACKETS_FILTER_NO_ACTION": {
+        "format": "[PFM] %s(): already registered filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DISABLE_ALL_PACKETS_FILTER_DROP": {
+        "format": "[PFM] %s(): drop packet with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_DISABLE_ALL_PACKETS_FILTER": {
+        "format": "[PFM] %s(): filter_id (%d) deregistered",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV4_PING_REQ_BYPASS_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): ICMPV4 echo request bypass filter ipc filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV4_PING_REQ_BYPASS_FILTER_REGISTER_FAILED": {
+        "format": "[PFM] %s(): ICMPV4 echo request bypass filter register failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_ICMPV4_PING_REQ_BYPASS_FILTER_NO_ACTION": {
+        "format": "[PFM] %s(): already registered filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV4_PING_REPLY_BYPASS_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): ICMPV4 echo reply bypass filter ipc filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV4_PING_REPLY_BYPASS_FILTER_REGISTER_FAILED": {
+        "format": "[PFM] %s(): ICMPV4 echo reply bypass filter register failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_ICMPV4_PING_REPLY_BYPASS_FILTER_NO_ACTION": {
+        "format": "[PFM] %s(): already registered filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_PING_REQ_BYPASS_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): ICMPV6 echo request bypass filter ipc filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_PING_REQ_BYPASS_FILTER_REGISTER_FAILED": {
+        "format": "[PFM] %s(): ICMPV6 echo request bypass filter register failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_PING_REQ_BYPASS_FILTER_NO_ACTION": {
+        "format": "[PFM] %s(): already registered filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_PING_REPLY_BYPASS_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): ICMPV6 echo reply bypass filter ipc filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_PING_REPLY_BYPASS_FILTER_REGISTER_FAILED": {
+        "format": "[PFM] %s(): ICMPV6 echo reply bypass filter register failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_PING_REPLY_BYPASS_FILTER_NO_ACTION": {
+        "format": "[PFM] %s(): already registered filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_NON_PING_FILTER_REGISTER_FILTER_ID": {
+        "format": "[PFM] %s(): Non-Ping packets wild card filter ipc filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_NON_PING_FILTER_REGISTER_FAILED": {
+        "format": "[PFM] %s(): Non-Ping packets wild card filter register failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_NON_PING_FILTER_NO_ACTION": {
+        "format": "[PFM] %s(): already registered filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_RS_BYPASS_FILTER_IPC_FILTER_ID": {
+        "format": "[PFM] %s(): ICMPV6 rs bypass filter ipc filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_RS_BYPASS_FILTER_REGISTER_FAILED": {
+        "format": "[PFM] %s(): ICMPV6 rs bypass filter register failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_ICMPV6_RS_BYPASS_FILTER_NO_ACTION": {
+        "format": "[PFM] %s(): already registered filter with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_ICMP_PING_WHITELIST_FILTER_DROP": {
+        "format": "[PFM] %s(): drop packet with filter_id (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_ICMPV4_PING_REQ_BYPASS_FILTER": {
+        "format": "[PFM] %s(): filter_id (%d) deregistered",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_ICMPV4_PING_REPLY_BYPASS_FILTER": {
+        "format": "[PFM] %s(): filter_id (%d) deregistered",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_ICMPV6_PING_REQ_BYPASS_FILTER": {
+        "format": "[PFM] %s(): filter_id (%d) deregistered",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_ICMPV6_PING_REPLY_BYPASS_FILTER": {
+        "format": "[PFM] %s(): filter_id (%d) deregistered",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_ICMPV6_RS_BYPASS_FILTER": {
+        "format": "[PFM] %s(): filter_id (%d) deregistered",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_NON_PING_FILTER": {
+        "format": "[PFM] %s(): filter_id (%d) deregistered",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_UL_DISABLE_ALL_PACKETS_FILTER_ALLOCATE_FAILED": {
+        "format": "[PFM] %s(): UL disable-all-packets filter allocate failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_UL_DISABLE_ALL_PACKETS_FILTER_SEND_ILM_FAILED": {
+        "format": "[PFM] %s(): UL disable-all-packets filter send ILM failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_UL_ICMP_PING_WHITELIST_FILTER_ALLOCATE_FAILED": {
+        "format": "[PFM] %s(): UL icmp ping whitelist filter send ILM failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_UL_ICMP_PING_WHITELIST_FILTER_SEND_ILM_FAILED": {
+        "format": "[PFM] %s(): UL icmp ping whitelist filter send ILM failed",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_TR_DATA_USAGE_INFO": {
+        "format": "[IPCORE] %s(): PDN(%u), Uplink Bytes(%u), Downlink Bytes(%u), Uplink Packets(%u), Downlink Packets(%u)",
+        "traceClass": "TRACE_DEBUG"
+      }
+    },
+    {
+      "IPC_TR_DATA_USAGE_RESET": {
+        "format": "[IPCORE] %s(): Reset Data usage for pdn_id(%u)",
+        "traceClass": "TRACE_DEBUG"
+      }
+    },
+    {
+      "IPC_TR_INVALID_PDN_ID": {
+        "format": "[IPCORE] %s(): Invalid pdn_id",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "PFM_TR_REG_CBK_WAKE_TYPE_PKT": {
+        "format": "[PFM] %s(): Register callback(0x%x) for wake type packet",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_DEREG_CBK_WAKE_TYPE_PKT": {
+        "format": "[PFM] %s(): De-register callback of wake type packet",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_PKT_FW": {
+        "format": "[PFM] %s(): Matched Packet forwared in callback(0x%x), pkt(0x%x), len(%d), pfm_str_filter_id(%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "PFM_TR_GARBAGE_STR_FILTER_CBK_NULL": {
+        "format": "[PFM] %s(): No callback registered for wake type packet",
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+    {
+      "IPC_RECEIVED_UL_META_INFO": {
+        "format": "[IPCORE] Received ul meta meta_idx (%d) match_idx (%d), match_result (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_FORCE_SW_PATH": {
+        "format": "[IPCORE] %s(): switch to SW path (%d) with proto_idx (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_RESET_HW_FILTER": {
+        "format": "[IPCORE] %s(): reset hw filter entry",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPC_DATA_PATH_STATUS": {
+        "format": "[IPCORE] %s(): current is_sw_path (%d)",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPF_IT_REGISTERED_FILTER_CASE": {
+        "format": "[IPF_IT] Registered filter for case = %d",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPF_IT_GENERATED_DATA_CASE": {
+        "format": "[IPF_IT] Generate data for case = %d",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPF_IT_TIMEOUT_CASE": {
+        "format": "[IPF_IT] Time out : check case %d",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPF_IT_PASS_CASE": {
+        "format": "[IPF_IT] it_case %2d PASS",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPF_IT_RECEIVED_RAW_DATA": {
+        "format": "[IPF_IT] invoke transfer raw data %d packets to cipher HW data",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPF_IT_RECEIVED_CBK_DATA": {
+        "format": "[IPF_IT] Received cbk data for case = %d",
+        "traceClass": "TRACE_INFO"
+      }
+    },
+    {
+      "IPF_IT_ALL_PASS": {
+        "format": "[IPF_IT] ALL Test Case PASS ~",
+        "traceClass": "TRACE_INFO"
+      }
+    }
+  ],
+  "traceFamily": "PS",
+  "userModule": "MOD_IPCORE"
+}
diff --git a/mcu/middleware/hif/ipcore/include/ipc_ut.h b/mcu/middleware/hif/ipcore/include/ipc_ut.h
new file mode 100644
index 0000000..5ed6577
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_ut.h
@@ -0,0 +1,211 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_ut.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IPCORE unit test defines and helper macros.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_UT_H
+#define __INC_IPC_UT_H
+
+#include "upcm.h"
+#include "ipc_defs.h"
+
+typedef enum {
+    IPC_UT_NO_ERROR = 0,
+    IPC_UT_SESSION_BIND_NEW_SESSION_FAIL,
+    IPC_UT_SESSION_DEACTIVATE_NO_SESSION_FOUND,
+    IPC_UT_REGISTER_FILTER_VALIDATE_FAIL,
+    IPC_UT_REGISTER_FILTER_NG,
+    IPC_UT_DEREGISTER_FILTER_WITH_INVALID_ID,
+    IPC_UT_DEREGISTER_FILTER_NOT_FOUND,
+    IPC_UT_NEW_NTFY_NG,
+    IPC_UT_DEL_NTFY_WITH_INVALID_ID,
+    IPC_UT_DEL_NTFY_NOT_FOUND,
+    IPC_UT_DL_PKT_NETIF_NOT_FOUND,
+} ipc_ut_error_e;
+
+#ifdef ATEST_SYS_IPCORE
+    extern ipc_ut_error_e ipc_ut_error_g;
+    extern kal_bool ipc_ut_dpfm_is_activated_g;
+
+    #define ipc_ut_set_error(_ut_error)     ipc_ut_error_g = (_ut_error)
+    #define ipc_ut_get_error()              ipc_ut_error_g
+    #define IPC_UT_ASSERT(_cond, _ut_error) if (!(_cond)) ipc_ut_set_error(_ut_error)
+
+    void ipc_ut_on_ul_packet_filtered_req(void *req_ptr);
+    void ipc_ut_on_dl_packet_filtered_req(void *req_ptr);
+    void ipc_ut_on_ul_packet_filtered_with_info_req(void *req_ptr);
+    void ipc_ut_on_dl_packet_filtered_with_info_req(void *req_ptr);
+    kal_bool ipc_ut_msg_send6(module_type _src_mod_id, module_type _dest_mod_id, sap_type _sap_id, msg_type _msg_id, local_para_struct *_local_para_ptr, peer_buff_struct *_peer_buff_ptr);
+    void ipc_ut_rcv_ul_sdu(ip_type_e ip_type, kal_uint32 pdn_id, qbm_gpd *p_head, qbm_gpd *p_tail, kal_uint8 proto_idx);
+    void ipc_ut_rcv_ul_sdu_by_ebi(kal_uint32 ebi, qbm_gpd *p_head, qbm_gpd *p_tail, kal_uint8 proto_idx);
+    void ipc_ut_reg_cbk_notify_tick_source(upcm_nofify_lte_tick_f pf_notify);
+    void ipc_ut_reg_cbk_dlvr_dl_sdu(upcm_dlvr_dl_sdu_93_f pf_dlvr_sdu);
+    void ipc_ut_rcv_ul_sdu_meta(kal_uint32 start_idx, kal_uint32 end_idx, LHIF_QUEUE_TYPE q_type);
+    kal_bool ipc_ut_query_meta_table(kal_uint32 **base_addr, kal_uint16 *size, LHIF_QUEUE_TYPE queue_type);
+    kal_bool ipc_ut_dpfm_check_route(kal_bool uplink, kal_uint8 ip_type, ipc_pkt_des_t *pkt_des, kal_uint32 in_netif_id, kal_uint32 *out_netif_id);
+    kal_bool ipc_ut_dpfm_is_activated(void);
+
+    /* Gen95 Wrapper Function */
+    kal_int32 ipc_ut_ipf_query_filter_id_by_index(kal_uint32 ipf_index);
+    void ipc_ut_query_ipf_meta_info(void** base, kal_uint16* entry_num, kal_uint32 ipf_meta_q_type);
+    void ipc_ut_ipf_pn_match_setting(kal_uint8 pdn_sim_id, kal_uint16 nc_id, kal_uint8 ipv4, kal_uint8 ipv6);
+    void ipc_ut_release_ipf_meta_entry(kal_uint16 rel_num, kal_uint32 ipf_meta_q_type);
+    kal_bool ipc_ut_ipf_take_filter_tlb(void** buff_base, kal_uint32* max_entry_num);
+    kal_bool ipc_ut_ipf_submit_filter_tlb(kal_uint32 filter_num, kal_uint32 v6_unknow_pro_ck);
+    void ipc_ut_free_ipf_meta_buf(void* meta, kal_uint32 len);
+    kal_bool ipc_ut_on_ilm(ilm_struct *p_ilm);
+    extern void ipc_fragment_test();
+
+#else /* not defined(ATEST_SYS_IPCORE) */
+    #define ipc_ut_set_error(_ut_error)
+    #define ipc_ut_get_error()              IPC_UT_NO_ERROR
+    #define IPC_UT_ASSERT(_cond, _ut_error) IPC_ASSERT(_cond)
+#endif /* ATEST_SYS_IPCORE */
+
+#endif /* __INC_IPC_UT_H */
diff --git a/mcu/middleware/hif/ipcore/include/ipc_utils.h b/mcu/middleware/hif/ipcore/include/ipc_utils.h
new file mode 100644
index 0000000..748bdf5
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/ipc_utils.h
@@ -0,0 +1,378 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_utils.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IPCore internal utilities.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_IPC_UTILS_H
+#define __INC_IPC_UTILS_H
+
+#include "kal_public_api.h"
+#include "ipc_enums.h"
+#include "ipc_data.h"
+#include "tst_msgid.h"
+
+#define MSG_IPC_DL_RAW_DATA         (MSG_ID_DHL_UPCM_IMS_DL_RAW_DATA)
+#define MSG_IPC_UL_RAW_DATA         (MSG_ID_DHL_UPCM_IMS_UL_RAW_DATA)
+#define IPC_DL_PKT_DUMP(buf_p, len) ipc_utils_pkt_dump_buf(MSG_IPC_DL_RAW_DATA, MOD_IPCORE, buf_p, len)
+#define IPC_UL_PKT_DUMP(buf_p, len) ipc_utils_pkt_dump_buf(MSG_IPC_UL_RAW_DATA, MOD_IPCORE, buf_p, len)
+
+/**
+ * Internal API to set GPD data length.
+ *
+ * @param   gpd [IN] GPD to set data length.
+ * @param   datalen [IN] data length to set.
+ * @param   payload_ptr [OUT] Pointer of payload to return.
+ *
+ * @return  KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+void ipc_utils_set_gpd_datalen(void *p_gpd, kal_uint32 datalen, void **p_payload);
+
+/**
+ * Internal API to get GPD data pointer.
+ *
+ * @param   gpd [IN] GPD to set data length.
+ * @param   payload_ptr [OUT] Pointer of payload to return.
+ *
+ * @return  KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+kal_bool ipc_utils_get_gpd_dataptr(void *p_gpd, void **p_payload);
+
+/**
+ * Internal API to copy buffers in the GPD list to the buffer prepared by caller.
+ *
+ * @param   dst_buffer [OUT] Destination buffer to copy to, which is prepared by caller.
+ * @param   dst_max_len [IN] Size of the destination buffer prepared by caller in bytes.
+ * @param   dst_len_copied [OUT] Number of bytes copied to the destination buffer.
+ * @param   src_head_gpd [IN] Head of the GPD list with source buffers to copy from.
+ * @param   src_tail_gpd [IN] Tail of the GPD list with source buffers to copy from.
+ *
+ * @return  KAL_TRUE if succeeded, KAL_FALSE otherwise.
+ */
+kal_bool ipc_utils_gpd_copy(kal_uint8 *p_dst_buf,
+                            kal_uint32 dst_max_len,
+                            kal_uint32 *p_dst_len_copied,
+                            qbm_gpd *p_head_gpd,
+                            qbm_gpd *p_tail_gpd);
+
+/**
+ * Internal API to classify IPv4v6 GPD list into separated IPv4 & IPv6 GPD lists.
+ *
+ * @param   head_gpd [IN] Head of the source IPv4v6 GPD list.
+ * @param   tail_gpd [IN] Tail of the source IPv4v6 GPD list.
+ * @param   ipv4_head_gpd [OUT] Head of the classified IPv4 GPD list.
+ * @param   ipv4_tail_gpd [OUT] Tail of the classified IPv4 GPD list.
+ * @param   ipv6_head_gpd [OUT] Head of the classified IPv6 GPD list.
+ * @param   ipv6_tail_gpd [OUT] Tail of the classified IPv6 GPD list.
+ */
+void ipc_utils_clarify_gpd(qbm_gpd *p_head_gpd,
+                           qbm_gpd *p_tail_gpd,
+                           qbm_gpd **p_ipv4_head_gpd,
+                           qbm_gpd **p_ipv4_tail_gpd,
+                           qbm_gpd **p_ipv6_head_gpd,
+                           qbm_gpd **p_ipv6_tail_gpd);
+
+/**
+ * Internal API to get hif type of the netif from the netif_id
+ *
+ * @param   netif_id [IN] The id of the netif.
+ *
+ * @return  the hif type of the netif.
+ */
+ipc_si_hif_type_e ipc_utils_get_hif_type_by_netif_id(kal_uint32 netif_id);
+
+/**
+ * Internal API to set hif type of all SI entries of the packet.
+ *
+ * @param   did [IN] The DID contained the packet.
+ * @param   hif_type [IN] The hif type to set.
+ * @param   p_curr_si_idx [IN|OUT] The current SI idx.
+ */
+void ipc_utils_pkt_set_si_hif_type(upcm_did *p_did, ipc_si_hif_type_e hif_type, kal_uint32 *p_curr_si_idx);
+
+/**
+ * Internal API to copy GPD list to DID.
+ *
+ * @param   src_head_gpd [IN] The head of the source GPD list.
+ * @param   src_tail_gpd [IN] The tail of the source GPD list.
+ * @param   did [IN] The destination DID.
+ * @param   hif_type [IN] The hif type to set.
+ */
+kal_bool ipc_utils_cpy_gpd_to_did(qbm_gpd *p_head_gpd, qbm_gpd *p_tail_gpd, upcm_did *p_did, ipc_si_hif_type_e hif_type);
+
+/**
+ * Internal API to set hif type of all SI entries of the packet as IGR and free the data buffer.
+ *
+ * @param   did [IN] The DID contained the packet.
+ * @param   p_curr_si_idx [IN|OUT] The current SI idx.
+ */
+void ipc_utils_pkt_free_si_data_buf(upcm_did *p_did, kal_uint32 *p_curr_si_idx);
+
+/**
+ * Internal API to fill DID/SI descriptor based on the META descriptor.
+ *
+ * @param   dst_did [IN] The destination DID.
+ * @param   p_si_idx [IN|OUT] The pointer of the current SI index.
+ * @param   src_meta [IN] The source META.
+ * @param   hif_type [IN] The hif type of the destination netif.
+ */
+kal_bool ipc_utils_fill_did_si_from_meta(kal_bool is_need_adjust,
+                                         upcm_did *p_dst_did,
+                                         kal_uint32 *p_si_idx,
+                                         ipc_meta_info_des *p_pkt_info,
+                                         ipc_si_hif_type_e hif_type);
+
+/**
+ * Internal API to dump raw packet content with continuous buffer.
+ *
+ * @param   msg_id [IN] DHL message ID.
+ * @param   src_mod [IN] Module ID of message source.
+ * @param   buf_p [IN] The buffer address of packet.
+ * @param   pkt_len [IN] The length of packet to be dumped.
+ */
+void ipc_utils_pkt_dump_buf(msg_type msg_id,
+                            module_type src_mod,
+                            kal_uint8 *p_buf,
+                            kal_uint32 pkt_len);
+
+/**
+ * Internal API to dump all raw packets' content within a GPD list.
+ * Note that it can only support GPD type with continuous buffer.
+ *
+ * @param   first_gpd [IN] The head of the GPD list.
+ * @param   last_gpd [IN] The tail of the GPD list.
+ * @param   uplink [IN] The packets are uplink or downlink.
+ */
+void ipc_utils_pkt_dump_buff_gpd_list(qbm_gpd *p_head_gpd, qbm_gpd *p_tail_gpd, kal_bool is_uplink);
+
+/**
+ * Internal API to dump the packet's raw content within a DID.
+ * @param   did [IN] DID descriptor.
+ * @param   p_curr_si_idx [IN|OUT] The current SI index.
+ */
+void ipc_utils_pkt_dump_did_one_pkt(upcm_did *p_did, kal_uint32 *p_curr_si_idx);
+
+/**
+ * Internal API to dump all packets' raw content within a DID list.
+ * @param   did_head [IN] DID descriptor head.
+ * @param   did_tail [IN] DID descriptor tail.
+ * @param   hif_type [IN] Specified hif_type to be dumped within a DID list.
+ */
+void ipc_utils_pkt_dump_did(upcm_did *p_did_head, upcm_did *p_did_tail, ipc_si_hif_type_e hif_type);
+
+/**
+ * Internal API to dump N bytes of packets' raw content.
+ * @param   p_data [IN] packet start point. (Data buffer should be continuous buffer)
+ * @param   bytes [IN] dump length.
+ */
+void ipc_utils_dump_data(void *p_data, kal_uint32 bytes);
+
+/**
+ * delete given entry of GPD list
+ *
+ * @param   p_first_gpd  first GPD
+ * @param   p_last_gpd   last GPD
+ * @param   p_curr_gpd   current GPD
+ * @param   p_prev_gpd   previous GPD
+ * @param   p_next_gpd   next GPD
+ */
+void ipc_utils_gpd_list_del_entry(qbm_gpd **p_first_gpd,
+                                  qbm_gpd **p_last_gpd,
+                                  qbm_gpd **p_curr_gpd,
+                                  qbm_gpd **p_prev_gpd,
+                                  qbm_gpd **p_next_gpd);
+
+/**
+ * united GPD as GPD only, it doesn't has BD
+ *
+ * @param   is_uplink  uplink or downlink
+ * @param   p_gpd_in   input GPD
+ * @param   pp_gpd_out output GPD
+ */
+void ipc_utils_unite_gpd(kal_bool is_uplink, qbm_gpd *p_gpd_in, qbm_gpd **pp_gpd_out);
+
+/**
+ * transfer SIT to GPD format
+ *
+ * @param   type        GPD type
+ * @param   p_did       input did
+ * @param   curr_si_idx current sit index
+ * @param   pkt_len     packet length
+ * @param   pp_gpd_out  output GPD
+ */
+kal_bool ipc_utils_sit_to_gpd(qbm_type type,
+                              upcm_did *p_did,
+                              kal_uint32 curr_si_idx,
+                              kal_uint32 pkt_len,
+                              qbm_gpd **pp_gpd_out);
+
+/**
+ * calculate TCP checksum
+ *
+ * @param   is_ipv4    ipv4 or ipv6
+ * @param   src_addr   source address
+ * @param   dst_addr   destination address
+ * @param   tcp_header tcp header pointer
+ * @param   tcp_len    tcp length
+ */
+kal_uint16 ipc_utils_calc_tcp_checksum(kal_bool is_ipv4,
+                                       kal_uint8 *src_addr,
+                                       kal_uint8 *dst_addr,
+                                       kal_uint8 *tcp_header,
+                                       kal_uint32 tcp_len);
+
+/**
+ * calculate UDP checksum
+ *
+ * @param   is_ipv4    ipv4 or ipv6
+ * @param   src_addr   source address
+ * @param   dst_addr   destination address
+ * @param   udp_header udp header pointer
+ * @param   udp_len    udp length
+ */
+kal_uint16 ipc_utils_calc_udp_checksum(kal_bool is_ipv4,
+                                       kal_uint8 *src_addr,
+                                       kal_uint8 *dst_addr,
+                                       kal_uint8 *udp_header,
+                                       kal_uint32 udp_len);
+
+/**
+ * calculate IPv4 checksum
+ *
+ * @param   ip_header IP header pointer
+ */
+kal_uint16 ipc_utils_calc_ipv4_checksum(kal_uint8 *ip_header);
+
+
+/**
+ * calculate ICMP checksum
+ *
+ * @param   icmp_header ICMP header pointer
+ * @param   len			legth over which checksum need to calculate
+ */
+kal_uint16 ipc_utils_calc_icmp_checksum(kal_uint8 *icmp_header, kal_uint32 len);
+
+
+#endif /* __INC_IPC_UTILS_H */
diff --git a/mcu/middleware/hif/ipcore/include/pfm_defs.h b/mcu/middleware/hif/ipcore/include/pfm_defs.h
new file mode 100644
index 0000000..f460868
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/pfm_defs.h
@@ -0,0 +1,222 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2014
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   pfm_defs.h
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   This file provides the filter set index for different features.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_PFM_DEFS_H
+#define __INC_PFM_DEFS_H
+
+#include "kal_public_api.h"
+#include "pfm_struct.h"
+
+/*------------------------------------------------------------------------------
+ * Auto produced register parser function prototypes. DO NOT MODIFY!!
+ *----------------------------------------------------------------------------*/
+/* pfm_xxx_register_parser function prototype */
+#undef PFM_FILTER_SET_FEATURE_NAME
+#undef PFM_FILTER_SET_PREFIX
+#define PFM_FILTER_SET_FEATURE_NAME(_name) 
+#define PFM_FILTER_SET_PREFIX(_prefix) void pfm_ ## _prefix ## _register_parser(void *, kal_uint32, kal_bool);
+#include "pfm_config.h"
+
+/* pfm_xxx_deregister_callback function prototype */
+#undef PFM_FILTER_SET_FEATURE_NAME
+#undef PFM_FILTER_SET_PREFIX
+#define PFM_FILTER_SET_FEATURE_NAME(_name) 
+#define PFM_FILTER_SET_PREFIX(_prefix) void pfm_ ## _prefix ## _deregister_callback(void *, kal_uint32, kal_bool);
+#include "pfm_config.h"
+
+/*------------------------------------------------------------------------------
+ * Configuration.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Constant definition.
+ *----------------------------------------------------------------------------*/
+#define PFM_ASSERT ASSERT               /* To completely bypass the overhead of ASSERT(), we could define PFM_ASSERT(...) to nothing. */
+#define PFM_DEL_OBJECT_SLEEP_TICKS      KAL_TICKS_10_MSEC
+#define PFM_W_LOCK_OBJECT_SLEEP_TICKS   1
+#define PFM_FILTER_SET_MAX_SIZE         256
+#define PFM_IPC_REGISTER_FILTER_FAIL    -1
+#define PFM_FILTER_STRUCT_MAGIC_CODE    168
+#define PFM_MATCHED_PACKET_DUMP_SIZE     40
+#define PFM_LOCK_NAME                   "PFM_LOCK"
+
+typedef enum {
+    PFM_STATE_RESUME,
+    PFM_STATE_SUSPEND,
+    PFM_STATE_INVALID
+} pfm_pcie_state_e;
+/*------------------------------------------------------------------------------
+ * Internal data structure defintion.
+ *----------------------------------------------------------------------------*/
+#define PFM_DECLARE_OBJECT \
+                kal_int32       ref_count; \
+                kal_int32       reader_cnt; \
+                kal_int32       writer_cnt;
+
+typedef struct _pfm_internal_filter_set_t {
+    PFM_DECLARE_OBJECT
+
+    kal_uint32  filter_set_id;
+    kal_int32   filter_cnt;
+    kal_int32   filters[PFM_FILTER_SET_MAX_SIZE];
+} pfm_internal_filter_set_t;
+
+typedef enum emPfmApStatus {
+    PFM_AP_STATUS_SUSPEND = 0x00000000,
+    PFM_AP_STATUS_WAKE_UP = 0x00000001
+} emPfmApStatus;
+
+#define PFM_AP_CMD_NONE              (0)
+#define PFM_AP_CMD_FIN_ACK_REDUCTION (0x01 << 0)
+
+typedef struct pfmApStatusInd {
+    LOCAL_PARA_HDR
+    emPfmApStatus em_ap_status;
+    kal_uint32 bm_cmd;
+} pfmApStatusInd;
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Internal function prototype.
+ *----------------------------------------------------------------------------*/
+pfm_internal_filter_set_t* pfm_get_filter_set_list(kal_bool is_uplink);
+
+void pfm_dispatch_cmd(ilm_struct *ilm, kal_bool is_register);
+
+void pfm_deregister_filters(local_para_struct *local_para_ptr);
+
+void pfm_delete_filter_set(pfm_internal_filter_set_t *filter_set);
+
+void pfm_deregister_filter(kal_bool uplink, pfm_internal_filter_set_t *filter_set, kal_int32 filter_id);
+
+kal_bool pfm_register_filter_cbk(kal_uint32              filter_set_id,
+                                 kal_int32               filter_id,
+                                 kal_bool                uplink,
+                                 ipc_filter_rules_t     *rules,
+                                 ipc_filter_callback_t   callback_func,
+                                 void                   *callback_context);
+
+kal_bool pfm_register_filter_msg(kal_uint32           filter_set_id,
+                                 kal_int32            filter_id,
+                                 kal_bool             uplink,
+                                 ipc_filter_rules_t  *rules,
+                                 module_type          callback_module,
+                                 void                *callback_context);
+
+kal_bool pfm_register_filter_with_info_cbk(kal_uint32                        filter_set_id,
+                                           kal_int32                         filter_id,
+                                           kal_bool                          uplink,
+                                           ipc_filter_rules_t               *rules,
+                                           ipc_filter_with_info_callback_t   callback_func,
+                                           void                             *callback_context);
+
+kal_bool pfm_register_filter_with_info_msg(kal_uint32           filter_set_id,
+                                           kal_int32            filter_id,
+                                           kal_bool             uplink,
+                                           ipc_filter_rules_t  *rules,
+                                           module_type          callback_module,
+                                           void                *callback_context);
+
+void pfm_matched_packet_trace(kal_int16 ebi, kal_uint8 *p_data, kal_uint32 bytes);
+
+pfm_internal_filter_set_t *pfm_get_filter_set_by_id(pfm_internal_filter_set_t  *filter_set_list,
+                                                    kal_uint32                  list_size,
+                                                    kal_uint32                  filter_set_id);
+
+#endif /* __INC_PFM_DEFS_H */
diff --git a/mcu/middleware/hif/ipcore/include/pfm_object.h b/mcu/middleware/hif/ipcore/include/pfm_object.h
new file mode 100644
index 0000000..9beb619
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/include/pfm_object.h
@@ -0,0 +1,215 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2014
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   PFM_object.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   Helper for object management and synchronization.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_PFM_OBJECT_H
+#define __INC_PFM_OBJECT_H
+
+#include "kal_public_api.h"
+
+#include "pfm_defs.h"
+
+struct _pfm_object_template;
+extern kal_spinlockid pfm_spinlock_g;
+static INLINE kal_bool pfm_is_object_valid(struct _pfm_object_template *object);
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+#define PFM_SPIN_LOCK(_lock)    kal_take_spinlock(_lock, KAL_INFINITE_WAIT)
+#define PFM_SPIN_UNLOCK(_lock)  kal_give_spinlock(_lock)
+
+#define PFM_IS_VALID_OBJECT_WO_LOCK(_object) \
+            ((_object) != NULL && (_object)->ref_count == 2)
+
+#define PFM_IS_VALID_OBJECT(_object) \
+            pfm_is_object_valid((struct _pfm_object_template *)_object)
+
+#define PFM_R_LOCK_OBJECT(_object, _lock) \
+            PFM_SPIN_LOCK(_lock); \
+            if (PFM_IS_VALID_OBJECT_WO_LOCK(_object) && ((_object)->writer_cnt == 0)) { \
+                ++((_object)->reader_cnt); \
+            } else { \
+                (_object) = NULL; \
+            } \
+            PFM_SPIN_UNLOCK(_lock)
+
+#define PFM_R_UNLOCK_OBJECT(_object, _lock) \
+            ASSERT((_object)); \
+            PFM_SPIN_LOCK(_lock); \
+            ASSERT((_object)->reader_cnt > 0); \
+            --((_object)->reader_cnt); \
+            PFM_SPIN_UNLOCK(_lock)
+
+#define PFM_INIT_OBJECT_BEGIN(_object, _lock) \
+            PFM_ASSERT(_object); \
+            PFM_SPIN_LOCK(_lock); \
+            PFM_ASSERT((_object)->ref_count == 0); \
+            (_object)->ref_count = 1; \
+            PFM_SPIN_UNLOCK(_lock)
+
+#define PFM_INIT_OBJECT_END(_object, _lock) \
+            PFM_ASSERT(_object); \
+            PFM_SPIN_LOCK(_lock); \
+            PFM_ASSERT(_object->ref_count == 1); \
+            (_object)->ref_count = 2; \
+            (_object)->reader_cnt = 0; \
+            (_object)->writer_cnt = 0; \
+            PFM_SPIN_UNLOCK(_lock)
+
+#define PFM_DEINIT_OBJECT_BEGIN(_object, _lock) \
+            PFM_ASSERT(kal_if_hisr() == KAL_FALSE); \
+            PFM_SPIN_LOCK(_lock); \
+            if (PFM_IS_VALID_OBJECT_WO_LOCK(_object)) { \
+                --((_object)->ref_count); \
+                while ((_object)->reader_cnt != 0 || (_object)->writer_cnt != 0) { \
+                    PFM_SPIN_UNLOCK(_lock); \
+                    kal_sleep_task(PFM_DEL_OBJECT_SLEEP_TICKS); \
+                    PFM_SPIN_LOCK(_lock); \
+                } \
+                PFM_ASSERT((_object)->ref_count == 1); \
+            } else { \
+                (_object) = NULL; \
+            } \
+            PFM_SPIN_UNLOCK(_lock)
+
+#define PFM_DEINIT_OBJECT_END(_object, _lock) \
+            PFM_SPIN_LOCK(_lock); \
+            PFM_ASSERT((_object)->ref_count == 1); \
+            PFM_ASSERT((_object)->reader_cnt == 0); \
+            PFM_ASSERT((_object)->writer_cnt == 0); \
+            (_object)->ref_count = 0; \
+            PFM_SPIN_UNLOCK(_lock)
+
+#define PFM_W_LOCK_OBJECT(_object, _lock) \
+            PFM_ASSERT(kal_if_hisr() == KAL_FALSE); \
+            PFM_SPIN_LOCK(_lock); \
+            if (PFM_IS_VALID_OBJECT_WO_LOCK(_object)) { \
+                while ((_object)->reader_cnt != 0 || (_object)->writer_cnt != 0) { \
+                    PFM_SPIN_UNLOCK(_lock); \
+                    kal_sleep_task(PFM_W_LOCK_OBJECT_SLEEP_TICKS); \
+                    PFM_SPIN_LOCK(_lock); \
+                } \
+                if (PFM_IS_VALID_OBJECT_WO_LOCK(_object)) { \
+                    ++((_object)->writer_cnt); \
+                } else { \
+                    (_object) = NULL; \
+                    PFM_SPIN_UNLOCK(_lock); \
+                } \
+            } else { \
+                (_object) = NULL; \
+                PFM_SPIN_UNLOCK(_lock); \
+            }
+
+#define PFM_W_UNLOCK_OBJECT(_object, _lock) \
+            PFM_ASSERT((_object)); \
+            PFM_ASSERT((_object)->writer_cnt == 1); \
+            --((_object)->writer_cnt); \
+            PFM_SPIN_UNLOCK(_lock)
+
+/*------------------------------------------------------------------------------
+ * Functions for Synchronization
+ *----------------------------------------------------------------------------*/
+struct _pfm_object_template {
+    PFM_DECLARE_OBJECT
+};
+
+static INLINE kal_bool pfm_is_object_valid(struct _pfm_object_template *object)
+{
+    kal_bool ret;
+
+    PFM_SPIN_LOCK(pfm_spinlock_g);
+    ret = PFM_IS_VALID_OBJECT_WO_LOCK(object);
+    PFM_SPIN_UNLOCK(pfm_spinlock_g);
+
+    return ret;
+}
+
+#endif /* __INC_PFM_OBJECT_H */
diff --git a/mcu/middleware/hif/ipcore/src/ipc_data.c b/mcu/middleware/hif/ipcore/src/ipc_data.c
new file mode 100644
index 0000000..626d818
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_data.c
@@ -0,0 +1,2651 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2016
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_data.c
+ *
+ * Project:
+ * --------
+ *   UMOLYA
+ *
+ * Description:
+ * ------------
+ *   IP Core Uplink/Downlink data path implementation.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_api.h"
+#include "mw_sap.h"
+#include "em_msgid.h"
+#include "hif_mw_msgid.h"
+#include "nl2_msgid.h"
+#include "upcm.h"
+#include "qmu_bm_util.h"
+
+#include "ipc_data.h"
+#include "ipc_debug.h"
+#include "ipc_filter.h"
+#include "ipc_utils.h"
+
+#if defined(__IPF_SUPPORT__)
+#include "ipc_data_ipf.h"
+#endif
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+kal_uint32                  ipc_em_on_s = 0;
+kal_bool                    ipc_ul_enable_g = KAL_TRUE;
+
+/* Test loopback mode */
+ipc_test_loopback_mode_e    ipc_test_loopback_mode_s = IPC_TEST_LOOPBACK_MODE_OFF;
+kal_uint32                  ipc_test_loopback_a_netif_id_s = 0;
+kal_uint32                  ipc_test_loopback_b_netif_id_s = 0;
+
+/*------------------------------------------------------------------------------
+ * Private data structure.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Private variables.
+ *----------------------------------------------------------------------------*/
+static ipc_ul_queue_t           ipc_ul_queues_s[IPC_UL_QUEUE_NUM];
+/* All DL queue processing MUST be in IPCore own context */
+static ipc_dl_queue_t           ipc_dl_queues_s[IPC_DL_QUEUE_NUM];
+kal_bool                        ipc_ul_processing_s = KAL_FALSE;
+static kal_bool                 ipc_dl_processing_s = KAL_FALSE;
+kal_bool                        ipc_ul_reload_retrying_s = KAL_FALSE;
+
+event_scheduler                *ipc_es_ul_throttle_s = NULL; /* Timer for UL throttle mechanism. */
+
+static ipc_ul_throttle_state_e  ipc_ul_throttle_state_s = IPC_UL_THROTTLE_STATE_NONE;
+static ipc_ul_throttle_conf_t   ipc_ul_throttle_conf_s = {0, 0, 0};
+static eventid                  ipc_eid_ul_throttle_s = NULL; /* Timer for UL throttle mechanism. */
+static kal_bool                 ipc_ul_throttle_is_block_latency_concern_s = KAL_FALSE;
+static kal_bool                 ipc_ul_throttle_is_ims_emergency_s = KAL_FALSE;
+static qbm_gpd*                 ipc_proxy_ipv6_ra_pool[IPC_PROXY_IPV6_RA_POOL_SIZE] = {NULL};
+static qbm_gpd*                 ipc_dl_qbm_head_s, *ipc_dl_qbm_tail_s;
+static ipc_data_usage_info_t    ipc_data_usage_info_s[IPC_MAX_SESSION_CNT];
+
+/*------------------------------------------------------------------------------
+ * Private functions.
+ *----------------------------------------------------------------------------*/
+void ipc_dest_ior(
+    ipc_io_request_t       *ior)
+{
+    ipc_io_request_t       *next_ior;
+
+    IPC_ASSERT(ior);
+    for (; ior; ior = next_ior) {
+        next_ior = ior->next_request;
+        if ( ior->first_gpd && ior->last_gpd ) {
+            qbmt_dest_q(ior->first_gpd, ior->last_gpd);
+        }
+    }
+}
+
+/*
+ * Assumption: netif read lock is acquired.
+ */
+void ipc_reload_uplink(ipc_netif_t *netif)
+{
+    kal_bool need_retry;
+
+    hif_data_trace(MD_TRC_IPC_UL_RELOAD_UPLINK, 0, netif, netif->config.netif_id, netif->config.ipc_ul_reload_callback_t);
+
+    if (netif->config.ipc_ul_reload_callback_t) {
+        /* Clear netif_ul_need_reload before call netif reload cbk */
+        ipc_set_netif_ul_set_need_reload(netif, KAL_FALSE);
+        need_retry = netif->config.ipc_ul_reload_callback_t(
+                                        netif->config.ul_reload_context);
+
+        hif_data_trace(MD_TRC_IPC_UL_RELOAD_UPLINK_RESULT, 0, netif, netif->config.netif_id, need_retry);
+
+        ipc_set_netif_ul_reload_retry(netif, need_retry);
+    }
+}
+
+/*
+ * Assumption: netif read lock is acquired.
+ */
+static void ipc_forward_ul_ior(ipc_netif_t *netif, ipc_io_request_t *ior)
+{
+#if IPC_PEER == IPC_PEER_NULL_DROP
+    /*
+         * Drop all uplink packets (Only for test purpose).
+         */
+    hif_data_trace(MD_TRC_IPC_UL_DROP_UL_IOR, 0, netif, ior);
+
+    ipc_dest_ior(ior);
+#elif IPC_PEER == IPC_PEER_NULL_LOOPBACK
+    /*
+         * Loopback uplink packets. (Only for test purpose).
+         */
+    if (NULL != netif->config.ipc_dlink_callback_t) {
+        hif_data_trace(MD_TRC_IPC_UL_LOOPBACK_UL_IOR, 0, netif, ior, netif->config.ipc_dlink_callback_t);
+        netif->config.ipc_dlink_callback_t(netif->config.callback_context, ior);
+    } else {
+        hif_data_trace(MD_TRC_IPC_UL_LOOPBACK_UL_IOR_DROP, 0, netif, ior, netif->config.ipc_dlink_callback_t);
+        ipc_dest_ior(ior);
+    }
+#else
+    ipc_session_t          *session = NULL;
+    ipc_io_request_t       *next_ior = NULL;
+    qbm_gpd                *ipv4_first_gpd = NULL;
+    qbm_gpd                *ipv4_last_gpd = NULL;
+    qbm_gpd                *ipv6_first_gpd = NULL;
+    qbm_gpd                *ipv6_last_gpd = NULL;
+
+    for (; ior; ior = next_ior) {
+        next_ior = ior->next_request;
+        if ( ior->first_gpd && ior->last_gpd ) {
+            if (ior->ip_type != IPC_IP_TYPE_MIXED) {
+                qbm_gpd *first_gpd = NULL;
+                qbm_gpd *last_gpd = NULL;
+
+                first_gpd = ior->first_gpd;
+                last_gpd = ior->last_gpd;
+
+                hif_data_trace(MD_TRC_IPC_UL_HANDLE_UL_GPD_LIST, ior->ip_type, netif->config.netif_id, first_gpd, last_gpd);
+
+                /* HIF network interface told IPv4 or IPv6 case. */
+                ipc_do_ul_filter(ior->ip_type, netif->config.netif_id, &first_gpd, &last_gpd);
+                if (first_gpd) {
+                    session = ipc_find_session_by_netif(netif, ior->ip_type);
+                    if (session) {
+
+                        hif_data_trace(MD_TRC_IPC_UL_FORWARD_UL_SDU, ior->ip_type, session->context, first_gpd, last_gpd);
+                        hif_data_trace(MD_TRC_IPC_UL_FORWARD_UL_SDU_MULTI_PS, session->context);
+                        IPC_FORWARD_UL_SDU((ip_type_e )ior->ip_type, /* ip_type */
+                                           session->context, /* pdn_id */
+                                           first_gpd, /* p_head */
+                                           last_gpd); /* p_tail */
+                        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                    } else {
+                        hif_trace_error(IPC_TR_UL_DROP_FOR_SESSION_DEACT, netif->config.netif_id, ior, ior->ip_type);
+                        qbmt_dest_q(first_gpd, last_gpd);
+                    }
+                }
+            } else {
+                /*
+                 * HIF network interface cannot tell IPv4 or IPv6 case.
+                 * Classify GPD into IPv4 and IPv6 lists, and then send them to wireless network respectively.
+                 */
+                /* ipv4_first_gpd / ipv4_last_gpd / ipv6_first_gpd / ipv6_last_gpd are initiated in this procedure */
+                ipc_utils_clarify_gpd(ior->first_gpd, ior->last_gpd, &ipv4_first_gpd, &ipv4_last_gpd, &ipv6_first_gpd, &ipv6_last_gpd);
+
+                if (ipv4_first_gpd) {
+
+                    hif_data_trace(MD_TRC_IPC_UL_HANDLE_IPV4_UL_GPD_LIST, ior->ip_type, netif->config.netif_id, ipv4_first_gpd, ipv4_last_gpd);
+
+                    ipc_do_ul_filter( IPC_IP_TYPE_IPV4, netif->config.netif_id, &ipv4_first_gpd, &ipv4_last_gpd);
+                    if (ipv4_first_gpd) {
+                        session = ipc_find_session_by_netif(netif, IPC_IP_TYPE_IPV4);
+                        if (session) {
+
+                            hif_data_trace(MD_TRC_IPC_UL_FORWARD_IPV4_UL_SDU, ior->ip_type, session->context, ipv4_first_gpd, ipv4_last_gpd);
+                            hif_data_trace(MD_TRC_IPC_UL_FORWARD_UL_SDU_MULTI_PS, session->context);
+                            IPC_FORWARD_UL_SDU((ip_type_e)IPC_IP_TYPE_IPV4, /* ip_type */
+                                               session->context, /* pdn_id */
+                                               ipv4_first_gpd, /* p_head */
+                                               ipv4_last_gpd); /* p_tail */
+                            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                        } else {
+                            hif_trace_error(IPC_TR_UL_DROP_FOR_SESSION_DEACT, netif->config.netif_id, ior, IPC_IP_TYPE_IPV4);
+                            qbmt_dest_q(ipv4_first_gpd, ipv4_last_gpd);
+                        }
+                    }
+                }
+
+                if (ipv6_first_gpd) {
+
+                    hif_data_trace(MD_TRC_IPC_UL_HANDLE_IPV6_UL_GPD_LIST, ior->ip_type, netif->config.netif_id, ipv6_first_gpd, ipv6_last_gpd);
+                    ipc_do_ul_filter( IPC_IP_TYPE_IPV6, netif->config.netif_id, &ipv6_first_gpd, &ipv6_last_gpd);
+
+                    if (ipv6_first_gpd) {
+                        session = ipc_find_session_by_netif(netif, IPC_IP_TYPE_IPV6);
+                        if (session) {
+
+                            hif_data_trace(MD_TRC_IPC_UL_FORWARD_IPV6_UL_SDU, ior->ip_type, session->context, ipv6_first_gpd, ipv6_last_gpd);
+                            hif_data_trace(MD_TRC_IPC_UL_FORWARD_UL_SDU_MULTI_PS, session->context);
+                            IPC_FORWARD_UL_SDU((ip_type_e)IPC_IP_TYPE_IPV6, /* ip_type */
+                                               session->context, /* pdn_id */
+                                               ipv6_first_gpd, /* p_head */
+                                               ipv6_last_gpd); /* p_tail */
+                            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                        } else {
+                            hif_trace_error(IPC_TR_UL_DROP_FOR_SESSION_DEACT, netif->config.netif_id, ior, IPC_IP_TYPE_IPV6);
+                            qbmt_dest_q(ipv6_first_gpd, ipv6_last_gpd);
+                        }
+                    }
+                }
+            } /* end of HIF network interface cannot tell IPv4 or IPv6 case. */
+        } else {
+            hif_trace_error(IPC_TR_UL_DROP_FOR_INVALID_IOR, netif->config.netif_id, ior, ior->first_gpd, ior->last_gpd);
+            IPC_ASSERT(KAL_FALSE);
+        }
+    } /* end of for (ior) */
+#endif
+}
+
+static void ipc_calc_data_usage(kal_uint32 pdn_id,
+                                    qbm_gpd *p_head_gpd,
+                                    qbm_gpd *p_tail_gpd)
+{
+    ipc_data_usage_info_t data_usage = {0};
+    qbm_gpd *p_curr_gpd = NULL;
+    qbm_gpd *p_next_gpd = NULL;
+    qbm_gpd *p_bd = NULL;
+    kal_uint32 pkt_len = 0;
+    kal_bool is_eol = KAL_FALSE;
+
+    IPC_ASSERT(p_head_gpd && p_tail_gpd);
+
+    for (p_curr_gpd = p_head_gpd; p_curr_gpd && !is_eol; p_curr_gpd = p_next_gpd) {
+        p_next_gpd = QBM_DES_GET_NEXT(p_curr_gpd);
+        is_eol = (p_curr_gpd == p_tail_gpd);
+
+        pkt_len = QBM_DES_GET_DATALEN(p_curr_gpd);
+        p_bd = QBM_DES_GET_DATAPTR(p_curr_gpd);
+        if ((0 != pkt_len) && (pkt_len == QBM_DES_GET_DATALEN(p_bd))) {
+            data_usage.uplink_bytes += pkt_len;
+            ++data_usage.uplink_packets;
+        }
+    }
+
+    ipc_set_data_usage_by_pdn_sim_id(UL_DIRECT, pdn_id, &data_usage);
+}
+
+static void ipc_on_process_ul_ior_list(ipc_ul_queue_t *q)
+{
+    ipc_internal_ior_t     *head_ior = q->ior_head;
+    ipc_internal_ior_t     *curr_ior = NULL;
+    ipc_internal_ior_t     *next_ior = NULL;
+    ipc_netif_t            *netif = NULL;
+    qbm_gpd                *head_gpd_p = NULL;
+    qbm_gpd                *tail_gpd_p =  NULL;
+    kal_uint8              prev_pdnid = 0;
+    kal_uint8              prev_iptype = 0;
+    qbm_gpd                *head_gpd_ebi_p = NULL;
+    qbm_gpd                *tail_gpd_ebi_p =  NULL;
+    kal_uint8              prev_ebi = 0;
+
+    HIF_SWLA_START("IU3");
+
+    for (curr_ior = head_ior; curr_ior; curr_ior = next_ior) {
+        next_ior = (ipc_internal_ior_t *)(curr_ior->io_req.next_request);
+
+        if (IPC_NORMAL_DATA_PATH == curr_ior->io_req.data_path_type) {
+            /* IOR of ipc_uplink() */
+            hif_data_trace(MD_TRC_IPC_UL_ON_PROCESS_NORMAL_IOR, 0, curr_ior, curr_ior->netif);
+
+            if ((NULL == next_ior) ||
+                (IPC_NORMAL_DATA_PATH != next_ior->io_req.data_path_type) ||
+                (head_ior->netif != next_ior->netif)) {
+
+                curr_ior->io_req.next_request = NULL;
+                netif = head_ior->netif;
+                IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+                if (netif) {
+                    /* Reload uplink buffers for the network interface. */
+                    ipc_reload_uplink(netif);
+                    ipc_forward_ul_ior(netif, &(head_ior->io_req));
+                    IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+                } else {
+                    hif_trace_error(IPC_TR_UL_DROP_FOR_INVALID_NETIF, head_ior->netif, &(head_ior->io_req));
+                    ipc_dest_ior(&(head_ior->io_req));
+                }
+
+                head_ior = next_ior;
+            }
+        } else if (IPC_INTERNAL_DATA_PATH == curr_ior->io_req.data_path_type) {
+            /* IOR of ipc_send_ul_pkt() & ipc_send_ul_pkt_by_pdn() */
+            IPC_ASSERT(head_ior == curr_ior);
+
+            if (curr_ior->io_req.ip_type == 0xFF) {
+                if ((NULL == head_gpd_ebi_p) && (NULL == tail_gpd_ebi_p)) {
+                    head_gpd_ebi_p = curr_ior->io_req.first_gpd;
+                    tail_gpd_ebi_p = curr_ior->io_req.last_gpd;
+                    prev_ebi = curr_ior->ebi;
+                } else {
+                    if (prev_ebi == curr_ior->ebi) {
+                        /* same EBI packet,need to group here */
+                        QBM_DES_SET_NEXT(tail_gpd_ebi_p, curr_ior->io_req.first_gpd);
+                        tail_gpd_ebi_p = curr_ior->io_req.last_gpd;
+                        hif_data_trace(MD_TRC_IPC_UL_CLUB_PKT_B4_FORWARD, prev_ebi, head_gpd_ebi_p, tail_gpd_ebi_p);
+                    } else {
+                        hif_data_trace(MD_TRC_IPC_UL_SEND_PKT_FORWARD, prev_ebi, head_gpd_ebi_p, tail_gpd_ebi_p);
+                        /* Sent to UPCM by EBI */
+                        IPC_FORWARD_UL_SDU_BY_EBI(prev_ebi, head_gpd_ebi_p, tail_gpd_ebi_p);
+                        head_gpd_ebi_p = curr_ior->io_req.first_gpd;
+                        tail_gpd_ebi_p = curr_ior->io_req.last_gpd;
+                        prev_ebi = curr_ior->ebi;
+                    }
+                }
+            } else {
+                if ((NULL == head_gpd_p) && (NULL == tail_gpd_p)) {
+                    head_gpd_p = curr_ior->io_req.first_gpd;
+                    tail_gpd_p = curr_ior->io_req.last_gpd;
+                    prev_pdnid = curr_ior->pdn;
+                    prev_iptype = curr_ior->io_req.ip_type;
+                } else {
+                    if ((prev_pdnid == curr_ior->pdn) && (prev_iptype == curr_ior->io_req.ip_type)) {
+                        /* same PDN & IP packet,need to group here */
+                        QBM_DES_SET_NEXT(tail_gpd_p, curr_ior->io_req.first_gpd);
+                        tail_gpd_p = curr_ior->io_req.last_gpd;
+                        hif_data_trace(MD_TRC_IPC_UL_CLUB_PKT_BY_PDN_B4_FORWARD, prev_pdnid, prev_iptype, head_gpd_p, tail_gpd_p);
+                    } else {
+                        hif_data_trace(MD_TRC_IPC_UL_SEND_PKT_BY_PDN_FORWARD, prev_pdnid, prev_iptype, head_gpd_p, tail_gpd_p);
+                        /*calculate Data usage for uplink packets*/
+                        ipc_calc_data_usage(prev_pdnid, head_gpd_p, tail_gpd_p);
+                        /* Sent to UPCM by PDN */
+                        IPC_FORWARD_UL_SDU((kal_uint8 )prev_iptype, prev_pdnid, head_gpd_p, tail_gpd_p);
+                        head_gpd_p = curr_ior->io_req.first_gpd;
+                        tail_gpd_p = curr_ior->io_req.last_gpd;
+                        prev_pdnid = curr_ior->pdn;
+                        prev_iptype = curr_ior->io_req.ip_type;
+                    }
+                }
+            }
+
+            head_ior = next_ior;
+        } else {
+            /* unsupported data path type */
+            ASSERT(KAL_FALSE);
+        }
+    }
+
+    if (NULL != head_gpd_ebi_p) {
+        hif_data_trace(MD_TRC_IPC_UL_SEND_PKT_FORWARD, prev_ebi, head_gpd_ebi_p, tail_gpd_ebi_p);
+        /* Sent to UPCM by EBI */
+        IPC_FORWARD_UL_SDU_BY_EBI(prev_ebi, head_gpd_ebi_p, tail_gpd_ebi_p);
+    }
+
+    if (NULL != head_gpd_p) {
+        hif_data_trace(MD_TRC_IPC_UL_SEND_PKT_BY_PDN_FORWARD, prev_pdnid, prev_iptype, head_gpd_p, tail_gpd_p);
+        /*calculate Data usage for uplink packets*/
+        ipc_calc_data_usage(prev_pdnid, head_gpd_p, tail_gpd_p);
+        /* Sent to UPCM by PDN */
+        IPC_FORWARD_UL_SDU((kal_uint8 )prev_iptype, prev_pdnid, head_gpd_p, tail_gpd_p);
+    }
+
+    HIF_SWLA_STOP("IU3");
+}
+
+static void ipc_start_ul_throttle_timer(kal_uint32 elapse_time);
+#ifndef ATEST_SYS_IPCORE
+static
+#endif
+void ipc_ul_throttle_timeout(void *event_hf_param)
+{
+    kal_bool                to_send_msg;
+
+#ifndef ATEST_SYS_IPCORE
+    IPC_ASSERT(ipc_eid_ul_throttle_s);
+    ipc_eid_ul_throttle_s = NULL;
+#endif
+
+    hif_data_trace(MD_TRC_IPC_TR_TIMER_UL_THROTTLE_TIMEOUT, kal_get_systicks(),
+                    ipc_ul_throttle_state_s,
+                    ipc_ul_throttle_conf_s.enabled,
+                    ipc_ul_throttle_conf_s.active_period_100ms,
+                    ipc_ul_throttle_conf_s.suspend_period_100ms);
+
+    if (ipc_ul_throttle_conf_s.enabled) {
+        if (IPC_UL_THROTTLE_STATE_ACTIVE == ipc_ul_throttle_state_s) {
+            /* UL throttle state: ACTIVE -> SUSPEND */
+            ipc_start_ul_throttle_timer(ipc_ul_throttle_conf_s.suspend_period_100ms * KAL_TICKS_100_MSEC);
+            ipc_ul_throttle_state_s = IPC_UL_THROTTLE_STATE_SUSPEND;
+        } else if (IPC_UL_THROTTLE_STATE_SUSPEND == ipc_ul_throttle_state_s) {
+            /* UL throttle state: SUSPEND -> ACTIVE */
+            ipc_start_ul_throttle_timer(ipc_ul_throttle_conf_s.active_period_100ms * KAL_TICKS_100_MSEC);
+            ipc_ul_throttle_state_s = IPC_UL_THROTTLE_STATE_ACTIVE;
+
+            /* IPCORE need to process ul queue if ul pending queue is not empty */
+            IPC_SPIN_LOCK(g_ul_spinlock);
+            to_send_msg = ((!ipc_ul_processing_s) && (!ipc_are_ul_queues_empty()));
+            if (to_send_msg) {
+                ipc_ul_processing_s = KAL_TRUE;
+            }
+            IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+            /* Switch to IPCORE context. */
+            if (to_send_msg) {
+                msg_send6(MOD_NIL,    /* src_mod_id */
+                          MOD_IPCORE, /* dest_mod_id */
+                          IPCORE_SAP, /* sap_id */
+                          MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ, /* msg_id */
+                          NULL,  /* local_para_ptr */
+                          NULL); /* peer_buff_ptr */
+            }
+        } else {
+            IPC_ASSERT(KAL_FALSE);
+        }
+        msg_send6(MOD_NIL,    /* src_mod_id */
+                  MOD_ENPDCP, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  (IPC_UL_THROTTLE_STATE_SUSPEND == ipc_ul_throttle_state_s) ?
+                    MSG_ID_IPCORE_ENPDCP_UL_SUSPEND_NTF : MSG_ID_IPCORE_ENPDCP_UL_ACTIVE_NTF, /* msg_id */
+                  NULL,  /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+
+        /* For EM ELT update info*/
+        ipc_em_send_ul_throttle_status();
+    }
+}
+
+static void ipc_start_ul_throttle_timer(kal_uint32 elapse_time)
+{
+#ifndef ATEST_SYS_IPCORE
+    IPC_ASSERT(ipc_es_ul_throttle_s && elapse_time);
+
+    ipc_eid_ul_throttle_s =
+        evshed_set_event(ipc_es_ul_throttle_s,
+                         ipc_ul_throttle_timeout,
+                         NULL,
+                         elapse_time);
+
+    IPC_ASSERT(ipc_eid_ul_throttle_s);
+    hif_data_trace(MD_TRC_IPC_TR_START_UL_THROTTLE_TIMER, kal_get_systicks(), elapse_time);
+#endif
+}
+
+/*------------------------------------------------------------------------------
+ * Private functions. (Gen93)
+ *----------------------------------------------------------------------------*/
+static INLINE ipc_ul_queue_priority_e
+ipc_get_queue_priority_from_lhif_queue_type(LHIF_QUEUE_TYPE lhif_q_type)
+{
+    switch (lhif_q_type) {
+        case LHIF_HWQ_AP_UL_Q0:
+            return IPC_UL_QUEUE_PRIORITY_LOW;
+        case LHIF_HWQ_AP_UL_Q1:
+            return IPC_UL_QUEUE_PRIORITY_HIGH;
+        default:
+            /*can't reach here*/
+            IPC_ASSERT(KAL_FALSE);
+            return IPC_UL_QUEUE_PRIORITY_LOW;
+    }
+}
+
+/*
+ * Assumption: UL queue write lock is acquired.
+ * This function should be very light. MUST NOT do any heavy jobs.
+ */
+static INLINE kal_bool
+ipc_is_ul_queue_allowed_to_send(ipc_ul_queue_t *queue)
+{
+    kal_bool ret = KAL_FALSE;
+
+    if (0 == queue->cnt) {
+        return KAL_FALSE;
+    }
+
+    switch (queue->queue_type) {
+        case IPC_UL_QUEUE_TYPE_IOR:
+            ret = (NULL != queue->ior_head);
+            break;
+        case IPC_UL_QUEUE_TYPE_META:
+            ret = (0 <= queue->meta_head);
+            break;
+        default:
+            /*can't reach here*/
+            IPC_ASSERT(KAL_FALSE);
+            return KAL_FALSE;
+    }
+
+    switch (queue->priority) {
+        case IPC_UL_QUEUE_PRIORITY_HIGH:
+            return ( ret && (!ipc_ul_throttle_is_block_latency_concern_s || ipc_ul_throttle_is_ims_emergency_s) );
+        case IPC_UL_QUEUE_PRIORITY_LOW:
+            return ( ret && (ipc_ul_throttle_state_s != IPC_UL_THROTTLE_STATE_SUSPEND) && ipc_ul_enable_g );
+        default:
+            /*can't reach here*/
+            IPC_ASSERT(KAL_FALSE);
+            return KAL_FALSE;
+    }
+}
+
+/*
+ * Assumption: UL queue write lock is acquired.
+ * This function should be very light. MUST NOT do any heavy jobs.
+ */
+static void
+ipc_clear_ior_queue(ipc_ul_queue_t *q)
+{
+    q->cnt = 0;
+    q->pending_cnt = 0;
+    q->ior_head = NULL;
+    q->ior_tail = NULL;
+}
+
+/*
+ * Assumption: UL queue write lock is acquired.
+ * This function should be very light. MUST NOT do any heavy jobs.
+ */
+static void
+ipc_clear_meta_queue(ipc_ul_queue_t *q)
+{
+    q->cnt = 0;
+    q->pending_cnt = 0;
+    q->meta_head = IPC_QUEUE_META_INVALID_VALUE;
+    q->meta_tail = IPC_QUEUE_META_INVALID_VALUE;
+}
+
+static void ipc_on_process_ul_meta_table(ipc_ul_queue_t *q)
+{
+    kal_uint16              start_idx, read_idx, end_idx;
+    LHIF_QUEUE_TYPE         queue_type;
+    lhif_meta_tbl_t        *meta_tbl;
+    lhif_meta_tbl_t        *meta;
+    kal_uint16              tbl_size;
+    kal_uint32              netif_id, prev_netif_id;
+    ipc_netif_t            *netif = NULL;
+    kal_uint8               ip_type;
+    kal_uint32              ipv4_pdn_id, ipv6_pdn_id;
+
+#ifdef __IPC_95_ACK_REDUCTION_SUPPORT__
+    lhif_meta_tbl_t        *p_drop_ea_table[IPC_HPC_ENTRY_SIZE] = {NULL};
+#endif
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    kal_uint32              i;
+    kal_uint32              netif_features;
+
+    static ipc_dpfm_lan_des_t        ap_to_host_des[IPC_DPFM_MAX_DEVICE_NUM];
+    static ipc_dpfm_lan_des_t        host_to_ap_des[IPC_DPFM_MAX_DEVICE_NUM];
+    static ipc_dpfm_mirror_des_t     dpfm_mirror_des[IPC_DPFM_MAX_DEVICE_NUM];
+#else
+        ipc_dpfm_mirror_des_t        *dpfm_mirror_des = NULL;
+#endif
+
+    HIF_SWLA_START("IU4");
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    kal_mem_set(ap_to_host_des, 0, sizeof(ap_to_host_des));
+    kal_mem_set(host_to_ap_des, 0, sizeof(host_to_ap_des));
+    kal_mem_set(dpfm_mirror_des, 0, sizeof(dpfm_mirror_des));
+    for (i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++) {
+        ap_to_host_des[i].dst_netif_id = IPC_INVALID_NETIF_ID;
+        ap_to_host_des[i].src_netif_id = IPC_INVALID_NETIF_ID;
+        /* the host interface don't care the sequence */
+        ap_to_host_des[i].is_need_adjust_seq = KAL_FALSE;
+        host_to_ap_des[i].dst_netif_id = IPC_INVALID_NETIF_ID;
+        host_to_ap_des[i].src_netif_id = IPC_INVALID_NETIF_ID;
+        host_to_ap_des[i].is_need_adjust_seq = KAL_FALSE;
+
+        dpfm_mirror_des[i].netif_id = IPC_INVALID_NETIF_ID;
+        dpfm_mirror_des[i].pdn_ids[0] = IPC_INVALID_NETIF_ID;
+        dpfm_mirror_des[i].pdn_ids[1] = IPC_INVALID_NETIF_ID;
+    }
+#endif
+
+    IPC_ASSERT(q);
+    start_idx = read_idx = q->meta_head;
+    end_idx = q->meta_tail;
+    queue_type = q->meta_queue_type;
+
+    IPC_QUERY_META_TABLE((kal_uint32 **)&meta_tbl, &tbl_size, queue_type);
+
+    prev_netif_id = IPC_INVALID_NETIF_ID;
+    ipv4_pdn_id = IPC_INVALID_PDN_ID;
+    ipv6_pdn_id = IPC_INVALID_PDN_ID;
+
+    do {
+        meta = &meta_tbl[read_idx];
+
+#if IPC_DBG_UL_PKT_DUMP_ENABLE
+        hif_trace_info(IPC_RECEIVED_UL_META_INFO, read_idx, meta->match_index, meta->mr);
+        ipc_utils_pkt_dump_buf(MSG_ID_DHL_UPCM_IMS_UL_RAW_DATA, MOD_IPCORE, (void*)meta->vrb_addr, meta->length);
+#endif
+
+        /* Filter & route packets */
+        if ( !meta->ignore &&
+             (LHIF_NET_TYPE_PDCP_LBA != meta->net_type) &&
+             (LHIF_NET_TYPE_PDCP_LBB != meta->net_type) &&
+             (LHIF_NET_TYPE_IGNORE != meta->net_type)) {
+
+#ifdef __IPC_95_ACK_REDUCTION_SUPPORT__
+            if (meta->ea && (IPC_HPC_MR_MATCH == meta->mr)) {
+                if (NULL != p_drop_ea_table[meta->match_index]) {
+                    /* free previous one */
+                    p_drop_ea_table[meta->match_index]->ignore = 1;
+                    IPC_FREE_META_VRB(p_drop_ea_table[meta->match_index]);
+                }
+
+                /* updated new one */
+                p_drop_ea_table[meta->match_index] = meta;
+            }
+#endif
+
+#if (CUR_GEN >= MD_GEN95)
+            //Gen95
+            netif_id = ipc_get_netif_id_from_meta(meta->net_type, meta->channel_id);
+#else
+            //Gen93
+            netif_id = ipc_get_netif_id_from_meta(meta->net_type, meta->net_if);
+#endif
+            if (netif_id != prev_netif_id) {
+                prev_netif_id = netif_id;
+
+                if (netif) {
+                    IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+                }
+                netif = ipc_find_netif(netif_id);
+                if (netif) {
+                    ipc_get_pdn_id_from_netif(&ipv4_pdn_id, &ipv6_pdn_id, netif);
+                } else {
+                    ipv4_pdn_id = IPC_INVALID_NETIF_ID;
+                    ipv6_pdn_id = IPC_INVALID_NETIF_ID;
+                }
+            }
+            if (netif) {
+        #if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+                /* Note that we don't support DPFM in Gen93 */
+                netif_features = netif->config.features;
+                if ( (netif_features & IPC_F_LAN) &&
+                     !(netif_features & IPC_F_TETHERING_ROUTE)) {
+                    ipc_pkt_des_t packet_des;
+
+                    /* Fill packet_des */
+                    kal_mem_set(&packet_des, 0, sizeof(ipc_pkt_des_t));
+                    packet_des.des_type = IPC_PKT_DES_TYPE_META;
+                    packet_des.packet = meta->vrb_addr;
+                    packet_des.packet_len = meta->length;
+                    packet_des.meta = meta;
+
+                    /*
+                     * Direct Tethering
+                     * The UL META from LHIF-LAN should be directly send to RNDIS.
+                     */
+                    meta->ignore = 1;
+                    if (!ipc_dpfm_fill_did_si_from_meta(ap_to_host_des, meta, netif_id, netif)) {
+                        hif_trace_error(IPC_TR_META_UL_DROP_FOR_LAN_DID_ALLOC_FAIL, netif->config.netif_id, meta, read_idx);
+                        IPC_FREE_META_VRB(meta);
+                    }
+                }
+                else {
+                    /* HPC supported */
+                    if (ipc_on_process_ul_hpc_result(&ip_type, read_idx, meta, netif_id, dpfm_mirror_des)) {
+                        /* return 1 means no filter match or no DPFM match. */
+                        if (netif_features & IPC_F_LAN) {
+                            meta->ignore = 1;
+                            if (!ipc_dpfm_fill_did_si_from_meta(host_to_ap_des, meta, netif_id, netif)) {
+                                hif_trace_error(IPC_TR_META_UL_DROP_FOR_LAN_DID_ALLOC_FAIL, netif->config.netif_id, meta, read_idx);
+                                IPC_FREE_META_VRB(meta);
+                            }
+                        }
+                        else {
+                            ipc_check_and_fill_session_info(ip_type, ipv4_pdn_id, ipv6_pdn_id, netif_id, meta);
+                        }
+                    }
+                }
+        #else //__MD_DIRECT_TETHERING_SUPPORT__
+            #if defined(__MD93__)
+                ip_type = ipc_get_ip_type_from_meta(meta);
+                if (IPC_IP_TYPE_INVALID != ip_type) {
+                    /* local used only */
+                    ipc_filter_info_t filter_info;
+                    ipc_packet_info_t packet_info;
+                    ipc_pkt_des_t packet_des;
+                    ipc_filter_t *filter;
+
+                    /* Fill packet_des */
+                    packet_des.des_type = IPC_PKT_DES_TYPE_META;
+                    packet_des.packet = meta->vrb_addr;
+                    packet_des.packet_len = meta->length;
+                    packet_des.meta = meta;
+                    packet_des.matched_filter = &filter;
+                    packet_des.filter_info = &filter_info;
+                    packet_des.packet_info = &packet_info;
+                    packet_des.ip_type = ip_type;
+                    packet_des.is_packet_info = KAL_FALSE;
+                    kal_mem_set(packet_des.packet_info, 0, sizeof(ipc_packet_info_t));
+
+                    if (ipc_meta_do_filter(ip_type, netif_id, meta, dpfm_mirror_des, &packet_des)) {
+                        ipc_fill_session_info_into_meta(ip_type, ipv4_pdn_id, ipv6_pdn_id, netif_id, meta);
+                    }
+                } else {
+                    hif_trace_error(IPC_TR_META_UL_DROP_FOR_NONE_IP_PKT, netif_id, read_idx, queue_type);
+                    meta->ignore = 1;
+                    IPC_FREE_META_VRB(meta);
+                }
+            #elif (CUR_GEN >= MD_GEN95)
+                /* HPC supported */
+                if (ipc_on_process_ul_hpc_result(&ip_type, read_idx, meta, netif_id, dpfm_mirror_des)) {
+                    ipc_check_and_fill_session_info(ip_type, ipv4_pdn_id, ipv6_pdn_id, netif_id, meta);
+                }
+            #endif
+        #endif
+            } else if (ipc_on_process_dpfm_cmd_result(read_idx, meta)) {
+                hif_trace_error(IPC_TR_META_UL_DROP_FOR_INVALID_NETIF, netif_id, read_idx, queue_type);
+                meta->ignore = 1;
+                IPC_FREE_META_VRB(meta);
+            }
+        }
+        else
+        {
+            if(LHIF_NET_TYPE_IGNORE == meta->net_type)
+            {
+                hif_trace_info(IPC_TR_UL_IGNORE_NET_TYPE_DROP, read_idx);
+                meta->ignore = 1;
+                IPC_FREE_META_VRB(meta);
+            }
+        }
+
+        read_idx ++;
+        if (read_idx == tbl_size) {
+            read_idx = 0;
+        }
+    } while (read_idx != end_idx);
+
+    if (netif) {
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+    }
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    /* For IPC_F_LAN netif, send packet to netif instead of upcm. */
+    ipc_dpfm_lan_on_did_downlink(ap_to_host_des);
+    ipc_dpfm_lan_on_did_downlink(host_to_ap_des);
+#endif
+    HIF_SWLA_STOP("IU4");
+
+    HIF_SWLA_START("IU5");
+    hif_data_trace(MD_TRC_IPC_UL_FORWARD_META, start_idx, end_idx, queue_type);
+    IPC_FORWARD_UL_META(q->meta_head, q->meta_tail, q->meta_queue_type);
+    HIF_SWLA_STOP("IU5");
+}
+
+static INLINE void ipc_clear_did_queue(ipc_did_queue_t *did_queue)
+{
+    did_queue->did_head = NULL;
+    did_queue->did_tail = NULL;
+}
+
+static INLINE void ipc_push_did_list_to_did_queue_tail(ipc_did_queue_t *did_queue, upcm_did *did_head, upcm_did *did_tail)
+{
+    upcm_did      **did_queue_head = &(did_queue->did_head);
+    upcm_did      **did_queue_tail = &(did_queue->did_tail);
+
+    if (*did_queue_tail) {
+        UPCM_DID_SET_NEXT(*did_queue_tail, did_head);
+        *did_queue_tail = did_tail;
+    } else {
+        *did_queue_head = did_head;
+        *did_queue_tail = did_tail;
+    }
+}
+
+static INLINE void ipc_push_did_list_to_did_queue_head(ipc_did_queue_t *did_queue, upcm_did *did_head, upcm_did *did_tail)
+{
+    upcm_did      **did_queue_head = &(did_queue->did_head);
+    upcm_did      **did_queue_tail = &(did_queue->did_tail);
+
+    if (*did_queue_head) {
+        UPCM_DID_SET_NEXT(did_tail, *did_queue_head);
+        *did_queue_head = did_head;
+    } else {
+        *did_queue_head = did_head;
+        *did_queue_tail = did_tail;
+    }
+}
+
+/*
+ * Assumption: netif read lock is acquired.
+ */
+static kal_bool ipc_forward_dl_did_default(kal_uint8 ip_type, ipc_netif_t *netif, kal_uint32 pdn_id, upcm_did *did)
+{
+    kal_bool            dl_cbk_ret = KAL_TRUE;
+    kal_uint32          netif_id = netif->config.netif_id;
+    kal_uint16          pkt_num_to_netif;
+
+    pkt_num_to_netif = ipc_did_do_filter(ip_type, netif_id, pdn_id, did);
+    if (pkt_num_to_netif) {
+        hif_data_trace(MD_TRC_IPC_DL_FWD_DL_CALLBACK_DID, pkt_num_to_netif, netif_id);
+
+        HIF_SWLA_START("ID3");
+        dl_cbk_ret = netif->config.ipc_dlink_did_cb_t(
+                netif->config.callback_context,
+                did);
+        HIF_SWLA_STOP("ID3");
+    }
+
+    return dl_cbk_ret;
+}
+
+/*
+ * Assumption: netif read lock is acquired.
+ */
+static kal_bool ipc_forward_dl_did_wo_filter(kal_uint8 ip_type, ipc_netif_t *netif, kal_uint32 pdn_id, upcm_did *did)
+{
+    kal_bool            dl_cbk_ret = KAL_TRUE;
+
+    hif_data_trace(MD_TRC_IPC_DL_FWD_DL_CALLBACK_DID_WO_FILTER, UPCM_DID_GET_PKT_NUM(did), netif->config.netif_id);
+
+    HIF_SWLA_START("ID3");
+    dl_cbk_ret = netif->config.ipc_dlink_did_cb_t(
+            netif->config.callback_context,
+            did);
+    HIF_SWLA_STOP("ID3");
+
+    return dl_cbk_ret;
+}
+
+typedef kal_bool (*ipc_fw_dl_did_f)(kal_uint8 ip_type, ipc_netif_t *netif, kal_uint32 pdn_id, upcm_did *did);
+typedef void (*ipc_enq_retry_dl_did_f)(upcm_did *did_head, upcm_did *did_tail, kal_uint32 queue_idx, ipc_data_enq_position_e position);
+
+/*
+ * Assumption: netif read lock is acquired.
+ */
+static ipc_fw_dl_did_f ipc_fw_dl_did_f_dispatcher_s[IPC_DID_QUEUE_TYPE_MAX] = {ipc_forward_dl_did_default,
+                                                                               ipc_forward_dl_did_wo_filter,
+                                                                               ipc_forward_dl_did_wo_filter};
+
+/*
+ * Assumption: netif read lock is acquired.
+ */
+static ipc_enq_retry_dl_did_f ipc_enq_retry_dl_did_f_dispatcher_s[IPC_DID_QUEUE_TYPE_MAX] = {ipc_did_enqueue_default_queue,
+                                                                                             ipc_did_enqueue_wo_filter_queue,
+                                                                                             ipc_did_enqueue_dpfm_queue};
+
+/*
+ * Assumption: netif read lock is acquired.
+ */
+static void ipc_on_process_dl_did_list(kal_uint8 ip_type, ipc_netif_t *netif, kal_uint32 pdn_id, ipc_did_queue_type_e queue_type, upcm_did *did_head, upcm_did *did_tail)
+{
+    upcm_did           *did;
+    upcm_did           *prev_did = NULL;
+    upcm_did           *next_did;
+    kal_bool            end_of_list;
+    kal_bool            dl_cbk_ret = KAL_TRUE;
+    kal_uint32          dl_queue_idx = pdn_id;
+
+    IPC_ASSERT(netif && did_head && did_tail);
+
+    end_of_list = KAL_FALSE;
+    for (did = did_head; did && !end_of_list; did = next_did) {
+        next_did = UPCM_DID_GET_NEXT(did);
+        end_of_list = (did == did_tail);
+
+        if (IPC_DID_QUEUE_TYPE_DEFAULT == queue_type) {
+            hif_data_trace(MD_TRC_IPC_DL_PROCESS_DL_DID, UPCM_DID_GET_FLOW(did),
+                                                  UPCM_DID_GET_COUNT_L(did),
+                                                 (UPCM_DID_GET_COUNT_L(did) + UPCM_DID_GET_PKT_NUM(did) - 1),
+                                                  UPCM_DID_GET_SEG_NUM(did),
+                                                  did,
+                                                  pdn_id);
+        }
+
+        dl_cbk_ret = (ipc_fw_dl_did_f_dispatcher_s[queue_type])(ip_type, netif, pdn_id, did);
+        if (!dl_cbk_ret) {
+            /*
+             * The netif is not able to receive DID for now.
+             * Queue all remaining DID to DL queue (IPC_DID_QUEUE_TYPE_WO_FILTER).
+             */
+            break;
+        }
+
+        prev_did = did;
+    }
+
+    if (did && !dl_cbk_ret) {
+        kal_bool            to_send_msg;
+
+        hif_data_trace(MD_TRC_IPC_DL_ON_DID_DOWNLINK_PENDING, did, did_tail);
+
+        if (did != did_head) {
+            /* Free DID which have been sent */
+            if (prev_did) {
+                IPC_ASSERT(UPCM_DID_GET_NEXT(prev_did) == did);
+                UPCM_DID_SET_NEXT(prev_did, NULL);
+            }
+            upcm_did_dest_q(did_head, prev_did);
+        }
+
+        /* Enqueue all remaining DID */
+        (ipc_enq_retry_dl_did_f_dispatcher_s[queue_type])(did, did_tail, dl_queue_idx, IPC_DATA_DID_HEAD);
+
+        /* Send ILM to IPCore for processing DL queue */
+        to_send_msg = ipc_data_check_and_set_dl_ilm_flag();
+
+        /*
+         * Switch to IPCORE context.
+         */
+        if (to_send_msg) {
+            msg_send6(MOD_NIL,    /* src_mod_id */
+                      MOD_IPCORE, /* dest_mod_id */
+                      IPCORE_DATAPATH_SAP,                /* sap_id */
+                      MSG_ID_IPCORE_PROCESS_DL_QUEUE_REQ, /* msg_id */
+                      NULL,  /* local_para_ptr */
+                      NULL); /* peer_buff_ptr */
+        }
+    } else {
+        upcm_did_dest_q(did_head, did_tail);
+    }
+
+    return;
+}
+
+/* Unused static function */
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+/*------------------------------------------------------------------------------
+ * Public functions.
+ *----------------------------------------------------------------------------*/
+void ipc_on_process_ul_queue(void)
+{
+    kal_uint32 i = 0;
+    ipc_ul_queue_t tmp_queue;
+    kal_bool to_send_pkt = KAL_FALSE;
+
+    HIF_SWLA_START("IU2");
+
+    IPC_SPIN_LOCK(g_ul_spinlock);
+    ipc_ul_processing_s = KAL_FALSE;
+    IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+    hif_data_trace(MD_TRC_IPC_UL_PROCESS_UPLINK_QUEUE);
+
+    for (i = 0; i < IPC_UL_QUEUE_NUM; i++) {
+        ipc_ul_queue_t *q = &ipc_ul_queues_s[i];
+        to_send_pkt = KAL_FALSE;
+
+        /*
+         * Check whether the ul queue is allowed to sent or not.
+         * If yes, dequeue the queue.
+         */
+        IPC_W_LOCK_OBJECT(q, g_ul_spinlock);
+        if (q) {
+            kal_mem_cpy(&tmp_queue, q, sizeof(ipc_ul_queue_t));
+            if (ipc_is_ul_queue_allowed_to_send(q)) {
+                q->ipc_clear_callback_t(q);
+                to_send_pkt = KAL_TRUE;
+            } else {
+                q->pending_cnt = q->cnt;
+            }
+            IPC_W_UNLOCK_OBJECT(q, g_ul_spinlock);
+
+            if (to_send_pkt) {
+                /* Process the queue by calling it's cbk */
+                tmp_queue.ipc_process_callback_t(&tmp_queue);
+            } else if (tmp_queue.pending_cnt) {
+                hif_data_trace(MD_TRC_IPC_UL_DEQUEUE_UPLINK_QUEUE, tmp_queue.queue_type, tmp_queue.priority, tmp_queue.pending_cnt);
+            }
+        } else {
+            IPC_ASSERT(KAL_FALSE);
+        }
+    }
+
+    HIF_SWLA_STOP("IU2");
+}
+
+void ipc_on_retry_ul_reload(void)
+{
+    kal_uint64      netif_bit_ids;
+    kal_uint64      lbs; /* least significant bit set to 1 */
+    ipc_netif_t    *netif;
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    ipc_ul_reload_retrying_s = KAL_FALSE;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    netif_bit_ids = ipc_get_all_netif_ul_reload_retry();
+
+    hif_data_trace(MD_TRC_IPC_UL_ON_RETRY_RELOAD, 0, netif_bit_ids);
+
+    while (netif_bit_ids) {
+        lbs = netif_bit_ids & ((~netif_bit_ids) + 1);
+        netif_bit_ids &= (~lbs);
+
+        netif = ipc_find_netif_by_bit_id(lbs);
+
+        hif_data_trace(MD_TRC_IPC_UL_ON_RETRY_RELOAD_FOR_NETIF, 0, netif, lbs);
+
+        if (netif) {
+            ipc_reload_uplink(netif);
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+        }
+    }
+}
+
+void ipc_on_downlink(kal_uint32 pdn_id, qbm_gpd *p_head, qbm_gpd *p_tail)
+{
+    ipc_session_t              *session;
+    ipc_netif_t                *netif;
+    ipc_io_request_t           *ior;
+    kal_uint8                   session_type;
+    kal_uint32                  netif_id;
+
+    HIF_SWLA_START("ID0");
+
+    IPC_ASSERT(p_head);
+    IPC_ASSERT(p_tail);
+
+    hif_data_trace(MD_TRC_IPC_DL_ON_DOWNLINK, pdn_id, p_head, p_tail);
+
+    session = ipc_find_session_by_context(pdn_id);
+    if (session) {
+        netif = session->netif;
+        session_type = session->type;
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        /* Get network interface information for following operations */
+        IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+        if (netif)
+        {
+            netif_id = netif->config.netif_id;
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+        } else
+        {
+            kal_uint8   ip_id = 0xff;
+
+            IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+            if (session)
+            {
+                ip_id = (kal_uint8)session->ip_id;
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            }
+
+            hif_trace_error(IPC_TR_DL_DROP_FOR_NETIF_INFO_LOCK_FAIL, pdn_id, ip_id, session_type, p_head, p_tail);
+            goto drop;
+        }
+
+        /* Do DL filter */
+        ipc_do_dl_filter(session_type, netif_id, pdn_id, &p_head, &p_tail);
+
+        if (NULL == p_head || NULL == p_tail)
+        {
+            hif_data_trace(MD_TRC_IPC_DL_ON_DOWNLINK_FILTER_OUT, 0, session_type, netif_id);
+            IPC_ASSERT(NULL == p_head && NULL == p_tail);
+            goto done;
+        }
+
+        /* Send DL traffic */
+        IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+        if (netif)
+        {
+            ior = (ipc_io_request_t *)QBM_DES_GET_SW_CTRL_FIELD(p_head);
+            ior->next_request = NULL;
+            ior->first_gpd = p_head;
+            ior->last_gpd = p_tail;
+            ior->ip_type = session_type;
+            ior->qos_priority = 0;
+
+            hif_data_trace(MD_TRC_IPC_DL_ON_DOWNLINK_CALLBACK_INFO, pdn_id, session_type, netif_id);
+            hif_data_trace(MD_TRC_IPC_DL_ON_DOWNLINK_CALLBACK_GPD, pdn_id, p_head, p_tail);
+
+            HIF_SWLA_START("ID3");
+            netif->config.ipc_dlink_callback_t(
+                netif->config.callback_context,
+                ior);
+            HIF_SWLA_STOP("ID3");
+
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+            goto done;
+        } else
+        {
+            kal_uint8   ip_id = 0xff;
+
+            IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+            if (session)
+            {
+                ip_id = (kal_uint8)session->ip_id;
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            }
+            hif_trace_error(IPC_TR_DL_DROP_FOR_NETIF_DETACH, pdn_id, ip_id, session_type, p_head, p_tail);
+            goto drop;
+        }
+    } else
+    {
+        hif_trace_error(IPC_TR_DL_DROP_FOR_INVALID_SESSION, pdn_id, p_head, p_tail);
+    }
+
+drop:
+    qbmt_dest_q(p_head, p_tail); /* Discard packets if something wrong. */
+done:
+
+    HIF_SWLA_STOP("ID0");
+    return;
+}
+
+void ipc_on_downlink_multiple_ps(kal_uint32 pdn_id, qbm_gpd *p_head, qbm_gpd *p_tail, kal_uint8 proto_idx)
+{
+    upcm_dlvr_dl_info_t *p_info = (upcm_dlvr_dl_info_t *)QBM_DES_GET_SW_CTRL_FIELD(p_head);
+
+    hif_data_trace(MD_TRC_IPC_DL_ON_DOWNLINK_MULTI_PS, pdn_id, proto_idx);
+
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, proto_idx);
+    IPC_MASK_PROTOID_ON_PDNID(p_info->ebi, proto_idx);
+    ipc_on_downlink(pdn_id, p_head, p_tail);
+}
+
+void ipc_timer_init()
+{
+    ipc_es_ul_throttle_s = evshed_create(
+                            "IPC_UL_THROTTLE", /* timer_name: event scheduler name */
+                            MOD_IPCORE, /* dest_mod_id: system sends timeout message to this module when event scheduler timeout happens */
+                            0, /* fuzz */
+                            0); /* max_delay_ticks */
+
+    if (ipc_es_ul_throttle_s) {
+        evshed_set_index(ipc_es_ul_throttle_s, IPC_ES_INDEX_UL_THROTTLE);
+    } else {
+        IPC_ASSERT(KAL_FALSE);
+    }
+}
+
+void ipc_set_ul_throttle(local_para_struct *local_para_ptr)
+{
+    ipc_set_ul_throttle_param_t *param = (ipc_set_ul_throttle_param_t *)local_para_ptr;
+    ipc_ul_throttle_conf_t *conf = (ipc_ul_throttle_conf_t *)(&(param->conf));
+    kal_bool to_send_msg = KAL_FALSE;
+
+    hif_trace_info(IPC_TR_SET_UL_THROTTLE_BEGIN, ipc_ul_throttle_state_s,
+                                                 ipc_ul_throttle_conf_s.enabled,
+                                                 ipc_ul_throttle_conf_s.active_period_100ms,
+                                                 ipc_ul_throttle_conf_s.suspend_period_100ms,
+                                                 ipc_ul_throttle_is_block_latency_concern_s);
+
+    /* Cancel original timer. */
+    if (NULL != ipc_eid_ul_throttle_s) {
+        ipc_ul_throttle_conf_s.enabled = KAL_FALSE;
+        evshed_cancel_event(ipc_es_ul_throttle_s, &ipc_eid_ul_throttle_s);
+        ipc_eid_ul_throttle_s = NULL;
+    }
+
+    if (conf->enabled) {
+        /* Enable IPC UL throttle. */
+        IPC_ASSERT(conf->active_period_100ms && conf->suspend_period_100ms);
+
+        kal_mem_cpy(&ipc_ul_throttle_conf_s, conf, sizeof(ipc_ul_throttle_conf_t));
+        /* Check if its the SUSPEND-FOREVER mode. (active:suspend = 1:255) */
+        if ( (1 == ipc_ul_throttle_conf_s.active_period_100ms) &&
+             (255 == ipc_ul_throttle_conf_s.suspend_period_100ms) ) {
+            /* It's SUSPEND-FOREVER mode */
+            ipc_ul_throttle_state_s = IPC_UL_THROTTLE_STATE_SUSPEND;
+        } else {
+            // Start new timer.
+            ipc_start_ul_throttle_timer(ipc_ul_throttle_conf_s.active_period_100ms * KAL_TICKS_100_MSEC);
+            ipc_ul_throttle_state_s = IPC_UL_THROTTLE_STATE_ACTIVE;
+        }
+
+        /* Check block-latency-concern enable bit */
+        if (1 == (conf->features & IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN)) {
+            IPC_ASSERT(255 == ipc_ul_throttle_conf_s.suspend_period_100ms);
+            ipc_ul_throttle_is_block_latency_concern_s = KAL_TRUE;
+        } else {
+            ipc_ul_throttle_is_block_latency_concern_s = KAL_FALSE;
+        }
+    } else {
+        /* Disable IPC UL throttle. */
+        kal_mem_set(&ipc_ul_throttle_conf_s, 0, sizeof(ipc_ul_throttle_conf_t));
+
+        ipc_ul_throttle_state_s = IPC_UL_THROTTLE_STATE_NONE;
+        ipc_ul_throttle_is_block_latency_concern_s = KAL_FALSE;
+
+        /* IPCORE need to process ul queue if ul pending queue is not empty */
+        IPC_SPIN_LOCK(g_ul_spinlock);
+        to_send_msg = ((!ipc_ul_processing_s) && (!ipc_are_ul_queues_empty()));
+        if (to_send_msg) {
+            ipc_ul_processing_s = KAL_TRUE;
+        }
+        IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+        /* Switch to IPCORE context. */
+        if (to_send_msg) {
+            msg_send6(MOD_NIL,    /* src_mod_id */
+                      MOD_IPCORE, /* dest_mod_id */
+                      IPCORE_SAP, /* sap_id */
+                      MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ, /* msg_id */
+                      NULL,  /* local_para_ptr */
+                      NULL); /* peer_buff_ptr */
+        }
+    }
+    hif_trace_info(IPC_TR_SET_UL_THROTTLE_END, ipc_ul_throttle_state_s,
+                                               ipc_ul_throttle_conf_s.enabled,
+                                               ipc_ul_throttle_conf_s.active_period_100ms,
+                                               ipc_ul_throttle_conf_s.suspend_period_100ms,
+                                               ipc_ul_throttle_is_block_latency_concern_s);
+
+    msg_send6(MOD_NIL,    /* src_mod_id */
+              MOD_ENPDCP, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              (IPC_UL_THROTTLE_STATE_SUSPEND == ipc_ul_throttle_state_s) ?
+                MSG_ID_IPCORE_ENPDCP_UL_SUSPEND_NTF : MSG_ID_IPCORE_ENPDCP_UL_ACTIVE_NTF, /* msg_id */
+              NULL,  /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+    /* For EM ELT update info*/
+    ipc_em_send_ul_throttle_status();
+}
+
+void ipc_em_send_ul_throttle_status(void)
+{
+#ifdef __EM_MODE__
+    em_ipc_ul_throttle_status_ind_struct_t *em_info_ptr;
+    ilm_struct ilm;
+
+    if (ipc_em_on_s) {
+        em_info_ptr = (em_ipc_ul_throttle_status_ind_struct_t *)
+                        construct_local_para(sizeof(em_ipc_ul_throttle_status_ind_struct_t), TD_RESET);
+
+        kal_mem_cpy(&(em_info_ptr->throttle_conf), &ipc_ul_throttle_conf_s, sizeof(ipc_ul_throttle_conf_t));
+        em_info_ptr->throttle_state = ipc_ul_throttle_state_s;
+
+        ilm.src_mod_id     = MOD_IPCORE;
+        ilm.dest_mod_id    = MOD_DHL;
+        ilm.msg_id         = MSG_ID_EM_IPC_UL_THROTTLE_STATUS_IND;
+        ilm.sap_id         = IPCORE_SAP;
+        ilm.local_para_ptr = (local_para_struct *)em_info_ptr;
+        ilm.peer_buff_ptr  = NULL;
+
+        dhl_EM_logger(&ilm);
+        destroy_ilm(&ilm);
+    }
+#endif
+}
+
+void ipc_ims_emergency_call_ind_handler(local_para_struct *local_para_ptr)
+{
+    ipc_vdm_ims_emergency_call_ind_struct_t *p = (ipc_vdm_ims_emergency_call_ind_struct_t *)local_para_ptr;
+    kal_bool                to_send_msg;
+
+    hif_data_trace(MD_TRC_IPC_UL_THROTTLE_IMS_EMERGEMCY_IND, ipc_ul_throttle_is_ims_emergency_s, p->is_calling);
+
+    ipc_ul_throttle_is_ims_emergency_s = p->is_calling;
+
+    if (ipc_ul_throttle_is_ims_emergency_s) {
+        /* IPCORE need to process ul queue if ul pending queue is not empty */
+        IPC_SPIN_LOCK(g_ul_spinlock);
+        to_send_msg = ((!ipc_ul_processing_s) && (!ipc_are_ul_queues_empty()));
+        if (to_send_msg) {
+            ipc_ul_processing_s = KAL_TRUE;
+        }
+        IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+        /* Switch to IPCORE context. */
+        if (to_send_msg) {
+            msg_send6(MOD_NIL,    /* src_mod_id */
+                      MOD_IPCORE, /* dest_mod_id */
+                      IPCORE_SAP, /* sap_id */
+                      MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ, /* msg_id */
+                      NULL,  /* local_para_ptr */
+                      NULL); /* peer_buff_ptr */
+        }
+    }
+}
+
+/*------------------------------------------------------------------------------
+ * Public functions. (Gen93)
+ *----------------------------------------------------------------------------*/
+kal_uint32
+ipc_get_netif_id_from_meta(kal_uint8 net_type, kal_uint8 channel_id)
+{
+    kal_uint32      netif_id = channel_id;
+
+    switch (net_type) {
+        case LHIF_NET_TYPE_LHIF:
+            netif_id |= IPC_NETIF_ID_LHIF_BEGIN;
+            break;
+        case LHIF_NET_TYPE_RNDIS:
+            netif_id |= IPC_NETIF_ID_ETH_BEGIN;
+            break;
+        case LHIF_NET_TYPE_MBIM:
+            netif_id |= IPC_NETIF_ID_MBIM_BEGIN;
+            break;
+        case LHIF_NET_TYPE_MCIF:
+            netif_id |= IPC_NETIF_ID_MCIF_BEGIN;
+            break;
+        case LHIF_NET_TYPE_VNIF:
+            netif_id |= IPC_NETIF_ID_VNIF_BEGIN;
+            break;
+        default:
+            /* Unexpected netif net_type. */
+            netif_id = IPC_INVALID_NETIF_ID;
+            hif_data_trace(MD_TRC_IPC_GET_NETIF_FROM_META, net_type, channel_id, netif_id);
+            break;
+    }
+
+    return netif_id;
+}
+
+kal_uint8
+ipc_get_ip_type_from_meta(lhif_meta_tbl_t *meta)
+{
+    /*
+     * 2016/11/29 Cammie.Yang
+     * Invalidate the first 64B of uplink packets to eliminate the duplicate cache-invalid effort in UPCM.
+     */
+    QBM_CACHE_INVALID(meta->vrb_addr, 64);
+    if (IPC_HDR_IS_V4(meta->vrb_addr)) {
+        return IPC_IP_TYPE_IPV4;
+    } else if (IPC_HDR_IS_V6(meta->vrb_addr)) {
+        return IPC_IP_TYPE_IPV6;
+    } else {
+        /* Unexpected packets, which is neither IPv4 or IPv6 */
+        return IPC_IP_TYPE_INVALID;
+    }
+}
+
+void
+ipc_get_pdn_id_from_netif(kal_uint32 *ipv4_pdn_id, kal_uint32 *ipv6_pdn_id, ipc_netif_t *netif)
+{
+    ipc_session_t      *session;
+
+    /* Get the IPv4 PDN ID of the netif */
+    session = ipc_find_session_by_netif(netif, IPC_IP_TYPE_IPV4);
+    if (session) {
+        IPC_ASSERT((session->context & 0xFFFFFF00) == 0);
+
+        *ipv4_pdn_id = session->context;
+
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+    } else {
+        *ipv4_pdn_id = IPC_INVALID_PDN_ID;
+    }
+
+    /* Get the IPv6 PDN ID of the netif */
+    session = ipc_find_session_by_netif(netif, IPC_IP_TYPE_IPV6);
+    if (session) {
+        IPC_ASSERT((session->context & 0xFFFFFF00) == 0);
+
+        *ipv6_pdn_id = session->context;
+
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+    } else {
+        *ipv6_pdn_id = IPC_INVALID_PDN_ID;
+    }
+}
+
+kal_bool ipc_queue_init()
+{
+    int i_type, i_priority;
+
+    /* Init UL queues */
+    for (i_type = 0; i_type < IPC_UL_QUEUE_TYPE_MAX; i_type++) {
+        for (i_priority = 0; i_priority < IPC_UL_QUEUE_PRIORITY_MAX; i_priority++) {
+            ipc_ul_queue_t *ul_queue = &ipc_ul_queues_s[_IPC_GET_UL_QUEUE_INDEX(i_type, i_priority)];
+
+            kal_mem_set(ul_queue, 0, sizeof(ipc_ul_queue_t));
+            if (!IPC_IS_VALID_OBJECT(ul_queue)) {
+                IPC_INIT_OBJECT_BEGIN(ul_queue, g_ul_spinlock);
+
+                ul_queue->queue_type = i_type;
+                ul_queue->priority = i_priority;
+                if (IPC_UL_QUEUE_TYPE_META == i_type) {
+                    switch (i_priority) {
+                        case IPC_UL_QUEUE_PRIORITY_HIGH:
+                            ul_queue->meta_queue_type = LHIF_HWQ_AP_UL_Q1;
+                            break;
+                        case IPC_UL_QUEUE_PRIORITY_LOW:
+                            ul_queue->meta_queue_type = LHIF_HWQ_AP_UL_Q0;
+                            break;
+                        default:
+                            /*can't reach here*/
+                            IPC_ASSERT(KAL_FALSE);
+                            return KAL_FALSE;
+                    }
+
+                    ul_queue->meta_queue_size = IPC_QUEUE_META_INVALID_VALUE;
+                    ul_queue->meta_head = IPC_QUEUE_META_INVALID_VALUE;
+                    ul_queue->meta_tail = IPC_QUEUE_META_INVALID_VALUE;
+                    ul_queue->ipc_clear_callback_t = ipc_clear_meta_queue;
+                    ul_queue->ipc_process_callback_t = ipc_on_process_ul_meta_table;
+                } else {
+                    ul_queue->ipc_clear_callback_t = ipc_clear_ior_queue;
+                    ul_queue->ipc_process_callback_t = ipc_on_process_ul_ior_list;
+                }
+                IPC_INIT_OBJECT_END(ul_queue, g_ul_spinlock);
+            }
+        }
+    }
+
+    /* Init DL queues */
+    kal_mem_set(ipc_dl_queues_s, 0, sizeof(ipc_dl_queues_s));
+    ipc_dl_qbm_head_s = NULL;
+    ipc_dl_qbm_tail_s = NULL;
+
+#if defined(__IPF_SUPPORT__)
+    /* Init DL meta queues */
+    ipc_dl_meta_queue_init();
+
+    /* Init UL HPC table */
+    ipc_hpc_init();
+#endif
+
+    return KAL_TRUE;
+}
+
+/*
+ * Assumption: ipc_spinlock_g is acquired.
+ * This function should be very light. MUST NOT do any heavy jobs.
+ */
+kal_bool ipc_are_ul_queues_empty()
+{
+    kal_bool    ret = KAL_TRUE;
+    kal_uint32  i = 0;
+
+    for (i = 0; i < IPC_UL_QUEUE_NUM; i++) {
+        ipc_ul_queue_t *q = &ipc_ul_queues_s[i];
+        ret &= (q->cnt == 0);
+    }
+
+    return ret;
+}
+
+void ipc_fill_session_info_into_meta(kal_uint8 ip_type, kal_uint32 ipv4_pdn_id, kal_uint32 ipv6_pdn_id, kal_uint32 netif_id, lhif_meta_tbl_t *meta)
+{
+    kal_uint32      pdn_id;
+    kal_uint32      proto_idx;
+
+    pdn_id = (IPC_IP_TYPE_IPV4 == ip_type) ? ipv4_pdn_id : ipv6_pdn_id;
+
+    if (IPC_INVALID_PDN_ID != pdn_id) {
+        IPC_RETRIEVE_PROTOID_FROM_PDNID(pdn_id, proto_idx);
+        IPC_UNMASK_PROTOID_FROM_PDNID(pdn_id);
+        meta->pdn = pdn_id;
+        meta->protocol_idx = proto_idx;
+    } else {
+        hif_trace_error(IPC_TR_META_UL_DROP_FOR_SESSION_DEACT, netif_id, meta, ip_type);
+        meta->ignore = 1;
+        IPC_FREE_META_VRB(meta);
+    }
+}
+
+void ipc_push_ior_list_to_ior_queue(ipc_io_request_t *head_ior, ipc_io_request_t *tail_ior, kal_uint32 ior_cnt, ipc_ul_queue_priority_e q_priority)
+{
+    ipc_ul_queue_t             *q;
+
+    IPC_ASSERT(head_ior && tail_ior);
+
+    q = &ipc_ul_queues_s[_IPC_GET_UL_QUEUE_INDEX(IPC_UL_QUEUE_TYPE_IOR, q_priority)];
+
+    IPC_W_LOCK_OBJECT(q, g_ul_spinlock);
+    if (q) {
+        if (q->ior_tail) {
+            q->ior_tail->io_req.next_request = head_ior;
+            q->ior_tail = (ipc_internal_ior_t *)tail_ior;
+        } else {
+            q->ior_head = (ipc_internal_ior_t *)head_ior;
+            q->ior_tail = (ipc_internal_ior_t *)tail_ior;
+        }
+
+        q->cnt += ior_cnt;
+        IPC_W_UNLOCK_OBJECT(q, g_ul_spinlock);
+    } else {
+        IPC_ASSERT(KAL_FALSE);
+    }
+}
+
+void ipc_push_meta_list_to_meta_queue(kal_uint16 start_idx, kal_uint16 end_idx, LHIF_QUEUE_TYPE q_type)
+{
+    ipc_ul_queue_priority_e     q_priority;
+    ipc_ul_queue_t             *q;
+
+    q_priority = ipc_get_queue_priority_from_lhif_queue_type(q_type);
+    q = &ipc_ul_queues_s[_IPC_GET_UL_QUEUE_INDEX(IPC_UL_QUEUE_TYPE_META, q_priority)];
+
+    IPC_W_LOCK_OBJECT(q, g_ul_spinlock);
+    if (q) {
+        IPC_ASSERT(q->meta_queue_type == q_type);
+
+        /*
+         * Since the LHIF API can't use in INIT stage,
+         * get meta_queue_size when the first uplink packet arrived.
+         */
+        if (IPC_QUEUE_META_INVALID_VALUE == q->meta_queue_size) {
+            kal_uint32     *base_addr;
+            kal_uint16      tbl_size;
+
+            IPC_QUERY_META_TABLE(&base_addr, &tbl_size, q_type);
+            q->meta_queue_size = tbl_size;
+        }
+
+        if (IPC_QUEUE_META_INVALID_VALUE == q->meta_tail) {
+            q->meta_head = start_idx;
+            q->meta_tail = end_idx;
+        } else {
+            IPC_ASSERT(start_idx == q->meta_tail);
+            q->meta_tail = end_idx;
+        }
+
+        q->cnt = (q->meta_tail >= q->meta_head)? (q->meta_tail - q->meta_head):(q->meta_queue_size - q->meta_head + q->meta_tail);
+        IPC_W_UNLOCK_OBJECT(q, g_ul_spinlock);
+    } else {
+        IPC_ASSERT(KAL_FALSE);
+    }
+}
+
+void ipc_did_enqueue_wo_filter_queue(upcm_did *did_head, upcm_did *did_tail, kal_uint32 queue_idx, ipc_data_enq_position_e position)
+{
+    ipc_dl_queue_t     *dl_queue = &(ipc_dl_queues_s[queue_idx]);
+
+    switch (position) {
+        case IPC_DATA_DID_HEAD :
+            ipc_push_did_list_to_did_queue_head(&(dl_queue->did_queues[IPC_DID_QUEUE_TYPE_WO_FILTER]), did_head, did_tail);
+            break;
+        case IPC_DATA_DID_TAIL :
+            ipc_push_did_list_to_did_queue_tail(&(dl_queue->did_queues[IPC_DID_QUEUE_TYPE_WO_FILTER]), did_head, did_tail);
+            break;
+        default :
+            IPC_ASSERT(KAL_FALSE);
+            break;
+    }
+
+    return;
+}
+
+void ipc_did_enqueue_dpfm_queue(upcm_did *did_head, upcm_did *did_tail, kal_uint32 queue_idx, ipc_data_enq_position_e position)
+{
+    ipc_dl_queue_t     *dl_queue = &(ipc_dl_queues_s[queue_idx]);
+
+    switch (position) {
+        case IPC_DATA_DID_HEAD :
+            ipc_push_did_list_to_did_queue_head(&(dl_queue->did_queues[IPC_DID_QUEUE_TYPE_DPFM]), did_head, did_tail);
+            break;
+        case IPC_DATA_DID_TAIL :
+            ipc_push_did_list_to_did_queue_tail(&(dl_queue->did_queues[IPC_DID_QUEUE_TYPE_DPFM]), did_head, did_tail);
+            break;
+        default :
+            IPC_ASSERT(KAL_FALSE);
+            break;
+    }
+
+    return;
+}
+
+void ipc_did_enqueue_default_queue(upcm_did *did_head, upcm_did *did_tail, kal_uint32 queue_idx, ipc_data_enq_position_e position)
+{
+    ipc_dl_queue_t     *dl_queue = &(ipc_dl_queues_s[queue_idx]);
+
+    switch (position) {
+        case IPC_DATA_DID_HEAD :
+            ipc_push_did_list_to_did_queue_head(&(dl_queue->did_queues[IPC_DID_QUEUE_TYPE_DEFAULT]), did_head, did_tail);
+            break;
+        case IPC_DATA_DID_TAIL :
+            ipc_push_did_list_to_did_queue_tail(&(dl_queue->did_queues[IPC_DID_QUEUE_TYPE_DEFAULT]), did_head, did_tail);
+            break;
+        default :
+            IPC_ASSERT(KAL_FALSE);
+            break;
+    }
+
+    return;
+}
+
+void ipc_did_internal_queue_dequeue(upcm_did **pp_did_head,
+                                    upcm_did **pp_did_tail,
+                                    kal_uint32 **pp_si_idx,
+                                    kal_uint8 pdn_id,
+                                    ipc_did_queue_type_e queue_type)
+{
+    kal_uint32 queue_idx = pdn_id;
+    ipc_dl_queue_t *p_dl_queue = &(ipc_dl_queues_s[queue_idx]);
+
+    if ((IPC_DID_QUEUE_TYPE_DEFAULT <= queue_type) && (IPC_DID_QUEUE_TYPE_MAX > queue_type)) {
+        *pp_did_head = p_dl_queue->did_queues[queue_type].did_head;
+        *pp_did_tail = p_dl_queue->did_queues[queue_type].did_tail;
+        *pp_si_idx = &(p_dl_queue->did_queues[queue_type].si_index);
+    }
+
+    return;
+}
+
+void ipc_on_did_downlink(kal_uint32 pdn_id, ipc_did_queue_type_e queue_type, upcm_did *did_head, upcm_did *did_tail)
+{
+    ipc_session_t          *session;
+    ipc_netif_t            *netif;
+    kal_uint8               session_type;
+
+    HIF_SWLA_START("ID1");
+
+    IPC_ASSERT(did_head && did_tail);
+
+    session = ipc_find_session_by_context(pdn_id);
+    if (session && (IPC_SESSION_STATE_LINKUP == session->state)) {
+        netif = session->netif;
+        session_type = session->type;
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        /* Send DL traffic */
+        IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+        if (netif)
+        {
+            /* Send DL traffic after DL filtering */
+            ipc_on_process_dl_did_list(session_type, netif, pdn_id, queue_type, did_head, did_tail);
+
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+            goto done;
+        } else
+        {
+            kal_uint8   ip_id = 0xff;
+
+            IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+            if (session)
+            {
+                ip_id = (kal_uint8)session->ip_id;
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            }
+            hif_trace_error(IPC_TR_DL_DID_DROP_FOR_NETIF_INFO_LOCK_FAIL, pdn_id, ip_id, session_type, did_head, did_tail);
+            goto drop;
+        }
+    } else {
+        if(session){
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+        }
+        hif_trace_error(IPC_TR_DL_DID_DROP_FOR_INVALID_SESSION, pdn_id, did_head, did_tail);
+        goto drop;
+    }
+
+drop:
+    ipc_filter_did_drop_pkt_handler(pdn_id, did_head, did_tail);
+    IPC_FREE_DID_W_DATABUF(did_head, did_tail, IPC_SI_HIF_TYPE_MAX);
+done:
+    HIF_SWLA_STOP("ID1");
+    return;
+}
+
+void ipc_data_qbm_downlink_dequeue(void)
+{
+    qbm_gpd *head = NULL, *tail = NULL, *prev_head = NULL, *nxt_head = NULL;
+    ipc_pkt_t pkt = {0};
+    ipc_dlq_ior_t *ior = NULL;
+    kal_uint32 netif_id = IPC_INVALID_NETIF_ID, session_type = IPC_IP_TYPE_INVALID;
+    ipc_netif_t *netif = NULL;
+    ipc_session_t *session = NULL;
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    head = ipc_dl_qbm_head_s;
+    tail = ipc_dl_qbm_tail_s;
+    ipc_dl_qbm_head_s = NULL;
+    ipc_dl_qbm_tail_s = NULL;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    pkt.buf_type = IPC_PKT_DES_TYPE_GPD;
+    pkt.head = head;
+    prev_head = head;
+    if (head == NULL) {
+        return;
+    }
+    QBM_DES_SET_NEXT(tail, NULL);
+    while (head != NULL) {
+        pkt.tail = prev_head;
+        nxt_head = QBM_DES_GET_NEXT(head);
+        ior = (ipc_dlq_ior_t *)QBM_DES_GET_SW_CTRL_FIELD(head);
+
+        if (netif_id != ior->netif_id || session_type != ior->session_type) {
+            kal_bool update_head = (head == pkt.head);
+
+            netif = ipc_find_netif(ior->netif_id);
+            if (netif == NULL) {
+                /* Drop packet & don't update state */
+                qbm_free_one(head);
+                if (!update_head) {
+                    QBM_DES_SET_NEXT(prev_head, nxt_head);
+                }
+                head = nxt_head;
+                if (update_head) {
+                    pkt.head = head;
+                    prev_head = head;
+                }
+                continue;
+            }
+            session = ipc_find_session_by_netif(netif, ior->session_type);
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+            if (session == NULL || IPC_SESSION_STATE_LINKUP != session->state) {
+                if(session) {
+                    IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                }
+                /* Drop packet */
+                qbm_free_one(head);
+                if (!update_head) {
+                    QBM_DES_SET_NEXT(prev_head, nxt_head);
+                }
+                head = nxt_head;
+                if (update_head) {
+                    pkt.head = head;
+                    prev_head = head;
+                }
+                continue;
+            }
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+            if (netif_id != IPC_INVALID_NETIF_ID) {
+                if (ipc_send_dl_pkt_in_did(&pkt, NULL, netif_id) != KAL_TRUE) {
+                    hif_trace_error(IPC_TR_DL_PKT_NETIF_DID_ALLOC_DID_NG, pkt.head, pkt.tail, netif_id);
+                }
+                pkt.head = head;
+            }
+            netif_id = ior->netif_id;
+            session_type = ior->session_type;
+        }
+        prev_head = head;
+        head = nxt_head;
+    }
+    if (pkt.head != NULL) {
+        pkt.tail = prev_head;
+        ipc_send_dl_pkt_in_did(&pkt, NULL, netif_id);
+    }
+    
+}
+
+void ipc_on_downlink_qbm_enqueue(qbm_gpd *head, qbm_gpd *tail)
+{
+    kal_bool to_send_msg;
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    if (ipc_dl_qbm_head_s == NULL) {
+        ipc_dl_qbm_head_s = head;
+        ipc_dl_qbm_tail_s = tail;
+    } else {
+        QBM_DES_SET_NEXT(ipc_dl_qbm_tail_s, head);
+        ipc_dl_qbm_tail_s = tail;
+    }
+    QBM_DES_SET_NEXT(ipc_dl_qbm_tail_s, NULL);
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    to_send_msg = ipc_data_check_and_set_dl_ilm_flag();
+
+    if (to_send_msg) {
+        msg_send6(  kal_get_active_module_id(), /* src_mod_id */
+                    MOD_IPCORE, /* dest_mod_id */
+                    IPCORE_DATAPATH_SAP, /* sap_id */
+                    MSG_ID_IPCORE_PROCESS_DL_QUEUE_REQ, /* msg_id */
+                    NULL, /* local_para_ptr */
+                    NULL); /* peer_buff_ptr */
+    }
+}
+
+void ipc_on_did_downlink_multiple_ps(kal_uint32 pdn_id, upcm_did *did_head, upcm_did *did_tail, kal_uint8 proto_idx)
+{
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, proto_idx);
+    ipc_did_downlink_enqueue(pdn_id, did_head, did_tail);
+}
+
+void ipc_on_did_downlink_test_mode(kal_uint32 pdn_id, upcm_did *did_head, upcm_did *did_tail, kal_uint8 proto_idx)
+{
+    upcm_did           *did;
+    upcm_did           *next_did;
+    kal_bool            end_of_list;
+    kal_bool            to_send_msg;
+
+    IPC_ASSERT(did_head && did_tail);
+
+    hif_data_trace(MD_TRC_IPC_DL_ON_DID_DOWNLINK_TEST_LOOPBACK, pdn_id, did_head, did_tail, ipc_test_loopback_mode_s);
+
+    end_of_list = KAL_FALSE;
+    for (did = did_head; did && !end_of_list; did = next_did) {
+        next_did = UPCM_DID_GET_NEXT(did);
+        end_of_list = (did == did_tail);
+
+        if (IPC_TEST_LOOPBACK_MODE_A == ipc_test_loopback_mode_s) {
+            UPCM_DID_SET_SW_CTRL_FIELD(did, ipc_test_loopback_a_netif_id_s);
+        } else {
+            UPCM_DID_SET_FLOW(did, pdn_id);
+            UPCM_DID_SET_SW_CTRL_FIELD(did, ipc_test_loopback_b_netif_id_s);
+        }
+    }
+
+    /* Enqueue DID to DID queue, We have to protect IPC_DL_NON_PDN_QUEUE_IDX queue, it may enq by other context */
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    ipc_did_enqueue_wo_filter_queue(did_head, did_tail, IPC_DL_NON_PDN_QUEUE_IDX, IPC_DATA_DID_TAIL);
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    /* Send ILM to IPCore for processing DL queue */
+    to_send_msg = ipc_data_check_and_set_dl_ilm_flag();
+
+    /*
+     * Switch to IPCORE context.
+     */
+    if (to_send_msg) {
+        msg_send6(  kal_get_active_module_id(), /* src_mod_id */
+                    MOD_IPCORE, /* dest_mod_id */
+                    IPCORE_DATAPATH_SAP, /* sap_id */
+                    MSG_ID_IPCORE_PROCESS_DL_QUEUE_REQ, /* msg_id */
+                    NULL, /* local_para_ptr */
+                    NULL); /* peer_buff_ptr */
+    }
+}
+
+void ipc_did_downlink_enqueue(kal_uint32 pdn_id, upcm_did *did_head, upcm_did *did_tail)
+{
+    ipc_dl_queue_t         *dl_queue;
+    kal_bool                to_send_msg;
+
+    /* For 95 log reduction, we disable the following log temporarily */
+    //hif_data_trace(MD_TRC_IPC_DL_ON_DID_DOWNLINK, pdn_id, did_head, did_tail);
+
+    dl_queue = &ipc_dl_queues_s[pdn_id];
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    ipc_push_did_list_to_did_queue_tail(&(dl_queue->did_queues[IPC_DID_QUEUE_TYPE_DEFAULT]), did_head, did_tail);
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    /* Send ILM to IPCore for processing DL queue */
+    to_send_msg = ipc_data_check_and_set_dl_ilm_flag();
+
+    if (to_send_msg) {
+        msg_send6(  kal_get_active_module_id(), /* src_mod_id */
+                    MOD_IPCORE, /* dest_mod_id */
+                    IPCORE_DATAPATH_SAP, /* sap_id */
+                    MSG_ID_IPCORE_PROCESS_DL_QUEUE_REQ, /* msg_id */
+                    NULL, /* local_para_ptr */
+                    NULL); /* peer_buff_ptr */
+    }
+}
+
+void ipc_did_downlink_dequeue()
+{
+    kal_uint32              pdn_id;
+    ipc_did_queue_type_e    queue_type;
+    upcm_did               *did_head;
+    upcm_did               *did_tail;
+    ipc_dl_queue_t         *dl_queue;
+
+    /* In test mode, there is a reqirement that UE shall loopback UL packet in time,
+     * so we will skip these process to enhance the latency.
+     * We expect that there is no packets in normal queue when test mode is enabled.
+     */
+    if(IPC_TEST_LOOPBACK_MODE_OFF == ipc_test_loopback_mode_s){
+        for (pdn_id = 0; pdn_id < IPC_MAX_SESSION_CNT; pdn_id++) {
+            for (queue_type = 0; queue_type < IPC_DID_QUEUE_TYPE_MAX; queue_type++) {
+                dl_queue = &(ipc_dl_queues_s[pdn_id]);
+
+                IPC_SPIN_LOCK(ipc_spinlock_g);
+                did_head = dl_queue->did_queues[queue_type].did_head;
+                did_tail = dl_queue->did_queues[queue_type].did_tail;
+                ipc_clear_did_queue(&(dl_queue->did_queues[queue_type]));
+                IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+                if (did_head) {
+                    ipc_on_did_downlink(pdn_id, queue_type, did_head, did_tail);
+                }
+            }
+        }
+    }
+
+    /*
+     * Dequeue the "send_dl" did_queue.
+     * Note that only IPC_DID_QUEUE_TYPE_WO_FILTER queue should be used.
+     * We have to protect IPC_DL_NON_PDN_QUEUE_IDX queue, it may enq by other context
+     */
+    for (queue_type = IPC_DID_QUEUE_TYPE_WO_FILTER; queue_type <= IPC_DID_QUEUE_TYPE_USB_PATH; queue_type++) {
+        IPC_SPIN_LOCK(ipc_spinlock_g);
+        dl_queue = &(ipc_dl_queues_s[IPC_DL_NON_PDN_QUEUE_IDX]);
+        did_head = dl_queue->did_queues[queue_type].did_head;
+        did_tail = dl_queue->did_queues[queue_type].did_tail;
+        /* Clear Q before processing it */
+        ipc_clear_did_queue(&(dl_queue->did_queues[queue_type]));
+        IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+        if (did_head) {
+            ipc_pkt_t   pkt;
+            upcm_did   *did;
+            upcm_did   *next_did;
+            kal_bool    end_of_list;
+
+            end_of_list = KAL_FALSE;
+            for (did = did_head; did && !end_of_list; did = next_did) {
+                next_did = UPCM_DID_GET_NEXT(did);
+                end_of_list = (did == did_tail);
+
+                if ( (end_of_list) ||
+                     (UPCM_DID_GET_SW_CTRL_FIELD(did_head) != UPCM_DID_GET_SW_CTRL_FIELD(next_did)) ) {
+                    pkt.buf_type = IPC_PKT_DES_TYPE_DID;
+                    pkt.did_head = did_head;
+                    pkt.did_tail = did;
+
+                    ipc_send_dl_pkt_in_did_internal(&pkt, NULL, UPCM_DID_GET_SW_CTRL_FIELD(did_head));
+
+                    did_head = next_did;
+                }
+            }
+        }
+    }
+}
+
+void ipc_data_drop_ul_meta_by_pdn(kal_uint8 pdn_id)
+{
+    kal_uint32 pkt_count = 0;
+    kal_uint32 start_idx = 0;
+    kal_uint32 read_idx = 0;
+    kal_uint32 end_idx = 0;
+    ipc_ul_queue_t *q;
+    lhif_meta_tbl_t *meta_tbl;
+    lhif_meta_tbl_t *meta;
+    kal_uint16 tbl_size = 0;
+    LHIF_QUEUE_TYPE meta_queue_type;
+    kal_uint8 pdn_id_from_meta;
+    kal_uint8 i;
+    kal_bool is_queue_active = KAL_FALSE;
+
+
+    for (i = 0; i < IPC_UL_QUEUE_NUM; i++) {
+
+        q = &ipc_ul_queues_s[i];
+
+        /* Skip IOR queue */
+        if(q->queue_type == IPC_UL_QUEUE_TYPE_IOR){
+            continue;
+        }
+
+        /* Get queue's info snapshot */
+        IPC_SPIN_LOCK(ipc_spinlock_g);
+        pkt_count = q->cnt;
+        start_idx = q->meta_head;
+        end_idx = q->meta_tail;
+        meta_queue_type = q->meta_queue_type;
+        is_queue_active = ipc_is_ul_queue_allowed_to_send(q);
+        IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+        /* We only search the queue which is inactive */
+        if(!is_queue_active && pkt_count){
+            IPC_QUERY_META_TABLE((kal_uint32 **)&meta_tbl, &tbl_size, meta_queue_type);
+            read_idx = start_idx;
+            do{
+                meta = &meta_tbl[read_idx];
+                pdn_id_from_meta = IPC_MASK_PROTOID_ON_PDNID(meta->pdn, meta->protocol_idx);
+
+                if(pdn_id == pdn_id_from_meta){
+                    /*
+                     * Set net_type to IGNORE if the corresponding PDN is unbinding
+                     * The buffer will be released when IPCore process the UL meta
+                     */
+                    meta->net_type = LHIF_NET_TYPE_IGNORE;
+                    hif_trace_info(IPC_TR_UNBIND_DROP_UL_META, pdn_id, read_idx, pdn_id_from_meta);
+                }
+
+                read_idx++;
+                if(read_idx == tbl_size){
+                    read_idx = 0;
+                }
+            }while(read_idx != end_idx);
+        }
+    }
+    return;
+}
+
+void ipc_data_clear_dl_ilm_flag()
+{
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    ipc_dl_processing_s = KAL_FALSE;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+}
+
+void ipc_data_set_dl_ilm_flag()
+{
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    ipc_dl_processing_s = KAL_TRUE;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+}
+
+kal_bool ipc_data_check_and_set_dl_ilm_flag()
+{
+    kal_bool to_send_msg = KAL_FALSE;
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    to_send_msg = (!ipc_dl_processing_s);
+    ipc_dl_processing_s = KAL_TRUE;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    return to_send_msg;
+}
+
+#if defined(__MD97__)
+kal_bool ipc_data_set_rq_info(ipc_rq_info_t *p_rq_info, kal_uint32 pdn_id, ipc_pkt_des_t *p_pkt_info, ipc_data_src_qfi_e src_qfi)
+{
+    upcm_did_si *p_sit = NULL;
+
+    if (NULL == p_rq_info || NULL == p_pkt_info) {
+        hif_trace_error(IPC_TR_INVALID_RQ_INFO_PKT_DES);
+        return KAL_FALSE;
+    }
+
+    if (KAL_FALSE == p_pkt_info->is_packet_info) {
+        hif_trace_error(IPC_TR_NO_PKT_INFO, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    p_rq_info->psi = UPCM_FIVEG_PDN_ID_TO_PSI(pdn_id);
+
+    if (p_pkt_info->packet_info->info_valid_fields & IPC_FILTER_BY_PROTOCOL) {
+        p_rq_info->protocol = p_pkt_info->packet_info->protocol;
+
+        if ((IPC_HDR_PROT_ESP == p_rq_info->protocol) &&
+            (p_pkt_info->packet_info->info_valid_fields & IPC_FILTER_BY_SPI)) {
+            p_rq_info->spi = p_pkt_info->packet_info->spi;
+        }
+    } else {
+        hif_trace_info(IPC_TR_SET_RQ_INFO_FAILED_PROTOCOL);
+        return KAL_FALSE;
+    }
+
+    if ((p_pkt_info->packet_info->info_valid_fields & IPC_FILTER_BY_SRC_IPV4) &&
+        (p_pkt_info->packet_info->info_valid_fields & IPC_FILTER_BY_DST_IPV4)) {
+
+        kal_mem_cpy(&p_rq_info->dst_ipv4.addr32, &p_pkt_info->packet_info->dst_addr[0], sizeof(kal_uint32));
+        kal_mem_cpy(&p_rq_info->src_ipv4.addr32, &p_pkt_info->packet_info->src_addr[0], sizeof(kal_uint32));
+        p_rq_info->valid_field = IPC_RQ_INFO_3_TUPLE;
+        p_rq_info->is_ipv4 = KAL_TRUE;
+
+    } else if((p_pkt_info->packet_info->info_valid_fields & IPC_FILTER_BY_SRC_IPV6) &&
+              (p_pkt_info->packet_info->info_valid_fields & IPC_FILTER_BY_DST_IPV6)){
+
+        kal_mem_cpy(&p_rq_info->dst_ipv6.addr32[0], &p_pkt_info->packet_info->dst_addr[0], 4*sizeof(kal_uint32));
+        kal_mem_cpy(&p_rq_info->src_ipv6.addr32[0], &p_pkt_info->packet_info->src_addr[0], 4*sizeof(kal_uint32));
+        p_rq_info->valid_field = IPC_RQ_INFO_3_TUPLE;
+        p_rq_info->is_ipv4 = KAL_FALSE;
+
+    } else {
+        hif_trace_info(IPC_TR_SET_RQ_INFO_FAILED_IP);
+        return KAL_FALSE;
+    }
+
+    switch (src_qfi) {
+        case IPC_DATA_QFI_SRC_IPF_META :
+            p_rq_info->qfi = IPC_DATA_GET_QFI(((ipf_dl_meta *)p_pkt_info->ipf_meta)->tcp_flag);
+            break;
+        case IPC_DATA_QFI_SRC_DL_DID :
+            p_sit = UPCM_DID_GET_SIT_PTR(p_pkt_info->did);
+            p_rq_info->qfi = p_sit->qfi;
+            break;
+        default :
+            hif_trace_info(IPC_TR_SET_RQ_INFO_FAILED_QFI);
+            return KAL_FALSE;
+    }
+
+    if ((p_pkt_info->packet_info->info_valid_fields & IPC_FILTER_BY_SRC_PORT) &&
+        (p_pkt_info->packet_info->info_valid_fields & IPC_FILTER_BY_DST_PORT)) {
+
+        p_rq_info->dst_port = p_pkt_info->packet_info->dst_port;
+        p_rq_info->src_port = p_pkt_info->packet_info->src_port;
+        p_rq_info->valid_field = IPC_RQ_INFO_5_TUPLE;
+    }
+
+    return KAL_TRUE;
+}
+
+void ipc_data_saved_rq_info_list(ipc_data_rq_info_list *p_rq_list, ipc_rq_info_t *p_rq_info)
+{
+    kal_uint32 i = 0;
+    kal_bool is_matched = KAL_FALSE;
+
+    if (NULL == p_rq_list || NULL == p_rq_info) {
+        hif_trace_error(IPC_TR_INVALID_RQ_LIST_INFO);
+        return;
+    }
+
+    for (i = 0; i < p_rq_list->cnt; i++) {
+        if ((p_rq_list->rq_info_list[i].protocol == p_rq_info->protocol) &&
+            (p_rq_list->rq_info_list[i].is_ipv4 == p_rq_info->is_ipv4) &&
+            (p_rq_list->rq_info_list[i].valid_field == p_rq_info->valid_field) &&
+            (p_rq_list->rq_info_list[i].qfi == p_rq_info->qfi)) {
+
+            if (IPC_RQ_INFO_5_TUPLE == p_rq_info->valid_field) {
+                if (p_rq_info->is_ipv4) {
+                    if ((0 == kal_mem_cmp(&p_rq_list->rq_info_list[i].dst_ipv4.addr32, &p_rq_info->dst_ipv4.addr32, 4)) &&
+                        (0 == kal_mem_cmp(&p_rq_list->rq_info_list[i].src_ipv4.addr32, &p_rq_info->src_ipv4.addr32, 4)) &&
+                        (p_rq_list->rq_info_list[i].dst_port == p_rq_info->dst_port) &&
+                        (p_rq_list->rq_info_list[i].src_port == p_rq_info->src_port)) {
+                        is_matched = KAL_TRUE;
+                    }
+                } else {
+                    if ((0 == kal_mem_cmp(p_rq_list->rq_info_list[i].dst_ipv6.addr32, p_rq_info->dst_ipv6.addr32, 16)) &&
+                        (0 == kal_mem_cmp(p_rq_list->rq_info_list[i].src_ipv6.addr32, p_rq_info->src_ipv6.addr32, 16)) &&
+                        (p_rq_list->rq_info_list[i].dst_port == p_rq_info->dst_port) &&
+                        (p_rq_list->rq_info_list[i].src_port == p_rq_info->src_port)) {
+                        is_matched = KAL_TRUE;
+                    }
+                }
+            } else {
+                if (p_rq_info->is_ipv4) {
+                    if ((0 == kal_mem_cmp(&p_rq_list->rq_info_list[i].dst_ipv4.addr32, &p_rq_info->dst_ipv4.addr32, 4)) &&
+                        (0 == kal_mem_cmp(&p_rq_list->rq_info_list[i].src_ipv4.addr32, &p_rq_info->src_ipv4.addr32, 4))) {
+                        is_matched = KAL_TRUE;
+                    }
+                } else {
+                    if ((0 == kal_mem_cmp(p_rq_list->rq_info_list[i].dst_ipv6.addr32, p_rq_info->dst_ipv6.addr32, 16)) &&
+                        (0 == kal_mem_cmp(p_rq_list->rq_info_list[i].src_ipv6.addr32, p_rq_info->src_ipv6.addr32, 16))) {
+                        is_matched = KAL_TRUE;
+                    }
+                }
+
+                if (IPC_HDR_PROT_ESP == p_rq_info->protocol) {
+                    if (p_rq_list->rq_info_list[i].spi == p_rq_info->spi) {
+                        is_matched = KAL_TRUE;
+                    }
+                }
+            }
+        }
+    }
+
+    if (!is_matched || 0 == p_rq_list->cnt) {
+        kal_mem_cpy(&p_rq_list->rq_info_list[p_rq_list->cnt], p_rq_info, sizeof(ipc_rq_info_t));
+        p_rq_list->cnt++;
+    }
+
+    return;
+}
+
+void ipc_data_dl_enq_by_netif(kal_uint32 netif_id, upcm_did *p_did_head, upcm_did *p_did_tail)
+{
+    ipc_dl_queue_t *p_dl_queue = NULL;
+    kal_bool is_send_msg = KAL_FALSE;
+    kal_bool end_of_list = KAL_FALSE;
+    upcm_did *p_current_did = NULL;
+    upcm_did *p_next_did = NULL;
+
+    ASSERT((NULL != p_did_head) && (NULL != p_did_head));
+    hif_data_trace(MD_TRC_IPC_DL_ENQ_BY_NETIF, p_did_head, p_did_tail, netif_id);
+
+    /* Save netif_id in SW_CTRL_FIELD */
+    for (p_current_did = p_did_head; p_current_did && !end_of_list; p_current_did = p_next_did) {
+        p_next_did = UPCM_DID_GET_NEXT(p_current_did);
+        end_of_list = (p_current_did == p_did_tail);
+        UPCM_DID_SET_SW_CTRL_FIELD(p_current_did, (kal_uint16)(netif_id & 0x0000FFFF));
+    }
+
+    /* enqueue DL without filter queue */
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    p_dl_queue = &ipc_dl_queues_s[IPC_DL_NON_PDN_QUEUE_IDX];
+    ipc_push_did_list_to_did_queue_tail(&(p_dl_queue->did_queues[IPC_DID_QUEUE_TYPE_WO_FILTER]), p_did_head, p_did_tail);
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    /* Send ILM to IPCore for processing DL queue */
+    is_send_msg = ipc_data_check_and_set_dl_ilm_flag();
+
+    /* Send ILM to IPCore for processing DL queue */
+    if (is_send_msg) {
+        msg_send6(kal_get_active_module_id(),         /* src_mod_id */
+                  MOD_IPCORE,                         /* dest_mod_id */
+                  IPCORE_DATAPATH_SAP,                /* sap_id */
+                  MSG_ID_IPCORE_PROCESS_DL_QUEUE_REQ, /* msg_id */
+                  NULL,  /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+    }
+
+    return;
+}
+
+kal_bool ipc_data_send_rq_info(ipc_data_rq_info_list *p_rq_list)
+{
+    if (NULL == p_rq_list) {
+        hif_trace_error(IPC_TR_INVALID_RQ_LIST, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    if (p_rq_list->cnt) {
+        peer_buff_struct *p_peer = construct_peer_buff(p_rq_list->cnt*sizeof(ipc_rq_info_t) + 4, 0, 0,TD_RESET);
+        ipc_rq_info_t *p_rq_info = NULL;
+        kal_uint32 i = 0;
+        kal_uint16 peer_buf_len = 0;
+
+        if (NULL == p_peer) {
+            hif_trace_error(IPC_TR_ALLOC_PEER_BUF_FAILED, __FUNCTION__);
+            return KAL_FALSE;
+        }
+
+        p_rq_info = (ipc_rq_info_t *)get_peer_buff_pdu(p_peer, &peer_buf_len);
+        for (i = 0; i < p_rq_list->cnt; i++) {
+            kal_mem_cpy(p_rq_info, &p_rq_list->rq_info_list[i], sizeof(ipc_rq_info_t));
+            p_rq_info++;
+        }
+
+        msg_send6(IPCORE_SRC_MOD, NAS_DST_MOD, IPCORE_SAP, MSG_ID_IPCORE_NAS_RQ_INFO_IND, NULL, (peer_buff_struct *)p_peer);
+    }
+
+    return KAL_TRUE;
+}
+#endif
+
+void ipc_data_ipv6_ra_pool_push(kal_uint32 pdn_id, qbm_gpd* gpd)
+{
+    qbm_gpd* old_gpd = NULL;
+
+    IPC_ASSERT(pdn_id < IPC_PROXY_IPV6_RA_POOL_SIZE);
+
+    old_gpd = ipc_proxy_ipv6_ra_pool[pdn_id];
+
+    if(old_gpd) {
+        qbmt_dest_q(old_gpd, old_gpd);
+    }
+
+    ipc_proxy_ipv6_ra_pool[pdn_id] = gpd;
+}
+
+qbm_gpd* ipc_data_ipv6_ra_pool_pop(kal_uint32 pdn_id)
+{
+    qbm_gpd* gpd = NULL;
+
+    IPC_ASSERT(pdn_id < IPC_PROXY_IPV6_RA_POOL_SIZE);
+
+    gpd = ipc_proxy_ipv6_ra_pool[pdn_id];
+    ipc_proxy_ipv6_ra_pool[pdn_id] = NULL;
+
+    return gpd;
+}
+
+kal_bool ipc_set_data_usage_by_pdn_sim_id(ipc_data_path_direction_e data_path_direct,
+                                                    kal_uint32 pdn_sim_id,
+                                                    ipc_data_usage_info_t* data_usage)
+{
+    if (pdn_sim_id != IPC_INVALID_PDN_ID) {
+        IPC_ASSERT(pdn_sim_id < IPC_MAX_SESSION_CNT);
+
+        if (DL_DIRECT != data_path_direct && UL_DIRECT != data_path_direct) {
+            hif_trace_error(IPC_TR_INVALID_DATA_PATH_DIR, __FUNCTION__, data_path_direct);
+            return KAL_FALSE;
+        }
+        if (DL_DIRECT == data_path_direct) {
+            ipc_data_usage_info_s[pdn_sim_id].downlink_bytes += data_usage->downlink_bytes;
+            ipc_data_usage_info_s[pdn_sim_id].downlink_packets += data_usage->downlink_packets;
+        } else {
+            ipc_data_usage_info_s[pdn_sim_id].uplink_bytes += data_usage->uplink_bytes;
+            ipc_data_usage_info_s[pdn_sim_id].uplink_packets += data_usage->uplink_packets;
+        }
+ 
+        return KAL_TRUE;
+    } else {
+        hif_trace_error(IPC_TR_INVALID_PDN_ID, __FUNCTION__);
+        return KAL_FALSE;
+    }
+}
+
+kal_bool ipc_set_data_usage_by_netif_id(ipc_data_path_direction_e data_path_direct,
+                                                kal_uint8 ip_type,
+                                                kal_uint32 netif_id,
+                                                ipc_data_usage_info_t *data_usage)
+{
+    kal_int32 pdn_sim_id;
+
+    if (KAL_FALSE == ipc_query_pdn_by_netif(netif_id, ip_type, &pdn_sim_id)) {
+        hif_trace_error(IPC_TR_GET_PDN_ID_FAILED, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    return ipc_set_data_usage_by_pdn_sim_id(data_path_direct, pdn_sim_id, data_usage);
+}
+
+ipc_data_usage_info_t* ipc_get_data_usage_by_pdn_sim_id(kal_uint32 pdn_sim_id)
+{
+    ipc_data_usage_info_t* data_usage = NULL;
+    if (pdn_sim_id != IPC_INVALID_PDN_ID) {
+        IPC_ASSERT(pdn_sim_id < IPC_MAX_SESSION_CNT);
+        data_usage = &ipc_data_usage_info_s[pdn_sim_id];
+        hif_trace_debug(IPC_TR_DATA_USAGE_INFO, __FUNCTION__, pdn_sim_id, data_usage->uplink_bytes, data_usage->downlink_bytes,
+                                                             data_usage->uplink_packets, data_usage->downlink_packets);
+        return data_usage;
+    } else {
+        hif_trace_error(IPC_TR_INVALID_PDN_ID, __FUNCTION__);
+        return NULL;
+    }
+}
+
+void ipc_reset_data_usage_by_pdn_sim_id(kal_uint8 pdn_sim_id)
+{
+    hif_trace_debug(IPC_TR_DATA_USAGE_RESET, __FUNCTION__, pdn_sim_id);
+    memset(&ipc_data_usage_info_s[pdn_sim_id], 0, sizeof(ipc_data_usage_info_t));
+}
diff --git a/mcu/middleware/hif/ipcore/src/ipc_data_ipf.c b/mcu/middleware/hif/ipcore/src/ipc_data_ipf.c
new file mode 100644
index 0000000..cd98ed4
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_data_ipf.c
@@ -0,0 +1,1321 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2016
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_hpc.c
+ *
+ * Project:
+ * --------
+ *   UMOLYA
+ *
+ * Description:
+ * ------------
+ *   IP Core Uplink data path functions related with HPC.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "mw_sap.h"
+#include "hif_mw_msgid.h"
+#include "qmu_bm_util.h"
+#include "cache_sw.h"
+
+#include "ipc_defs.h"
+#include "ipc_debug.h"
+#include "ipc_utils.h"
+#include "ipc_data_ipf.h"
+#include "ipc_object.h"
+#include "ipc_filter.h"
+#include "ipc_dpfm.h"
+#include "dpcopro_custom.h"
+#include "hif_lhif.h"
+#include "sim_public_enum.h"
+#include "el2_public_api.h"
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Private data structure.
+ *----------------------------------------------------------------------------*/
+
+typedef struct ipc_unk_hdr_stats_t {
+    kal_bool   is_valid;
+    kal_uint32 unk_hdr_cnt;
+    kal_uint16 begin_cntl;
+    kal_uint16 end_cntl;
+    kal_uint16 rb_idx;
+    kal_uint16 protocol_idx;
+} ipc_unk_hdr_stats_t;
+
+#define MAX_SIM_RBIDX_NUM 37
+#define MAX_RBIDX_NUM     (MAX_SIM_RBIDX_NUM * MAX_SIM_NUM)
+
+/*------------------------------------------------------------------------------
+ * Private variables.
+ *----------------------------------------------------------------------------*/
+static ipc_hpc_info_tbl_t ipc_hpc_tbl[IPC_HPC_ENTRY_SIZE];
+static ipc_dl_meta_queue_t ipc_dl_meta_queues_s[IPC_DL_META_QUEUE_NUM];
+#if defined(__MD97__)
+    static ipc_data_rq_info_list g_rq_list = {0};
+#endif
+static kal_uint8 g_ipc_qbm_failed_gpd_cnt = 0;
+static ipc_unk_hdr_stats_t g_unk_hdr_stat[MAX_RBIDX_NUM] = {0};
+
+/*------------------------------------------------------------------------------
+ * Private functions.
+ *----------------------------------------------------------------------------*/
+static LHIF_NET_TYPE ipc_get_net_type_from_netif_id(kal_uint32 netif_id)
+{
+
+    IPC_ASSERT(IPC_INVALID_NETIF_ID != netif_id);
+
+    switch (netif_id & 0xFFFFFF00) {
+        case IPC_NETIF_ID_LHIF_BEGIN:
+            return LHIF_NET_TYPE_LHIF;
+        case IPC_NETIF_ID_ETH_BEGIN:
+            return LHIF_NET_TYPE_RNDIS;
+        case IPC_NETIF_ID_MCIF_BEGIN:
+            return LHIF_NET_TYPE_MCIF;
+        case IPC_NETIF_ID_VNIF_BEGIN:
+            return LHIF_NET_TYPE_VNIF;
+        case IPC_NETIF_ID_MBIM_BEGIN:
+            return LHIF_NET_TYPE_MBIM;
+        default:
+            /*can't reach here*/
+            IPC_ASSERT(KAL_FALSE);
+            return LHIF_NET_TYPE_IGNORE;
+    }
+}
+
+/*------------------------------------------------------------------------------
+ * Public functions.
+ *----------------------------------------------------------------------------*/
+
+void ipc_check_and_fill_session_info(kal_uint8 ip_type, kal_uint32 ipv4_pdn_id, kal_uint32 ipv6_pdn_id, kal_uint32 netif_id, lhif_meta_tbl_t *meta)
+{
+    kal_uint8 pdn_id_from_meta = IPC_MASK_PROTOID_ON_PDNID(meta->pdn, meta->protocol_idx) ;
+    kal_uint32 pdn_id = (IPC_IP_TYPE_IPV4 == ip_type) ? ipv4_pdn_id : ipv6_pdn_id;
+
+    if (IPC_INVALID_PDN_ID != pdn_id)
+    {
+        if((IPC_UL_META_INVALID_PDN_SIM_ID == pdn_id_from_meta) && !meta->ignore)
+        {
+            IPC_RETRIEVE_PROTOID_FROM_PDNID(pdn_id, meta->protocol_idx);
+            IPC_UNMASK_PROTOID_FROM_PDNID(pdn_id);
+            meta->pdn = pdn_id;
+        }
+        else
+        {
+            /* IPF has filled the PDN_SIM_ID from pn match, just confirm if the value is same as IPcore. */
+            if(!meta->ignore && (pdn_id_from_meta != pdn_id))
+            {
+                hif_data_trace(MD_TRC_IPC_UL_META_PN_MISS_MATCH, netif_id, ip_type, pdn_id, pdn_id_from_meta);
+                /* restore IPCore PDN info to meta */
+                IPC_RETRIEVE_PROTOID_FROM_PDNID(pdn_id, meta->protocol_idx);
+                IPC_UNMASK_PROTOID_FROM_PDNID(pdn_id);
+                meta->pdn = pdn_id;
+                /* Clear HPC mr because HW/SW may unsync */
+                meta->mr = IPC_HPC_MR_UNKNOWN;
+            }
+        }
+    }
+    else
+    {
+        hif_trace_error(IPC_TR_META_UL_DROP_FOR_SESSION_DEACT, netif_id, meta, ip_type);
+        meta->ignore = 1;
+        IPC_FREE_META_VRB(meta);
+    }
+}
+
+kal_uint16 ipc_on_process_ul_hpc_result(kal_uint8 *ip_type, kal_uint32 meta_idx, lhif_meta_tbl_t *meta, kal_uint32 netif_id, ipc_dpfm_mirror_des_t *dpfm_mirror_des)
+{
+    kal_uint16 result = 0;
+    ipc_pkt_des_t packet_des = {0};
+    ipc_filter_t *filter = NULL;
+    /*
+     * In order to reduce MCPS, we would not do initialization for these two variables.
+     * Make sure all elements are assigned correct value before using them.
+     */
+    ipc_filter_info_t filter_info;
+    ipc_packet_info_t packet_info;
+
+    *ip_type = (meta->ip)?IPC_IP_TYPE_IPV6 : IPC_IP_TYPE_IPV4;
+    switch(meta->mr)
+    {
+        case IPC_HPC_MR_NEW:
+        case IPC_HPC_MR_UNKNOWN:
+        case IPC_HPC_MR_DPFM_MATCH:
+        case IPC_HPC_MR_MATCH:
+            {
+                if(IPC_HPC_MR_UNKNOWN == meta->mr) {
+                    /* If the packet is unknown, we need to get correct packet info from raw buffer */
+                    *ip_type = ipc_get_ip_type_from_meta(meta);
+                }
+
+                if (IPC_IP_TYPE_INVALID != *ip_type){
+                    /* Fill packet_des */
+                    if (IPC_HPC_MR_UNKNOWN != meta->mr){
+                        /* If MR == HPC_MR_NEW or IPC_HPC_MR_MATCH or IPC_HPC_MR_DPFM_MATCH, we store or get pacekt_info from HPC table */
+                        packet_des.packet_info = &(ipc_hpc_tbl[meta->match_index].packet_info);
+                    }else{
+                        packet_des.packet_info = &packet_info;
+                    }
+
+                    if(IPC_HPC_MR_NEW == meta->mr || IPC_HPC_MR_UNKNOWN == meta->mr || ipc_hpc_tbl[meta->match_index].is_dirty){
+                        /*
+                         * Reset packet info for HPC_NEW/UNKNOWN cases.
+                         * If dirty flag is set, we also need to re-parse packet info to prevent using out-of-date info.
+                         */
+                        kal_mem_set(packet_des.packet_info, 0, sizeof(ipc_packet_info_t));
+                        packet_des.is_packet_info = KAL_FALSE;
+                        if(KAL_TRUE == ipc_hpc_tbl[meta->match_index].is_dirty){
+                            ipc_hpc_tbl[meta->match_index].is_dirty = KAL_FALSE;
+                        }
+                    }else{
+                        packet_des.is_packet_info = KAL_TRUE;
+                        if(IPC_HPC_MR_MATCH == meta->mr){
+                            /* update latest TCP flags from meta */
+                            if((packet_des.packet_info->info_valid_fields & IPC_FILTER_BY_PROTOCOL) &&
+                                (packet_des.packet_info->protocol == IPC_HDR_PROT_TCP)){
+                                packet_des.packet_info->tcp_flags = meta->tcp_flags;
+                            }
+                        }
+                    }
+
+                    packet_des.des_type = IPC_PKT_DES_TYPE_META;
+                    packet_des.packet = meta->vrb_addr;
+                    packet_des.packet_len = meta->length;
+                    packet_des.meta = meta;
+                    packet_des.matched_filter = &filter;
+                    packet_des.filter_info = &filter_info;
+                    packet_des.ip_type = *ip_type;
+
+                    result = ipc_meta_do_filter(*ip_type, netif_id, meta, dpfm_mirror_des, &packet_des);
+                }
+                else
+                {
+                    hif_trace_error(IPC_TR_META_UL_DROP_FOR_NONE_IP_PKT2, netif_id, meta_idx);
+                    IPC_FREE_META_VRB(meta);
+                    meta->ignore = 1;
+                }
+                break;
+            }
+        case IPC_HPC_MR_DPFM_MATCH_BUT_NO_NAT:
+            {
+                /* Assumption: there is no filter request for these data from LAN NETIF.
+                   So just forward these data to AP (Host2AP) */
+                result = 1;
+                break;
+            }
+        case IPC_HPC_MR_DPFM_DEL_CMD_MATCH:
+            /* Set dirty flag to prevent using wrong packet info if rule is deleted and result is HPC_MR_MATCH with same match_index*/
+            ipc_hpc_tbl[meta->match_index].is_dirty = KAL_TRUE;
+        case IPC_HPC_MR_DPFM_DEL_CMD_MISS:
+        case IPC_HPC_MR_DPFM_ADD_CMD:
+            {
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+                /* DPFM command, no data */
+                hif_data_trace(MD_TRC_IPC_UL_META_DPFM_CMD, meta->mr, meta_idx);
+
+                /* Note that UPCM need DPFM_ADD_CMD for HPC state sync */
+                /* So we don't need to set ignore bit. */
+                if(IPC_HPC_MR_DPFM_ADD_CMD != meta->mr)
+                {
+                    meta->ignore = 1;
+                }
+
+                packet_des.des_type = IPC_PKT_DES_TYPE_META;
+                packet_des.packet = meta->vrb_addr;
+                packet_des.packet_len = meta->length;
+                packet_des.meta = meta;
+                packet_des.is_packet_info = KAL_FALSE;
+                IPC_DPFM_PROCESS_FILTER_CMD(&packet_des);
+
+                result = 0;
+                break;
+#endif
+            }
+        default:
+            /* should not reach here */
+            IPC_ASSERT(0);
+            break;
+    }
+    return result;
+}
+
+kal_bool ipc_on_process_dpfm_cmd_result(kal_uint32 meta_idx, lhif_meta_tbl_t *meta)
+{
+    kal_bool result = 0;
+
+    switch(meta->mr)
+    {
+        case IPC_HPC_MR_DPFM_DEL_CMD_MATCH:
+            /* Set dirty flag to prevent using wrong packet info if rule is deleted and result is HPC_MR_MATCH with same match_index*/
+            ipc_hpc_tbl[meta->match_index].is_dirty = KAL_TRUE;
+        case IPC_HPC_MR_DPFM_DEL_CMD_MISS:
+        case IPC_HPC_MR_DPFM_ADD_CMD:
+            {
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+                ipc_pkt_des_t packet_des = {0};
+                /* DPFM command, no data */
+                hif_data_trace(MD_TRC_IPC_UL_META_DPFM_CMD, meta->mr, meta_idx);
+
+                /* Note that UPCM need DPFM_ADD_CMD for HPC state sync */
+                /* So we don't need to set ignore bit. */
+                if(IPC_HPC_MR_DPFM_ADD_CMD != meta->mr)
+                {
+                    meta->ignore = 1;
+                }
+
+                packet_des.des_type = IPC_PKT_DES_TYPE_META;
+                packet_des.packet = meta->vrb_addr;
+                packet_des.packet_len = meta->length;
+                packet_des.meta = meta;
+                packet_des.is_packet_info = KAL_FALSE;
+                IPC_DPFM_PROCESS_FILTER_CMD(&packet_des);
+
+                result = 0;
+                break;
+#else
+                /* should not reach here */
+                IPC_ASSERT(KAL_FALSE);
+#endif
+            }
+        default:
+            result = 1;
+            break;
+    }
+    return result;
+}
+
+void ipc_hpc_init()
+{
+    kal_mem_set(ipc_hpc_tbl, 0, sizeof(ipc_hpc_info_tbl_t)*IPC_HPC_ENTRY_SIZE);
+}
+
+void ipc_push_meta_list_to_dl_meta_queue(kal_uint16 start_idx, kal_uint16 end_idx, ipfc_dl_filter_queue_type q_type)
+{
+    ipc_dl_meta_queue_t *q;
+
+    q = &ipc_dl_meta_queues_s[q_type];
+
+    IPC_W_LOCK_OBJECT(q, ipc_spinlock_g);
+    if (q) {
+        IPC_ASSERT(q->meta_queue_type == q_type);
+
+        /*
+         * Get meta_queue_size when the first downlink packet arrived.
+         */
+        if (IPC_QUEUE_META_INVALID_VALUE == q->meta_size) {
+            kal_uint32 *base_addr;
+            kal_uint16 tbl_size;
+
+            IPC_QUERY_IPF_META_TABLE((void**)&base_addr, &tbl_size, q_type);
+            q->meta_size = tbl_size;
+            q->pending_cnt = 0;
+        }
+
+        if (IPC_QUEUE_META_INVALID_VALUE == q->meta_tail) {
+            q->meta_head = start_idx;
+            q->meta_tail = end_idx;
+        } else {
+            IPC_ASSERT(start_idx == q->meta_tail);
+            q->meta_tail = end_idx;
+        }
+
+        q->cnt = (q->meta_tail >= q->meta_head)? (q->meta_tail - q->meta_head):(q->meta_size - q->meta_head + q->meta_tail);
+        IPC_W_UNLOCK_OBJECT(q, ipc_spinlock_g);
+    } else {
+        IPC_ASSERT(KAL_FALSE);
+    }
+}
+
+void ipc_meta_downlink(kal_uint16 start_idx, kal_uint16 end_idx, kal_uint32 queue_type)
+{
+    kal_bool to_send_msg;
+
+    HIF_SWLA_START("ID2");
+
+    hif_data_trace(MD_TRC_IPC_DL_META_DOWNLINK_CALLBACK, start_idx, end_idx, queue_type);
+
+    ipc_push_meta_list_to_dl_meta_queue(start_idx, end_idx, (ipfc_dl_filter_queue_type) queue_type);
+
+    to_send_msg = ipc_data_check_and_set_dl_ilm_flag();
+    /*
+     * Switch to IPCORE context.
+     */
+    if (to_send_msg) {
+        msg_send6(  MOD_NIL, /* src_mod_id */
+                    MOD_IPCORE, /* dest_mod_id */
+                    IPCORE_DATAPATH_SAP, /* sap_id */
+                    MSG_ID_IPCORE_PROCESS_DL_QUEUE_REQ, /* msg_id */
+                    NULL, /* local_para_ptr */
+                    NULL); /* peer_buff_ptr */
+    }
+
+    HIF_SWLA_STOP("ID2");
+}
+
+void ipc_meta_downlink_dequeue()
+{
+    kal_uint8 i;
+    ipc_dl_meta_queue_t tmp_queue;
+
+    for (i = 0; i < IPC_DL_META_QUEUE_NUM; i++)
+    {
+        ipc_dl_meta_queue_t *q = &ipc_dl_meta_queues_s[i];
+
+        /*
+         * Check whether the ul queue is allowed to sent or not.
+         * If yes, dequeue the queue.
+         */
+        IPC_W_LOCK_OBJECT(q, ipc_spinlock_g);
+        if (q)
+        {
+            if(0 == q->cnt || IPC_QUEUE_META_INVALID_VALUE == q->cnt)
+            {
+                IPC_W_UNLOCK_OBJECT(q, ipc_spinlock_g);
+                continue;
+            }
+            else
+            {
+                kal_mem_cpy(&tmp_queue, q, sizeof(ipc_dl_meta_queue_t));
+                q->ipc_clear_callback_t(q);
+            }
+
+            IPC_W_UNLOCK_OBJECT(q, ipc_spinlock_g);
+
+            /* Process the queue upto IPC_IPF_DL_META_THRESHOLD */
+            if (tmp_queue.cnt > IPC_IPF_DL_META_THRESHOLD)
+            {
+                hif_data_trace(MD_TRC_IPC_DL_META_PROC_INFO, tmp_queue.meta_head, tmp_queue.meta_tail, tmp_queue.cnt, tmp_queue.pending_cnt, tmp_queue.meta_size);
+                tmp_queue.pending_cnt = tmp_queue.cnt - IPC_IPF_DL_META_THRESHOLD;
+                tmp_queue.cnt = IPC_IPF_DL_META_THRESHOLD;
+                tmp_queue.meta_tail = tmp_queue.meta_head + IPC_IPF_DL_META_THRESHOLD;
+                if (tmp_queue.meta_tail >= tmp_queue.meta_size) {
+                    tmp_queue.meta_tail = tmp_queue.meta_tail - tmp_queue.meta_size;
+                }
+            }
+
+            /* Process the queue by calling it's cbk */
+            tmp_queue.ipc_process_callback_t(&tmp_queue);
+
+            /* Process the pending counts of queue by calling it's cbk */
+            while (tmp_queue.pending_cnt) {
+                hif_data_trace(MD_TRC_IPC_DL_META_PROC_INFO, tmp_queue.meta_head, tmp_queue.meta_tail, tmp_queue.cnt, tmp_queue.pending_cnt, tmp_queue.meta_size);
+                if (tmp_queue.pending_cnt > IPC_IPF_DL_META_THRESHOLD) {
+                    tmp_queue.cnt = IPC_IPF_DL_META_THRESHOLD;
+                    tmp_queue.pending_cnt = tmp_queue.pending_cnt - IPC_IPF_DL_META_THRESHOLD;
+                } else {
+                    tmp_queue.cnt = tmp_queue.pending_cnt;
+                    tmp_queue.pending_cnt = 0;
+                }
+
+                tmp_queue.meta_head = tmp_queue.meta_tail;
+                tmp_queue.meta_tail = tmp_queue.meta_tail + tmp_queue.cnt;
+                if (tmp_queue.meta_tail >= tmp_queue.meta_size) {
+                    tmp_queue.meta_tail = tmp_queue.meta_tail - tmp_queue.meta_size;
+                }
+
+                /* Process the queue by calling it's cbk */
+                tmp_queue.ipc_process_callback_t(&tmp_queue);
+            }
+        }
+        else
+        {
+            IPC_ASSERT(KAL_FALSE);
+        }
+    }
+    return;
+}
+
+void ipc_on_process_dl_meta(ipc_dl_meta_queue_t *q)
+{
+    kal_uint16 read_idx, end_idx, current_idx;
+    ipfc_dl_filter_queue_type q_type = q->meta_queue_type;
+    ipf_dl_meta *meta;
+    ipf_dl_meta *meta_base;
+    kal_uint16 tbl_size;
+    ipc_ipf_dl_match_result_e match_result;
+    kal_bool is_saved = KAL_FALSE;
+    kal_uint32 last_l2cache_invalidate_mask = 0;
+    kal_uint32 i = 0;
+    kal_bool is_matched = KAL_FALSE;
+    kal_uint16 insert_idx = 0;
+
+    /*For packet not matched case, IPCore will diret DL data to default HIF*/
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+#if defined(__MODEM_ONLY__) || defined(__L1_STANDALONE__)
+    ipc_si_hif_type_e default_dl_hif_type = IPC_SI_HIF_TYPE_USB;
+#else
+    ipc_si_hif_type_e default_dl_hif_type = IPC_SI_HIF_TYPE_LHIF;
+#endif
+#endif
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    ipc_dpfm_mirror_des_t dpfm_mirror_des[IPC_DPFM_MAX_DEVICE_NUM] = {0};
+    kal_bool is_mirror_did = KAL_FALSE;
+
+    for (i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++) {
+        dpfm_mirror_des[i].netif_id = IPC_INVALID_NETIF_ID;
+    }
+#else
+    ipc_dpfm_mirror_des_t *dpfm_mirror_des = NULL;
+    kal_bool is_mirror_did = KAL_FALSE;
+#endif
+
+    HIF_SWLA_START("ID4");
+
+    read_idx = q->meta_head;
+    end_idx = q->meta_tail;
+    current_idx = read_idx;
+
+    IPC_QUERY_IPF_META_TABLE((void**)&meta_base, &tbl_size, q_type);
+    hif_data_trace(MD_TRC_IPC_DL_META_ON_PROC, read_idx, end_idx, q_type);
+    kal_mem_set(&g_unk_hdr_stat, 0, sizeof(g_unk_hdr_stat));
+#if defined(__MD97__)
+    kal_mem_set(&g_rq_list, 0, sizeof(g_rq_list));
+    g_rq_list.cnt = 0;
+#endif
+
+    do
+    {
+        read_idx = current_idx;
+#if defined(__MD97__)
+        if (IPFC_META_QUEUE_DL_NR == q_type) {
+            read_idx = lhif_drv_data_get_real_meta_id(read_idx);
+        }
+#endif
+
+        meta = &meta_base[read_idx];
+        if(last_l2cache_invalidate_mask != L2CACHE_LINE_ALIGN_ADDR((kal_uint32)meta)){
+            QBM_CACHE_INVALID(meta, CPU_L2CACHE_LINE_SIZE);
+            last_l2cache_invalidate_mask = L2CACHE_LINE_ALIGN_ADDR((kal_uint32)meta);
+        }
+        match_result = meta->mr;
+        is_saved = KAL_FALSE;
+
+#if IPC_DBG_DL_PKT_DUMP_ENABLE
+        if((match_result != IPC_IPF_MR_NET_INVALID) && (match_result != IPC_IPF_MR_DIRECT_TO_AP) && (match_result != IPC_IPF_MR_PN_NO_MATCH))
+        {
+            ipc_utils_dump_data((void*)meta->addr,64);
+        }
+#endif
+
+        switch(match_result){
+            case IPC_IPF_MR_FILTER_MATCH:
+            case IPC_IPF_MR_UNKNOWN_HEADER:
+            case IPC_IPF_MR_DPFM_MATCH:
+                {
+                    kal_int32 filter_id;
+                    ipc_pkt_des_t packet_des;
+                    kal_uint8 ip_type;
+                    kal_uint8 pdn_sim_id = meta->pdn_sim_id;
+                    kal_uint32 netif_id = ipc_get_netif_id_from_meta(meta->net_type, meta->channel_id);
+                    ipc_session_t *session;
+                    ipc_netif_t *netif;
+                    kal_uint8 filter_idx;
+                    ipc_packet_info_t packet_info = {0};
+                    ipc_filter_info_t filter_info = {0};
+                    ipc_filter_t *p_filter = NULL;
+                    kal_uint8 proto_idx = 0;
+                    kal_uint8 pdn_id = meta->pdn_sim_id;;
+
+                    hif_data_trace(MD_TRC_IPC_DL_META_MATCH_RESULT, read_idx, match_result);
+
+                    if(IPC_IPF_MR_UNKNOWN_HEADER != match_result)
+                    {
+                        ip_type = (meta->ip)?IPC_IP_TYPE_IPV6:IPC_IP_TYPE_IPV4;
+                    }
+                    else
+                    {
+                        ip_type = IPC_IP_TYPE_INVALID;
+                    }
+
+                    session = ipc_find_session_by_context(pdn_sim_id);
+                    if (session) {
+                        netif = session->netif;
+                        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+                        /* Send DL traffic */
+                        IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+                        if (netif)
+                        {
+                            if(match_result == IPC_IPF_MR_FILTER_MATCH)
+                            {
+                                filter_idx = (ip_type == IPC_IP_TYPE_IPV4)?meta->filter_idx:(meta->filter_idx)-1;
+                                filter_id = IPC_QUERY_FILTER_ID_BY_IDX(filter_idx);
+                                if(IPC_SW_DL_FILTER_ID == filter_id){
+                                    filter_id = IPC_INVALID_FILTER_ID;
+                                }
+                            }
+                            else
+                            {
+                                filter_id = IPC_INVALID_FILTER_ID;
+                            }
+
+                            /* Fill packet_des */
+                            packet_des.des_type = IPC_PKT_DES_TYPE_META;
+                            packet_des.packet = (kal_uint8*)meta->addr;
+                            packet_des.packet_len = meta->len;
+                            packet_des.ipf_meta = (void*) meta;
+                            packet_des.matched_filter = &p_filter;
+                            packet_des.filter_info = &filter_info;
+                            packet_des.packet_info = &packet_info;
+                            packet_des.ip_type = ip_type;
+                            packet_des.is_packet_info = KAL_FALSE;
+
+                            ipc_ipf_meta_do_filter(filter_id, &packet_des, ip_type, pdn_sim_id, netif_id, dpfm_mirror_des, &is_mirror_did, &is_saved);
+                            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+                            if ((IPC_IPF_MR_UNKNOWN_HEADER == match_result) &&
+                                (IPC_IP_TYPE_INVALID == packet_des.ip_type)) {
+                                IPC_DL_PKT_DUMP((void *)meta->addr, meta->len);
+
+                                /* calculate statistics */
+                                IPC_RETRIEVE_PROTOID_FROM_PDNID(pdn_id, proto_idx);
+                                is_matched = KAL_FALSE;
+                                insert_idx = 0;
+                                for (i = 0; i < MAX_RBIDX_NUM; i++) {
+                                    if (KAL_TRUE == g_unk_hdr_stat[i].is_valid) {
+                                        if ((meta->rbid == g_unk_hdr_stat[i].rb_idx) &&
+                                            (proto_idx == g_unk_hdr_stat[i].protocol_idx)) {
+                                            is_matched = KAL_TRUE;
+                                            insert_idx = i;
+                                            break;
+                                        }
+                                        insert_idx = i;
+                                    }
+                                }
+
+                                if (is_matched) {
+                                    g_unk_hdr_stat[insert_idx].end_cntl = meta->count;
+                                    g_unk_hdr_stat[insert_idx].unk_hdr_cnt++;
+                                } else {
+                                    if (!((0 == insert_idx) && (KAL_FALSE == g_unk_hdr_stat[insert_idx].is_valid))) {
+                                        insert_idx++;
+                                    }
+
+                                    g_unk_hdr_stat[insert_idx].is_valid = KAL_TRUE;
+                                    g_unk_hdr_stat[insert_idx].unk_hdr_cnt++;
+                                    g_unk_hdr_stat[insert_idx].begin_cntl = meta->count;
+                                    g_unk_hdr_stat[insert_idx].end_cntl = meta->count;
+                                    g_unk_hdr_stat[insert_idx].protocol_idx = proto_idx;
+                                    g_unk_hdr_stat[insert_idx].rb_idx = meta->rbid;
+                                }
+                            }
+
+                            goto _done;
+                        }
+                        else
+                        {
+                            kal_uint8 ip_id = 0xff;
+                            kal_uint8 session_type = IPC_IP_TYPE_INVALID;
+
+                            IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+                            if (session)
+                            {
+                                ip_id = (kal_uint8)session->ip_id;
+                                session_type = session->type;
+                                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                            }
+                            hif_trace_error(IPC_TR_DL_META_DROP_FOR_NETIF_INFO_LOCK_FAIL, pdn_sim_id, ip_id, session_type, read_idx);
+                            goto _drop;
+                        }
+                    }
+                    else
+                    {
+
+                        hif_trace_error(IPC_TR_DL_META_DROP_FOR_INVALID_SESSION, pdn_sim_id, read_idx);
+                        goto _drop;
+                    }
+
+_drop:
+                    IPC_FREE_DL_META_PRB(meta, meta->len);
+_done:
+#if defined(__MD97__)
+                    if (is_saved) {
+                        ipc_rq_info_t rq_info = {0};
+                        kal_uint32 pdn_id = IPC_UNMASK_PROTOID_FROM_PDNID(pdn_sim_id);
+
+                        if (packet_des.is_packet_info) {
+                            if (ipc_data_set_rq_info(&rq_info, pdn_id, &packet_des, IPC_DATA_QFI_SRC_IPF_META)) {
+                                ipc_data_saved_rq_info_list(&g_rq_list, &rq_info);
+                            }
+                        } else {
+                            hif_trace_info(IPC_TR_NO_PKT_INFO, __FUNCTION__);
+                        }
+                    }
+#endif
+
+                    break;
+                }
+            case IPC_IPF_MR_NET_INVALID:
+                {
+                    /* check packet before drop */
+                    ipc_ipf_drop_packet_handler((kal_uint8 *)meta->addr, meta->len, meta->pdn_sim_id);
+
+                    /* do Drop */
+                    hif_trace_error(IPC_TR_DL_META_DROP_FOR_INVALID_NETIF, read_idx, meta->pdn_sim_id, meta->net_type, meta->channel_id);
+
+                    /* we only dump first 64 bytes to optimize user experience on ELT */
+                    if (IPC_PKT_DUMP_LIMITED_LEN > meta->len) {
+                        IPC_FREE_DL_META_PRB(meta, meta->len);
+                    } else {
+                        IPC_FREE_DL_META_PRB(meta, IPC_PKT_DUMP_LIMITED_LEN);
+                    }
+                    break;
+                }
+            case IPC_IPF_MR_DIRECT_TO_AP:
+            case IPC_IPF_MR_PN_NO_MATCH:
+                {
+                    // Do nothing, should not arrive here.
+                    // No need to release data buffer.
+                    if(IPC_IPF_MR_PN_NO_MATCH == match_result)
+                    {
+                        hif_trace_error(IPC_TR_DL_META_DROP_FOR_PN_NO_MATCH, read_idx, meta->rbid, meta->pdn_sim_id, meta->net_type, meta->channel_id);
+                    }
+                    break;
+                }
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+            case IPC_IPF_MR_DPFM_MATCH_BUT_NO_NAT:
+            case IPC_IPF_MR_DPFM_OPEN_AND_DPFM_NOT_MATCH:
+                {
+                    //Just forward to AP
+                    ipc_meta_info_des pkt_info;
+                    upcm_did *did_head;
+                    upcm_did *did_tail;
+                    upcm_did *did;
+                    kal_uint32 *p_si_idx;
+
+                    pkt_info.addr = (void*)(meta->addr);
+                    pkt_info.len = meta->len;
+                    pkt_info.psn_countL = meta->count;
+
+                    //retrieve DID by PDN ID
+                    ipc_did_internal_queue_dequeue(&did_head, &did_tail, &p_si_idx, meta->pdn_sim_id, IPC_DID_QUEUE_TYPE_DPFM);
+
+                    if(!did_head)
+                    {
+                        //allocate DID
+                        did = upcm_did_alloc_one();
+                        if (!did) {
+                            hif_trace_error(IPC_TR_DPFM_DL_ALLOC_DID_NG, meta->pdn_sim_id, meta->channel_id, meta->net_type, __LINE__);
+                            //Drop packet here
+                            IPC_FREE_DL_META_PRB(meta, meta->len);
+                            break;
+                        }
+                        did_head = did_tail = did;
+                        ipc_dpfm_push_did_to_dpfm_queue(did, meta->pdn_sim_id);
+                        *p_si_idx = 0;
+                        UPCM_DID_SET_COUNT_L(did, meta->count);
+                        UPCM_DID_SET_PKT_NUM(did, 0);
+                        UPCM_DID_SET_SEG_NUM(did, 0);
+                    }
+
+                    if(!ipc_utils_fill_did_si_from_meta(KAL_TRUE, did_tail, p_si_idx, &pkt_info, default_dl_hif_type))
+                    {
+                        //count-L overflow, need a new DID, and try again.
+                        did = upcm_did_alloc_one();
+                        if (!did) {
+                            hif_trace_error(IPC_TR_DPFM_DL_ALLOC_DID_NG, meta->pdn_sim_id, meta->channel_id, meta->net_type, __LINE__);
+                            //Drop packet here
+                            IPC_FREE_DL_META_PRB(meta, meta->len);
+                            break;
+                        }
+
+                        ipc_dpfm_push_did_to_dpfm_queue(did, meta->pdn_sim_id);
+                        *p_si_idx = 0;
+                        UPCM_DID_SET_COUNT_L(did, meta->count);
+                        UPCM_DID_SET_PKT_NUM(did, 0);
+                        UPCM_DID_SET_SEG_NUM(did, 0);
+
+                        ipc_utils_fill_did_si_from_meta(KAL_TRUE, did, p_si_idx, &pkt_info, default_dl_hif_type);
+                    }
+                }
+                break;
+#endif
+            default:
+                IPC_ASSERT(0);
+                break;
+        }
+
+        current_idx ++;
+        if (current_idx == tbl_size) {
+            current_idx = 0;
+        }
+    } while(current_idx != end_idx);
+
+    /* notification to L2 */
+    for (i = 0; i < MAX_RBIDX_NUM; i++) {
+        if (KAL_TRUE == g_unk_hdr_stat[i].is_valid) {
+            _IPC_NOTIFY_L2_STATS(g_unk_hdr_stat[i].unk_hdr_cnt,
+                                 g_unk_hdr_stat[i].begin_cntl,
+                                 g_unk_hdr_stat[i].end_cntl,
+                                 g_unk_hdr_stat[i].rb_idx,
+                                 g_unk_hdr_stat[i].protocol_idx);
+            hif_data_trace(MD_TRC_IPC_SEND_L2_UNK_INFO, q->meta_head,
+                                                        q->meta_tail,
+                                                        g_unk_hdr_stat[i].unk_hdr_cnt,
+                                                        g_unk_hdr_stat[i].begin_cntl,
+                                                        g_unk_hdr_stat[i].end_cntl,
+                                                        g_unk_hdr_stat[i].rb_idx,
+                                                        g_unk_hdr_stat[i].protocol_idx);
+        }
+    }
+
+    hif_data_trace(MD_TRC_IPC_DL_META_ON_PROC_DONE, q->meta_head, q->meta_tail, q->cnt, q_type);
+    IPC_FREE_IPF_META(q->cnt, q_type);
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    /* Check if there is DPFM DL data */
+    if (is_mirror_did) {
+        for (i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++) {
+            if (dpfm_mirror_des[i].mirror_did_head) {
+                ipc_pkt_t           pkt;
+
+                IPC_ASSERT(dpfm_mirror_des[i].netif_id != IPC_INVALID_NETIF_ID);
+
+                pkt.buf_type = IPC_PKT_DES_TYPE_DID;
+                pkt.did_head = dpfm_mirror_des[i].mirror_did_head;
+                pkt.did_tail = dpfm_mirror_des[i].mirror_did_tail;
+
+                ipc_send_dl_pkt_in_did_internal(&pkt, NULL, dpfm_mirror_des[i].netif_id);
+            }
+        }
+    }
+#endif
+
+#if defined(__MD97__)
+    ipc_data_send_rq_info(&g_rq_list);
+#endif
+
+    HIF_SWLA_STOP("ID4");
+
+    /*
+     * We don't send DID to AP immediately,
+     * because IPcore will continue to process all DID queue after DL meta is processed
+     */
+
+    return;
+}
+
+/**
+ * Assumption: DL queue write lock is acquired.
+ * This function should be very light. MUST NOT do any heavy jobs.
+ */
+static void ipc_clear_dl_meta_queue(ipc_dl_meta_queue_t *q)
+{
+    q->cnt = 0;
+    q->pending_cnt = 0;
+    q->meta_head = IPC_QUEUE_META_INVALID_VALUE;
+    q->meta_tail = IPC_QUEUE_META_INVALID_VALUE;
+}
+
+void ipc_dl_meta_queue_init()
+{
+    kal_uint8 i;
+    ipc_dl_meta_queue_t *queue_p;
+
+    for( i = 0; i < IPFC_META_QUEUE_MAX; i++)
+    {
+        queue_p = &ipc_dl_meta_queues_s[i];
+        kal_mem_set(queue_p, 0, sizeof(ipc_dl_meta_queue_t));
+        if (!IPC_IS_VALID_OBJECT(queue_p))
+        {
+            IPC_INIT_OBJECT_BEGIN(queue_p, ipc_spinlock_g);
+            queue_p->meta_size = IPC_QUEUE_META_INVALID_VALUE;
+            queue_p->meta_head = IPC_QUEUE_META_INVALID_VALUE;
+            queue_p->meta_tail = IPC_QUEUE_META_INVALID_VALUE;
+            queue_p->cnt = IPC_QUEUE_META_INVALID_VALUE;
+            queue_p->pending_cnt = IPC_QUEUE_META_INVALID_VALUE;
+            queue_p->ipc_clear_callback_t = ipc_clear_dl_meta_queue;
+            queue_p->ipc_process_callback_t = ipc_on_process_dl_meta;
+            queue_p->meta_queue_type = i;
+            IPC_INIT_OBJECT_END(queue_p, ipc_spinlock_g);
+        }
+    }
+}
+
+void ipc_update_pn_match_setting(kal_uint8 pdn_sim_id, kal_uint32 network_interface_id, kal_uint32 ip_type, ipc_ipf_pn_match_cmd_e pnm_cmd )
+{
+    kal_uint8 ipv4 = 0;
+    kal_uint8 ipv6 = 0;
+    kal_uint8 net_type = 0;
+    kal_uint16 nc_id = 0;
+
+    IPC_ASSERT(pdn_sim_id != 0);
+
+    IPC_ASSERT((IPC_IP_TYPE_IPV4 == ip_type) || (IPC_IP_TYPE_IPV6 == ip_type) || (IPC_IP_TYPE_MIXED == ip_type));
+
+    ipv4 = (IPC_IP_TYPE_IPV4 == ip_type || IPC_IP_TYPE_MIXED == ip_type)? 1 : 0 ;
+    ipv6 = (IPC_IP_TYPE_IPV6 == ip_type || IPC_IP_TYPE_MIXED == ip_type)? 1 : 0 ;
+
+    switch(pnm_cmd)
+    {
+        case IPC_IPF_PN_MATCH_UNBIND:
+            /* Clear IPF PN match setting to default value */
+            nc_id = IPC_PN_NCID_DEFAULT;
+            break;
+        case IPC_IPF_PN_MATCH_BIND:
+            net_type = ipc_get_net_type_from_netif_id(network_interface_id);
+            nc_id = (net_type << 8) | ((0xFF) & network_interface_id);
+            break;
+        default:
+            hif_trace_error(IPC_TR_PN_MATCH_CMD_UNKNOWN, pnm_cmd);
+            IPC_ASSERT(0);
+            break;
+    }
+
+    hif_trace_info(IPC_TR_PN_MATCH_SETTING, pdn_sim_id, nc_id, ipv4, ipv6);
+
+    IPC_PN_MATCH_SETTING(pdn_sim_id, nc_id, ipv4, ipv6);
+}
+
+static void ipc_ipf_fill_tcpip_header_in_gpd(kal_uint8 ip_type, qbm_gpd *p_gpd, kal_uint8* p_tcp_hdr_in, kal_uint8* p_ip_hdr_in, kal_uint8 ref_index, kal_uint8 tcp_flag)
+{
+    void* p_bd = NULL;
+    kal_uint32 ip_header_len = 0;
+    kal_uint32 tcp_header_len = 0;
+    kal_uint32 total_len = 0;
+    kal_uint8 *tcp_header = NULL;
+    kal_uint8 *ip_header = NULL;
+    kal_uint8 *src_addr = NULL;
+    kal_uint8 *dst_addr = NULL;
+    kal_uint16 sum16;
+    kal_bool is_ipv4;
+    kal_uint16 ipid = 0;
+
+    ip_header_len = (ip_type == IPC_IP_TYPE_IPV4) ? IPC_HDR_V4_HEADER_SIZE : IPC_HDR_V6_HEADER_SIZE;
+    is_ipv4 = (ip_type == IPC_IP_TYPE_IPV4) ? KAL_TRUE : KAL_FALSE;
+    tcp_header_len = IPC_HDR_TCP_HEADER_SIZE;
+    total_len = ip_header_len + tcp_header_len;
+
+    IPC_ASSERT(p_gpd);
+
+    p_bd = QBM_DES_GET_DATAPTR(p_gpd);
+    ip_header = QBM_DES_GET_DATAPTR(p_bd);
+    tcp_header = ip_header + ip_header_len;
+
+    if (ip_type == IPC_IP_TYPE_IPV4) {
+        src_addr = IPC_HDR_V4_GET_DST_ADDR(p_ip_hdr_in);
+        dst_addr = IPC_HDR_V4_GET_SRC_ADDR(p_ip_hdr_in);
+        ipid = IPC_HDR_V4_GET_IDENTITY(p_ip_hdr_in);
+    } else if (ip_type == IPC_IP_TYPE_IPV6) {
+        src_addr = IPC_HDR_V6_GET_DST_ADDR(p_ip_hdr_in);
+        dst_addr = IPC_HDR_V6_GET_SRC_ADDR(p_ip_hdr_in);
+    } else {
+        /* unknown packet type */
+        DEBUG_ASSERT(0);
+        return;
+    }
+
+    /* Fill TCP header */
+    IPC_HDR_TCP_SET_SRC_PORT(tcp_header, IPC_HDR_TCP_GET_DST_PORT(p_tcp_hdr_in));
+    IPC_HDR_TCP_SET_DST_PORT(tcp_header, IPC_HDR_TCP_GET_SRC_PORT(p_tcp_hdr_in));
+    IPC_HDR_TCP_SET_SEQ_NUM(tcp_header, IPC_HDR_TCP_GET_ACK_NUM(p_tcp_hdr_in) + ref_index);
+    if(IPC_HDR_TCP_FLAG_RST == tcp_flag){
+        IPC_HDR_TCP_SET_ACK_NUM(tcp_header, 0);
+        /* set reserved1 flag for TCP RST UL packet*/
+        QBM_DES_SET_DRP_ALLW(p_gpd, IPC_DRP_ALLW_PKT);
+    }else{
+        IPC_HDR_TCP_SET_ACK_NUM(tcp_header, (IPC_HDR_TCP_GET_SEQ_NUM(p_tcp_hdr_in)+1));
+    }
+    IPC_HDR_TCP_SET_OFFSET(tcp_header, IPC_HDR_TCP_HEADER_SIZE);
+    IPC_HDR_TCP_SET_RESERVED(tcp_header, 0);
+    IPC_HDR_TCP_SET_FLAGS(tcp_header, tcp_flag);
+    IPC_HDR_TCP_SET_WINDOW(tcp_header, 0);
+    IPC_HDR_TCP_SET_CHECKSUM(tcp_header, 0);
+    IPC_HDR_TCP_SET_URGENT_PTR(tcp_header, 0);
+    sum16 = ipc_calc_tcp_checksum(is_ipv4, src_addr, dst_addr, tcp_header, tcp_header_len);
+    IPC_HDR_TCP_SET_CHECKSUM(tcp_header, sum16);
+
+    /* Fill IP header */
+    if (is_ipv4) {
+        IPC_HDR_V4_RESET_VER_IHL_DSCP_ECN(ip_header);
+        IPC_HDR_V4_SET_TOTAL_LENGTH(ip_header, total_len);
+        IPC_HDR_V4_SET_IDENTITY(ip_header, (ipid+ref_index)); /* reference peer IPID */
+        IPC_HDR_V4_SET_FLAGS(ip_header, 0x2); /* Set Do Not Fragment */
+        IPC_HDR_V4_SET_FRAG_OFFSET(ip_header, 0);
+        IPC_HDR_V4_SET_TTL(ip_header, IPC_DEF_TTL);
+        IPC_HDR_V4_SET_PROTOCOL(ip_header, IPC_HDR_PROT_TCP);
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, 0);
+        IPC_HDR_V4_SET_SRC_ADDR(ip_header, src_addr);
+        IPC_HDR_V4_SET_DST_ADDR(ip_header, dst_addr);
+        sum16 = ipc_calc_ipv4_checksum(ip_header);
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, sum16);
+    } else {
+        IPC_HDR_V6_RESET_VER_TC_FL(ip_header);
+        IPC_HDR_V6_SET_TC(ip_header, IPC_HDR_V6_GET_TC(p_ip_hdr_in));
+        IPC_HDR_V6_SET_FLOW_LABEL(ip_header, IPC_HDR_V6_GET_FLOW_LABEL(p_ip_hdr_in));
+        IPC_HDR_V6_SET_LENGTH(ip_header, (total_len - ip_header_len));
+        IPC_HDR_V6_SET_NH_TYPE(ip_header, IPC_HDR_PROT_TCP);
+        IPC_HDR_V6_SET_HOP_LIMIT(ip_header, IPC_HDR_V6_GET_HOP_LIMIT(p_ip_hdr_in));
+        IPC_HDR_V6_SET_SRC_ADDR(ip_header, src_addr);
+        IPC_HDR_V6_SET_DST_ADDR(ip_header, dst_addr);
+    }
+
+    /* Flush GPD and BD */
+    QBM_CACHE_FLUSH(ip_header, total_len);
+    QBM_DES_SET_DATALEN(p_bd, total_len);
+    qbm_cal_set_checksum(p_bd);
+    QBM_DES_SET_DATALEN(p_gpd, total_len);
+    qbm_cal_set_checksum(p_gpd);
+
+    return;
+}
+
+static kal_bool ipc_ipf_fill_icmp_port_unreachable_in_gpd(kal_uint8 ip_type, qbm_gpd *p_gpd, kal_uint8* p_ip_hdr_in)
+{
+    kal_uint32 ip_header_len = 0;
+    kal_uint32 icmp_header_len = 0;
+    kal_uint32 total_len = 0;
+    kal_bool is_ipv4;
+    kal_uint16 input_ip_pkt_len = 0;
+
+    kal_uint8 *p_ip_header = NULL;
+    kal_uint8 *p_icmp_header = NULL;
+    kal_uint8 *p_data_ptr = NULL;
+    void* p_bd = NULL;
+
+    kal_uint16 sum16;
+    kal_uint16 ipid = 0;
+
+    kal_uint8 *p_src_addr = NULL;
+    kal_uint8 *p_dst_addr = NULL;
+
+
+    ip_header_len = (ip_type == IPC_IP_TYPE_IPV4) ? IPC_HDR_V4_HEADER_SIZE : IPC_HDR_V6_HEADER_SIZE;
+    is_ipv4 = (ip_type == IPC_IP_TYPE_IPV4) ? KAL_TRUE : KAL_FALSE;
+    icmp_header_len = IPC_HDR_ICMP_HEADER_SIZE;
+    if(is_ipv4 == KAL_TRUE) {
+        input_ip_pkt_len = IPC_HDR_V4_GET_TOTAL_LENGTH(p_ip_hdr_in);
+    } else {
+        input_ip_pkt_len = IPC_HDR_V6_GET_LENGTH(p_ip_hdr_in) + IPC_HDR_V6_HEADER_SIZE;
+    }
+    /*this is the length of response message*/
+    total_len = ip_header_len + icmp_header_len + input_ip_pkt_len;
+
+    IPC_ASSERT(p_gpd);
+
+    p_bd = QBM_DES_GET_DATAPTR(p_gpd);
+    p_ip_header = QBM_DES_GET_DATAPTR(p_bd);
+
+    /*out response = IPv4/v6 + ICMP header + data(return IP packet)*/
+
+    p_icmp_header = p_ip_header + ip_header_len;
+    p_data_ptr = p_icmp_header + icmp_header_len;
+
+    /*fill the return ip packet*/
+    /*there could be a need of length check to copy, MTU size exceed issue*/
+    if (total_len < (QBM_NET_UL_DATA_LEN - QBM_CACHE_SIZE)) {
+        kal_mem_cpy(p_data_ptr, p_ip_hdr_in, input_ip_pkt_len);
+    } else {
+        hif_trace_info(IPC_TR_DL_META_B4_DROP_UDP_PREPARE_UL_GPD_NG, __FUNCTION__, total_len);
+        return KAL_FALSE;
+    }
+
+    if (ip_type == IPC_IP_TYPE_IPV4) {
+        p_src_addr = IPC_HDR_V4_GET_DST_ADDR(p_ip_hdr_in);
+        p_dst_addr = IPC_HDR_V4_GET_SRC_ADDR(p_ip_hdr_in);
+        ipid = IPC_HDR_V4_GET_IDENTITY(p_ip_hdr_in);
+    } else if (ip_type == IPC_IP_TYPE_IPV6) {
+        p_src_addr = IPC_HDR_V6_GET_DST_ADDR(p_ip_hdr_in);
+        p_dst_addr = IPC_HDR_V6_GET_SRC_ADDR(p_ip_hdr_in);
+    } else {
+        /* unknown packet type */
+        DEBUG_ASSERT(0);
+        return KAL_FALSE;
+    }
+
+    /*fill icmp header, type, code, checksum*/
+    if(is_ipv4) {
+        IPC_HDR_ICMP_SET_TYPE(p_icmp_header, 3);
+        IPC_HDR_ICMP_SET_CODE(p_icmp_header, 3);
+        IPC_HDR_ICMP_SET_CHECKSUM(p_icmp_header, 0);
+        IPC_HDR_ICMP_SET_UNUSED(p_icmp_header, 0);
+        sum16 = ipc_utils_calc_icmp_checksum(p_icmp_header, total_len-ip_header_len);
+        IPC_HDR_ICMP_SET_CHECKSUM(p_icmp_header, sum16);
+    } else  {
+        IPC_HDR_ICMP_SET_TYPE(p_icmp_header, 1);
+        IPC_HDR_ICMP_SET_CODE(p_icmp_header, 4);
+        IPC_HDR_ICMP_SET_CHECKSUM(p_icmp_header, 0);
+        IPC_HDR_ICMP_SET_UNUSED(p_icmp_header, 0);
+        sum16 = ipc_utils_calc_icmp_checksum(p_icmp_header, total_len-ip_header_len);
+        IPC_HDR_ICMP_SET_CHECKSUM(p_icmp_header, sum16);
+    }
+
+    /* Fill IP header */
+    if (is_ipv4) {
+        IPC_HDR_V4_RESET_VER_IHL_DSCP_ECN(p_ip_header);
+        //IPC_HDR_V4_SET_DSCP(ip_header, 192);
+        IPC_HDR_V4_SET_TOTAL_LENGTH(p_ip_header, total_len);
+        IPC_HDR_V4_SET_IDENTITY(p_ip_header, (ipid)); /* reference peer IPID */
+        IPC_HDR_V4_SET_FLAGS(p_ip_header, 0x2); /* Set Do Not Fragment */
+        IPC_HDR_V4_SET_FRAG_OFFSET(p_ip_header, 0);
+        IPC_HDR_V4_SET_TTL(p_ip_header, IPC_DEF_TTL);
+        IPC_HDR_V4_SET_PROTOCOL(p_ip_header, IPC_HDR_PROT_ICMP);
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(p_ip_header, 0);
+        IPC_HDR_V4_SET_SRC_ADDR(p_ip_header, p_src_addr);
+        IPC_HDR_V4_SET_DST_ADDR(p_ip_header, p_dst_addr);
+        sum16 = ipc_calc_ipv4_checksum(p_ip_header);
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(p_ip_header, sum16);
+    } else {
+        IPC_HDR_V6_RESET_VER_TC_FL(p_ip_header);
+        IPC_HDR_V6_SET_TC(p_ip_header, IPC_HDR_V6_GET_TC(p_ip_hdr_in));
+        IPC_HDR_V6_SET_FLOW_LABEL(p_ip_header, IPC_HDR_V6_GET_FLOW_LABEL(p_ip_hdr_in));
+        IPC_HDR_V6_SET_LENGTH(p_ip_header, (total_len - ip_header_len));
+        IPC_HDR_V6_SET_NH_TYPE(p_ip_header, IPC_HDR_PROT_ICMPV6);
+        IPC_HDR_V6_SET_HOP_LIMIT(p_ip_header, IPC_HDR_V6_GET_HOP_LIMIT(p_ip_hdr_in));
+        IPC_HDR_V6_SET_SRC_ADDR(p_ip_header, p_src_addr);
+        IPC_HDR_V6_SET_DST_ADDR(p_ip_header, p_dst_addr);
+    }
+
+    /* set reserved1 flag for UDP Response UL packet*/
+    QBM_DES_SET_DRP_ALLW(p_gpd, IPC_DRP_ALLW_PKT);
+
+    /* Flush GPD and BD */
+    QBM_CACHE_FLUSH(p_ip_header, total_len);
+    QBM_DES_SET_DATALEN(p_bd, total_len);
+    qbm_cal_set_checksum(p_bd);
+    QBM_DES_SET_DATALEN(p_gpd, total_len);
+    qbm_cal_set_checksum(p_gpd);
+    hif_trace_info(IPC_TR_DL_META_B4_DROP_UDP_PREPARE_UL_GPD, __FUNCTION__);
+    return KAL_TRUE;
+}
+
+void ipc_ipf_dhlr_for_udp_rst(kal_uint8 *p_packet, kal_uint8 pdn_sim_id)
+{
+    kal_uint8 ip_type;
+    qbm_gpd *p_head = NULL;
+    qbm_gpd *p_tail = NULL;
+    ipc_pkt_t ipc_pkt = {0};
+    kal_bool result = KAL_TRUE;
+
+    if(NULL == p_packet){
+        hif_trace_info(IPC_TR_DL_META_B4_DROP_INVALID_PARAM, __FUNCTION__, p_packet);
+        return;
+    }
+
+    /* Alias */
+    if (IPC_HDR_IS_V4(p_packet)) {
+        ip_type = IPC_IP_TYPE_IPV4;
+    } else if (IPC_HDR_IS_V6(p_packet)) {
+        ip_type = IPC_IP_TYPE_IPV6;
+    } else {
+        /* unknown packet type */
+        hif_trace_info(IPC_TR_DROP_HDLR_UNKNOWN_IPTYPE, __FUNCTION__);
+        return;
+    }
+
+    if(1 != qbmt_alloc_q(QBM_TYPE_NET_UL, 1, (void**)&p_head, (void**)&p_tail)){
+        hif_trace_info(IPC_TR_DL_META_B4_DROP_GPD_ALLOC_NG, __FUNCTION__, __LINE__);
+        return;
+    }
+    if (KAL_FALSE == ipc_ipf_fill_icmp_port_unreachable_in_gpd(ip_type, p_head, p_packet)) {
+        qbmt_dest_q(p_head, p_tail);
+        p_head = p_tail = NULL;
+        return;
+    }
+
+    /* Send response */
+    if(p_head && p_tail){
+        ipc_pkt.isGPD = KAL_TRUE;
+        ipc_pkt.head = p_head;
+        ipc_pkt.tail = p_tail;
+        hif_trace_info(IPC_TR_DL_META_B4_DROP_UDP_SEND_UL_GPD, __FUNCTION__, p_head, p_tail);
+        result = ipc_send_ul_pkt_by_pdn(&ipc_pkt, NULL, pdn_sim_id, ip_type);
+        if(KAL_FALSE == result){
+            qbmt_dest_q(p_head, p_tail);
+        }
+    }
+}
+
+void ipc_ipf_dhlr_for_tcp_rst(kal_uint8 *p_packet, ipc_packet_info_t packet_info, kal_uint8 pdn_sim_id)
+{
+    kal_uint8 *p_tcp_header = NULL;
+    kal_uint8 ip_type;
+    kal_uint8 gpd_num = 0;
+    qbm_gpd *p_head = NULL;
+    qbm_gpd *p_tail = NULL;
+    ipc_pkt_t ipc_pkt = {0};
+    kal_bool result = KAL_TRUE;
+
+    if(NULL == p_packet){
+        hif_trace_info(IPC_TR_DL_META_B4_DROP_INVALID_PARAM, __FUNCTION__, p_packet);
+        return;
+    }
+
+    /* Alias */
+    if (IPC_HDR_IS_V4(p_packet)) {
+        ip_type = IPC_IP_TYPE_IPV4;
+    } else if (IPC_HDR_IS_V6(p_packet)) {
+        ip_type = IPC_IP_TYPE_IPV6;
+    } else {
+        /* unknown packet type */
+        hif_trace_info(IPC_TR_DROP_HDLR_UNKNOWN_IPTYPE, __FUNCTION__);
+        return;
+    }
+    p_tcp_header = p_packet + packet_info.l4_offset;
+
+    /* Determine Response:
+     * If received [ACK], response [RST]
+     * If received [FIN,ACK], response [ACK] + [FIN,ACK]
+     * If received [SYN], response [ACK] + [RST]
+     */
+    if (packet_info.tcp_flags & (IPC_HDR_TCP_FLAG_FIN | IPC_HDR_TCP_FLAG_SYN)) {
+        gpd_num = 2;
+        if (gpd_num != qbmt_alloc_q(QBM_TYPE_NET_UL, gpd_num, (void**) &p_head, (void**) &p_tail)) {
+            if (p_head && p_tail) {
+                g_ipc_qbm_failed_gpd_cnt++;
+                qbmt_dest_q(p_head, p_tail);
+            }
+            hif_trace_info(IPC_TR_DL_META_B4_DROP_GPD_ALLOC_NG_CNT, __FUNCTION__, __LINE__, g_ipc_qbm_failed_gpd_cnt);
+            return;
+        }
+
+        /* 1st GPD : [ACK]*/
+        ipc_ipf_fill_tcpip_header_in_gpd(ip_type, p_head, p_tcp_header, p_packet, 0, IPC_HDR_TCP_FLAG_ACK);
+
+        /* 2nd GPD : [FIN,ACK] or [RST] */
+        if (packet_info.tcp_flags & IPC_HDR_TCP_FLAG_FIN) {
+            ipc_ipf_fill_tcpip_header_in_gpd(ip_type, p_tail, p_tcp_header, p_packet, 0, IPC_HDR_TCP_FLAG_ACK | IPC_HDR_TCP_FLAG_FIN);
+        } else {
+            ipc_ipf_fill_tcpip_header_in_gpd(ip_type, p_tail, p_tcp_header, p_packet, 0, IPC_HDR_TCP_FLAG_RST);
+        }
+    } else {
+        gpd_num = 1;
+        if (gpd_num != qbmt_alloc_q(QBM_TYPE_NET_UL, gpd_num, (void**) &p_head, (void**) &p_tail)) {
+            hif_trace_info(IPC_TR_DL_META_B4_DROP_GPD_ALLOC_NG, __FUNCTION__, __LINE__);
+            return;
+        }
+        /* [RST] packet only */
+        ipc_ipf_fill_tcpip_header_in_gpd(ip_type, p_head, p_tcp_header, p_packet, 0, IPC_HDR_TCP_FLAG_RST);
+    }
+
+    /* Send response */
+    if (p_head && p_tail) {
+        kal_mem_set(&ipc_pkt, 0, sizeof(ipc_pkt));
+        ipc_pkt.isGPD = KAL_TRUE;
+        ipc_pkt.head = p_head;
+        ipc_pkt.tail = p_tail;
+        hif_trace_info(IPC_TR_DL_META_B4_DROP_SEND_UL_GPD, __FUNCTION__, p_head, p_tail);
+        result = ipc_send_ul_pkt_by_pdn(&ipc_pkt, NULL, pdn_sim_id, ip_type);
+        if (KAL_FALSE == result) {
+            qbmt_dest_q(p_head, p_tail);
+        }
+    }
+
+    return;
+}
+
+void ipc_ipf_drop_packet_handler(kal_uint8* p_packet, kal_uint32 len, kal_uint8 pdn_sim_id)
+{
+    kal_bool result = KAL_FALSE;
+    ipc_packet_info_t packet_info;
+    qbm_gpd *p_ra_gpd = NULL;
+    kal_uint8 *p_gpd_data = NULL;
+
+    if((NULL == p_packet) || (0 == len)){
+        hif_trace_info(IPC_TR_IPF_DROP_HDR_INVALID_PARAM, __FUNCTION__, p_packet, len);
+        return;
+    }
+
+    kal_mem_set(&packet_info, 0, sizeof(ipc_packet_info_t));
+    /* Parsing packet first */
+    result = ipc_get_packet_info(p_packet, len, &packet_info);
+    if(KAL_FALSE == result){
+        hif_trace_info(IPC_TR_DROP_HDLR_PKT_INFO_NG, __FUNCTION__);
+        return;
+    }
+
+    switch(packet_info.protocol){
+        case IPC_HDR_PROT_TCP:
+        {
+            if((IPC_HDR_TCP_FLAG_RST == (packet_info.tcp_flags & IPC_HDR_TCP_FLAG_RST)) || (!packet_info.tcp_flags)){
+                /* Skipped if received [RST] packet */
+                break;
+            }
+            ipc_ipf_dhlr_for_tcp_rst(p_packet, packet_info, pdn_sim_id);
+            break;
+        }
+        case IPC_HDR_PROT_ICMPV6:
+        {
+            if(IPC_HDR_ICMPV6_TYPE_RA == packet_info.icmpv6_type){
+                ipc_data_ipv6_ra_pool_push(pdn_sim_id, NULL);
+                p_ra_gpd = qbm_alloc_one(QBM_TYPE_NET_DL);
+                if(!p_ra_gpd){
+                    hif_trace_info(IPC_TR_DROP_HDR_GPD_ALLOC_NG, __FUNCTION__, __LINE__);
+                    break;
+                }
+                ipc_utils_set_gpd_datalen(p_ra_gpd, len, (void**)&p_gpd_data);
+                QBM_CACHE_INVALID(p_packet, len);
+                kal_mem_cpy(p_gpd_data, p_packet, len);
+                ipc_data_ipv6_ra_pool_push(pdn_sim_id, p_ra_gpd);
+                hif_trace_info(IPC_TR_DOWNLINK_RA_PROXY_GPD, __FUNCTION__, pdn_sim_id, p_ra_gpd);
+            }
+            break;
+        }
+        case IPC_HDR_PROT_UDP:
+        {
+            ipc_ipf_dhlr_for_udp_rst(p_packet, pdn_sim_id);
+            break;
+        }
+        default :
+        {
+            /* Protocol not support log */
+            hif_trace_info(IPC_TR_DROP_HDLR_NG_PROTO, __FUNCTION__, packet_info.protocol);
+            break;
+        }
+    }
+
+    return;
+}
+
+
diff --git a/mcu/middleware/hif/ipcore/src/ipc_dhcp_adp.c b/mcu/middleware/hif/ipcore/src/ipc_dhcp_adp.c
new file mode 100644
index 0000000..fe8334b
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_dhcp_adp.c
@@ -0,0 +1,555 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_dhcp_adp.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   DHCP adaption.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_api.h"
+#include "intrCtrl.h"
+#include "mw_sap.h"
+#include "hif_mw_msgid.h"
+#include "dhcp4c_struct.h"
+#include "ipcore_iph.h"
+
+#include "ipc_defs.h"
+#include "ipc_debug.h"
+#include "ipc_utils.h"
+#include "ipc_dhcp_adp.h"
+#include "ipc_filter.h"
+#include "ipc_notify.h"
+#include "ipc_filter_priority.h"
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Privatate implementation.
+ *----------------------------------------------------------------------------*/
+void
+ipc_on_dl_dhcp4_packet(
+        void       *context,
+        kal_int32   filter_id,
+        qbm_gpd    *head_gpd,
+        qbm_gpd    *tail_gpd,
+        kal_uint32  length)
+{
+    ipc_session_t      *session = (ipc_session_t *)context;
+    kal_int32           ip_id;
+    dhcp4c_packet_req_struct   *packet_req;
+    kal_uint8           dhcp_id;
+
+    IPC_ASSERT(NULL != context && NULL != head_gpd && NULL != tail_gpd && 0 < length);
+
+    IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+    if (session) {
+        ip_id   = session->ip_id;
+        dhcp_id = session->dhcp4c_id;
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        if (head_gpd == tail_gpd) {
+            packet_req = (dhcp4c_packet_req_struct *)construct_local_para(sizeof(dhcp4c_packet_req_struct), 0);
+            packet_req->ip_id   = ip_id;
+            packet_req->dhcp_id = dhcp_id;
+            packet_req->gpd     = head_gpd;
+
+            msg_send6(MOD_IPCORE, /* src_mod_id */
+                      MOD_DHCP4C, /* dest_mod_id */
+                      DHCP4C_SAP, /* sap_id */
+                      MSG_ID_DHCP4C_PACKET_REQ, /* msg_id */
+                      (local_para_struct *)packet_req, /* local_para_ptr */
+                      NULL); /* peer_buff_ptr */
+            return;
+        } else {
+            hif_trace_error(IPC_TR_DHCP4C_ON_DL_PACKET_INVALID_GPD_LIST, head_gpd, tail_gpd, length);
+        }
+    } else {
+        hif_trace_error(IPC_TR_DHCP4C_ON_DL_PACKET_FIND_NO_SESSION, context);
+    }
+
+    /*
+     * Free the downlink IP datagram filtered to BM if something wrong.
+     */
+    if (NULL != head_gpd && NULL != tail_gpd) {
+        qbmt_dest_q(head_gpd, tail_gpd);
+    }
+}
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+void ipc_enable_dhcp4c(void *session_ptr)
+{
+    ipc_session_t      *session = (ipc_session_t *)session_ptr;
+    ipc_filter_rules_t  rules;
+    kal_int32           filter_id;
+    dhcp4c_activate_req_struct  *activate_req;
+    kal_int32           ip_id;
+    kal_uint8           context;
+    kal_uint8           type;
+    static kal_uint8    hw_addr[] = {0x00, 0x0c, 0x7c, 0x00, 0x00, 0x00};
+
+    IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+    if (session) {
+        context = session->context;
+        type = session->type;
+        ip_id = session->ip_id;
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        /*
+         * Install a downlink filter for packet from DHCPv4 server.
+         */
+        kal_mem_set(&rules, 0, sizeof(rules));
+        rules.priority = IPC_DL_FILTER_PRIORITY_IPC_DHCP_BEGIN;
+        rules.valid_fields = ( IPC_FILTER_BY_PROTOCOL |
+                               IPC_FILTER_BY_SRC_PORT |
+                               IPC_FILTER_BY_DST_PORT |
+                               IPC_FILTER_BY_PDN_ID );
+        rules.pdn_id = context;
+
+        IPC_RETRIEVE_PROTOID_FROM_PDNID(context, rules.proto_idx);
+        IPC_UNMASK_PROTOID_FROM_PDNID(rules.pdn_id);
+
+        rules.ip_type = IPC_IP_TYPE_IPV4;
+        rules.protocol = IPC_HDR_PROT_UDP;
+        rules.src_port = IPC_PORT_BOOTPS;
+        rules.dst_port = IPC_PORT_BOOTPC;
+
+        filter_id = ipc_register_dl_filter_cbk(&rules, ipc_on_dl_dhcp4_packet, session);
+        if (0 <= filter_id) {
+            hif_trace_info(IPC_TR_DHCP4C_EN_REG_DL_FILTER_OK, context, type, filter_id);
+
+            IPC_W_LOCK_OBJECT(session, ipc_spinlock_g);
+            if (session) {
+                session->dhcp4c_dl_filter_id = filter_id;
+                IPC_W_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            }
+
+            /*
+             * Activate DHCPv4 client.
+             */
+            activate_req = (dhcp4c_activate_req_struct *)construct_local_para(sizeof(dhcp4c_activate_req_struct), 0);
+            activate_req->ip_id = ip_id;
+            activate_req->hardware_address_type = DHCP4C_HTYPE_ETHERNET;
+            kal_mem_cpy(activate_req->hardware_address, hw_addr, sizeof(hw_addr));
+            activate_req->hardware_address[5] = context;
+
+            msg_send6(MOD_IPCORE, /* src_mod_id */
+                      MOD_DHCP4C, /* dest_mod_id */
+                      DHCP4C_SAP, /* sap_id */
+                      MSG_ID_DHCP4C_ACTIVATE_REQ, /* msg_id */
+                      (local_para_struct *)activate_req, /* local_para_ptr */
+                      NULL); /* peer_buff_ptr */
+        } else {
+            hif_trace_error(IPC_TR_DHCP4C_EN_REG_DL_FILTER_NG, context, type, filter_id);
+            IPC_ASSERT(KAL_FALSE);
+        }
+    } else {
+        hif_trace_error(IPC_TR_DHCP4C_EN_FAILED_WITH_INVALID_PARAMETER);
+    }
+}
+
+void ipc_on_dhcp4c_activate_rsp(void *activate_rsp_ptr)
+{
+    dhcp4c_activate_rsp_struct *activate_rsp = (dhcp4c_activate_rsp_struct *)activate_rsp_ptr;
+    ipc_session_t      *session;
+    kal_uint8           context;
+    kal_uint8           type;
+    kal_uint8           dhcp4c_id;
+
+    session = ipc_find_session_by_ip_id(activate_rsp->ip_id, IPC_IP_TYPE_IPV4);
+    if (session) {
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        if (DHCP4C_CAUSE_SUCCESS == activate_rsp->cause) {
+            IPC_W_LOCK_OBJECT(session, ipc_spinlock_g);
+            if (session) {
+                context = session->context;
+                type = session->type;
+                dhcp4c_id = session->dhcp4c_id;
+                session->dhcp4c_id = activate_rsp->dhcp_id;
+                session->dhcp4c_running = KAL_TRUE;
+                IPC_W_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+                hif_trace_info(IPC_TR_DHCP4C_ACT_RSP_OK, context, type, dhcp4c_id);
+                return;
+            } else {
+                hif_trace_error(IPC_TR_DHCP4C_ACT_RSP_INVALID_SESSION, activate_rsp->ip_id);
+            }
+        } else {
+            hif_trace_error(IPC_TR_DHCP4C_ACT_RSP_NG, session->context, session->type);
+        }
+
+        ipc_disable_dhcp4c(session);
+    } else {
+        hif_trace_error(IPC_TR_DHCP4C_ACT_RSP_FIND_NO_SESSION, activate_rsp->ip_id);
+    }
+}
+
+void ipc_disable_dhcp4c(void *session_ptr)
+{
+    ipc_session_t      *session = (ipc_session_t *)session_ptr;
+    kal_int32           filter_id;
+    kal_int32           ip_id;
+    dhcp4c_deactivate_req_struct *deactivate_req;
+    kal_bool            to_stop_dhcpc;
+    kal_uint8           dhcp_id;
+    kal_uint8           context;
+    kal_uint8           type;
+
+    IPC_W_LOCK_OBJECT(session, ipc_spinlock_g);
+    if (session) {
+        to_stop_dhcpc = session->dhcp4c_running;
+        filter_id = session->dhcp4c_dl_filter_id;
+        ip_id = session->ip_id;
+        dhcp_id = session->dhcp4c_id;
+        context = session->context;
+        type = session->type;
+
+        session->dhcp4c_running = KAL_FALSE;
+        session->dhcp4c_dl_filter_id = -1;
+        IPC_W_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        hif_trace_info(IPC_TR_DHCP4C_DIS_INFO, context, type, to_stop_dhcpc, dhcp_id, filter_id);
+
+        /*
+             * Deactivate DHCPv4 client.
+             */
+        if (to_stop_dhcpc) {
+            deactivate_req = (dhcp4c_deactivate_req_struct *)construct_local_para(sizeof(dhcp4c_deactivate_req_struct), 0);
+            deactivate_req->ip_id = ip_id;
+            deactivate_req->dhcp_id = dhcp_id;
+
+            msg_send6(MOD_IPCORE, /* src_mod_id */
+                      MOD_DHCP4C, /* dest_mod_id */
+                      DHCP4C_SAP, /* sap_id */
+                      MSG_ID_DHCP4C_DEACTIVATE_REQ, /* msg_id */
+                      (local_para_struct *)deactivate_req, /* local_para_ptr */
+                      NULL); /* peer_buff_ptr */
+        }
+
+        /*
+         * Uninstall the downlink filter.
+         */
+        if (0 <= filter_id) {
+            ipc_deregister_dl_filter(filter_id);
+            hif_trace_info(IPC_TR_DHCP4C_DIS_DEREG_DL_FILTER_OK, session->context, session->type, filter_id);
+        }
+    } else {
+        hif_trace_error(IPC_TR_DHCP4C_DIS_FAILED_WITH_INVALID_PARAMETER);
+    }
+}
+
+void ipc_on_dhcp4c_deactivate_rsp(void *deactivate_rsp_ptr)
+{
+    /* do nothing since we have done the clean up in ipc_disable_dhcp4c(). */
+}
+
+void ipc_on_dhcp4c_ip_up_ind(void *dhcp4c_ip_up_ind_ptr)
+{
+    dhcp4c_ip_up_ind_struct *ip_up_ind = (dhcp4c_ip_up_ind_struct *)dhcp4c_ip_up_ind_ptr;
+    ipc_session_t      *session;
+    ipc_session_state_e session_state;
+
+    hif_trace_info(IPC_TR_DHCP4C_IP_UP_IND_START, dhcp4c_ip_up_ind_ptr);
+
+    session = ipc_find_session_by_ip_id(ip_up_ind->ip_id, IPC_IP_TYPE_IPV4);
+
+    hif_trace_info(IPC_TR_DHCP4C_IP_UP_IND_FIND_SESSION_RESULT, session, ip_up_ind->ip_id);
+
+    if (session) {
+        session_state = session->state;
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        hif_trace_info(IPC_TR_DHCP4C_IP_UP_IND_SESSION_STATE, session, session_state);
+
+        /* Only handle following states */
+        if (    session_state == IPC_SESSION_STATE_BIND ||
+                session_state == IPC_SESSION_STATE_PRE_LINKUP_IPV4_LEASE ||
+                session_state == IPC_SESSION_STATE_IPV4_LEASE)
+        {
+
+        if (    session_state == IPC_SESSION_STATE_BIND ||
+                session_state == IPC_SESSION_STATE_PRE_LINKUP_IPV4_LEASE    )
+        {   /* Not linkup for IPv4 yet : swtich to Pre-link up */
+            ipc_update_session_state(session, IPC_SESSION_STATE_PRE_LINKUP);
+
+        } else
+        {   /* Already linkup for IPv4 before : swtich to Pre-IPv4 relocate */
+            ipc_update_session_state(session, IPC_SESSION_STATE_PRE_IPV4_RELOCATE);
+        }
+        } else
+        {
+            hif_trace_error(IPC_TR_DHCP4C_IP_UP_IND_SESSION_STATE_INCORRECT, ip_up_ind->ip_id, session, session_state);
+        }
+    } else
+    {
+        hif_trace_error(IPC_TR_DHCP4C_IP_UP_IND_FIND_NO_SESSION, ip_up_ind->ip_id);
+    }
+
+    hif_trace_info(IPC_TR_DHCP4C_IP_UP_IND_END, dhcp4c_ip_up_ind_ptr);
+}
+
+void ipc_on_dhcp4c_ip_down_ind(void *dhcp4c_ip_down_ind_ptr)
+{
+    dhcp4c_ip_down_ind_struct *ip_down_ind = (dhcp4c_ip_down_ind_struct *)dhcp4c_ip_down_ind_ptr;
+    ipc_session_t      *session;
+    ipc_session_state_e session_state;
+
+    hif_trace_info(IPC_TR_DHCP4C_IP_DOWN_IND_START, dhcp4c_ip_down_ind_ptr);
+
+
+    session = ipc_find_session_by_ip_id(ip_down_ind->ip_id, IPC_IP_TYPE_IPV4);
+
+    hif_trace_info(IPC_TR_DHCP4C_IP_DOWN_IND_FIND_SESSION_RESULT, session, ip_down_ind->ip_id);
+
+    if (session) {
+        session_state = session->state;
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        hif_trace_info(IPC_TR_DHCP4C_IP_DOWN_IND_SESSION_STATE, session, session_state);
+
+
+        /* Only handle following states */
+        if(     session_state == IPC_SESSION_STATE_PRE_LINKUP ||
+                session_state == IPC_SESSION_STATE_PRE_IPV4_RELOCATE ||
+                session_state == IPC_SESSION_STATE_LINKUP)
+        {
+        if (session_state == IPC_SESSION_STATE_PRE_LINKUP)
+        {   /* Not linkup for IPv4 yet : swtich to Pre-link up lease state */
+            ipc_update_session_state(session, IPC_SESSION_STATE_PRE_LINKUP_IPV4_LEASE);
+        } else
+        {   /* Already linkup for IPv4 before : swtich to IPv4 lease state */
+            ipc_update_session_state(session, IPC_SESSION_STATE_IPV4_LEASE);
+        }
+        } else
+        {
+            hif_trace_error(IPC_TR_DHCP4C_IP_DOWN_IND_SESSION_STATE_INCORRECT, ip_down_ind->ip_id, session, session_state);
+        }
+    } else
+    {
+        hif_trace_error(IPC_TR_DHCP4C_IP_DOWN_IND_FIND_NO_SESSION, ip_down_ind->ip_id);
+    }
+
+    hif_trace_info(IPC_TR_DHCP4C_IP_DOWN_IND_END, ip_down_ind);
+}
+
+void ipc_on_dhcp4c_packet_ind(void *dhcp4c_packet_ind_ptr)
+{
+    dhcp4c_packet_ind_struct   *packet_ind = (dhcp4c_packet_ind_struct *)dhcp4c_packet_ind_ptr;
+    ipc_session_t              *session;
+    ipc_netif_t                *netif;
+    qbm_gpd                    *gpd;
+    ipc_io_request_t           *ior;
+
+    IPC_ASSERT(packet_ind);
+    gpd = packet_ind->gpd;
+    IPC_ASSERT(gpd);
+
+    session = ipc_find_session_by_ip_id(packet_ind->ip_id, IPC_IP_TYPE_IPV4);
+
+    hif_data_trace(MD_TRC_IPC_UL_DHCP4C_PKT_SESSION, 0, gpd, packet_ind->ip_id, session);
+
+    if (session)
+    {
+        netif = session->netif;
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        hif_data_trace(MD_TRC_IPC_UL_DHCP4C_PKT_UPLINK, 0, gpd, session, netif->config.netif_id);
+
+        ior = (ipc_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(gpd);
+        kal_mem_set(ior, 0, sizeof(ipc_io_request_t));
+        ior->first_gpd      = gpd;
+        ior->last_gpd       = gpd;
+        ior->ip_type        = IPC_IP_TYPE_IPV4;
+
+        if (!ipc_uplink(netif, ior))
+        {
+            hif_trace_error(IPC_TR_DHCP4C_IP_PACKET_IND_UPLINK_NG, packet_ind->ip_id);
+            qbmt_dest_q(gpd, gpd);
+        }
+    } else
+    {
+        hif_trace_error(IPC_TR_DHCP4C_IP_PACKET_IND_FIND_NO_SESSION, packet_ind->ip_id);
+        qbmt_dest_q(gpd, gpd);
+    }
+}
+
diff --git a/mcu/middleware/hif/ipcore/src/ipc_dpfm.c b/mcu/middleware/hif/ipcore/src/ipc_dpfm.c
new file mode 100644
index 0000000..9f6acbe
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_dpfm.c
@@ -0,0 +1,565 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2017
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_dpfm.c
+ *
+ * Project:
+ * --------
+ *   UMOLYA
+ *
+ * Description:
+ * ------------
+ *   MD Direct Tethering API of IPCore
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_api.h"
+#include "mw_sap.h"
+
+#include "ipc_dpfm.h"
+#include "ipc_data.h"
+#include "ipc_utils.h"
+#include "ipc_object.h"
+#include "ipc_data_ipf.h"
+#include "ipc_debug.h"
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+#define ipc_dpfm_fill_pdn_id_into_meta(_ip_type, _mirror_des, _netif_id, _meta) \
+{                                                                              \
+    kal_uint8 _pdn_idx_v4 = ipc_session_type_hash(IPC_IP_TYPE_IPV4);           \
+    kal_uint8 _pdn_idx_v6 = ipc_session_type_hash(IPC_IP_TYPE_IPV6);           \
+    ipc_fill_session_info_into_meta(_ip_type,                                  \
+                                    _mirror_des->pdn_ids[_pdn_idx_v4],         \
+                                    _mirror_des->pdn_ids[_pdn_idx_v6],         \
+                                    _netif_id,                                 \
+                                    _meta);                                    \
+}
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Private data structure.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Private functions.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Public functions.
+ *----------------------------------------------------------------------------*/
+
+void ipc_dpfm_lan_on_did_downlink(ipc_dpfm_lan_des_t *lan_des_array)
+{
+    kal_uint32      i;
+
+    for (i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++) {
+        ipc_dpfm_lan_des_t  *lan_des = &lan_des_array[i];
+        ipc_pkt_t           pkt;
+
+        if (lan_des->is_did) {
+            IPC_ASSERT(lan_des->dst_netif_id != IPC_INVALID_NETIF_ID);
+
+            pkt.buf_type = IPC_PKT_DES_TYPE_DID;
+            pkt.did_head = lan_des->did;
+            pkt.did_tail = lan_des->did;
+
+            ipc_send_dl_pkt_in_did_internal(&pkt, NULL, lan_des->dst_netif_id);
+        }
+    }
+}
+
+/*
+ * Assumption: netif read lock is acquired.
+ */
+kal_bool ipc_dpfm_fill_did_si_from_meta(ipc_dpfm_lan_des_t *lan_des_array, lhif_meta_tbl_t *src_meta, kal_uint32 src_netif_id, ipc_netif_t *src_netif)
+{
+    kal_uint32      i;
+    ipc_meta_info_des pkt_info;
+
+    for (i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++) {
+        ipc_dpfm_lan_des_t  *lan_des = &lan_des_array[i];
+
+        if (src_netif_id == lan_des->src_netif_id) {
+            if (lan_des->is_did) {
+                pkt_info.addr = (void *)(src_meta->vrb_addr);
+                pkt_info.len = src_meta->length;
+                pkt_info.psn_countL = src_meta->psn;
+                if(!ipc_utils_fill_did_si_from_meta(lan_des->is_need_adjust_seq, lan_des->did, &(lan_des->curr_si_idx), &pkt_info, lan_des->hif_type)){
+                    return KAL_FALSE;
+                }
+                return KAL_TRUE;
+            } else {
+                hif_trace_error(IPC_TR_META_UL_DROP_FOR_LAN_DID_ALLOC_FAIL_CAUSE_DID_NULL, src_netif_id, lan_des->is_did);
+                return KAL_FALSE;
+            }
+        } else if (IPC_INVALID_NETIF_ID == lan_des->src_netif_id) {
+            /* The first lan-routed packet in the META list */
+            ipc_netif_t    *netif;
+
+            netif = src_netif->lan_netif;
+            IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+            if (netif) {
+                lan_des->did = upcm_did_alloc_one();
+                if (lan_des->did) {
+                    /* Init lan_des */
+                    lan_des->is_did = KAL_TRUE;
+                    lan_des->dst_netif_id = netif->config.netif_id;
+                    lan_des->src_netif_id = src_netif_id;
+                    lan_des->hif_type = ipc_utils_get_hif_type_by_netif_id(lan_des->dst_netif_id);
+
+                    /* Init DID: Set FLOW and COUNT-L */
+                    UPCM_DID_SET_FLOW(lan_des->did, 0);
+                    UPCM_DID_SET_COUNT_L(lan_des->did, src_meta->psn);
+
+                    pkt_info.addr = (void *)(src_meta->vrb_addr);
+                    pkt_info.len = src_meta->length;
+                    pkt_info.psn_countL = src_meta->psn;
+                    if(!ipc_utils_fill_did_si_from_meta(lan_des->is_need_adjust_seq, lan_des->did, &(lan_des->curr_si_idx), &pkt_info, lan_des->hif_type)){
+                        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+                        return KAL_FALSE;
+                    }
+                    IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+                    return KAL_TRUE;
+                } else {
+                    /* Fail to allocate DID */
+                    lan_des->is_did = KAL_FALSE;
+                    lan_des->src_netif_id = IPC_INVALID_NETIF_ID;
+
+                    IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+                    hif_trace_error(IPC_TR_META_UL_DROP_FOR_LAN_DID_ALLOC_FAIL_DID_ALLOC_NG, src_netif_id);
+                    return KAL_FALSE;
+                }
+            } else {
+                /* Fail to get netif read lock */
+                lan_des->is_did = KAL_FALSE;
+                lan_des->src_netif_id = IPC_INVALID_NETIF_ID;
+                hif_trace_error(IPC_TR_META_UL_DROP_FOR_LAN_DID_ALLOC_FAIL_NETIF_NULL, src_netif_id, src_netif->lan_netif);
+                return KAL_FALSE;
+            }
+        }
+    }
+    hif_trace_error(IPC_TR_META_UL_DROP_FOR_LAN_DEVICE_NG, src_netif_id);
+    return KAL_FALSE;
+}
+
+kal_bool ipc_dpfm_set_pdn_id_in_meta(ipc_dpfm_mirror_des_t *mirror_des_array, lhif_meta_tbl_t *meta, kal_uint32 netif_id, kal_uint8 ip_type)
+{
+    kal_uint32      i;
+
+    for (i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++) {
+        ipc_dpfm_mirror_des_t   *mirror_des = &mirror_des_array[i];
+
+        if (netif_id == mirror_des->netif_id) {
+            ipc_dpfm_fill_pdn_id_into_meta(ip_type, mirror_des, netif_id, meta);
+            return KAL_TRUE;
+        } else if (IPC_INVALID_NETIF_ID == mirror_des->netif_id) {
+            /* The first DPFM_MATCHED packet in the META list */
+            ipc_netif_t    *netif;
+
+            netif = ipc_find_netif(netif_id);
+            if (netif) {
+                /* Init mirror_des */
+                mirror_des->netif_id = netif_id;
+                mirror_des->pdn_ids[ipc_session_type_hash(IPC_IP_TYPE_IPV4)] = ipc_map_netif_to_pdn_id(netif, IPC_IP_TYPE_IPV4);
+                mirror_des->pdn_ids[ipc_session_type_hash(IPC_IP_TYPE_IPV6)] = ipc_map_netif_to_pdn_id(netif, IPC_IP_TYPE_IPV6);
+
+                ipc_dpfm_fill_pdn_id_into_meta(ip_type, mirror_des, netif_id, meta);
+                IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+                return KAL_TRUE;
+            } else {
+                /* Fail to get netif read lock */
+                mirror_des->netif_id = netif_id;
+                return KAL_FALSE;
+            }
+        }
+    }
+    return KAL_FALSE;
+}
+
+kal_bool ipc_dpfm_set_ipf_pkt_in_did_mirror_des(ipc_dpfm_mirror_des_t *mirror_des_array, ipc_pkt_des_t *packet_des, kal_uint32 netif_id)
+{
+    kal_uint32 i;
+    upcm_did_si *sit;
+    upcm_did_si *si;
+    ipf_dl_meta *meta = packet_des->ipf_meta;
+    upcm_did *did;
+    
+    for(i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++)
+    {
+        ipc_dpfm_mirror_des_t *mirror_des = &mirror_des_array[i];
+
+        if(netif_id == mirror_des->netif_id)
+        {
+            //IPF DL meta
+            IPC_ASSERT(IPC_PKT_DES_TYPE_META == packet_des->des_type);
+
+            if(mirror_des->mirror_did_tail){
+                did = mirror_des->mirror_did_tail;
+                
+                /* Check if DID SEG_NUM exceeds UPCM_DID_MAX_SIT_ENT_NUM(62) */
+                if(mirror_des->seg_num >= UPCM_DID_MAX_SIT_ENT_NUM){
+                    did = upcm_did_alloc_one();
+                    if(did){   
+                        /* Init new DID */
+                        UPCM_DID_SET_FLOW(did, 0);
+                        UPCM_DID_SET_COUNT_L(did, 0);
+                        mirror_des->seg_num = 0;
+                        mirror_des->pkt_num = 0;
+                        UPCM_DID_SET_NEXT(mirror_des->mirror_did_tail, did);
+                        mirror_des->mirror_did_tail = did;
+                    }else{
+                        /* new DID allocation is failed */
+                        return KAL_FALSE;
+                    }
+                }
+                
+                /* We don't adjust the COUNT_L, because USB/WIFI doesn't care this */
+                sit = UPCM_DID_GET_SIT_PTR(did);
+                si = &sit[mirror_des->seg_num];
+
+                UPCM_DID_SI_SET_EOL(si);
+                UPCM_DID_SI_SET_F(si);
+                UPCM_DID_SI_SET_LEN(si, meta->len);
+                UPCM_DID_SI_SET_DATAPTR(si, (void*)meta->addr);
+                UPCM_DID_SI_SET_HIF_TYPE(si, mirror_des->hif_type);
+                UPCM_DID_SI_SET_OFFSET(si, 0);
+
+                mirror_des->seg_num++;
+                mirror_des->pkt_num++;
+                UPCM_DID_SET_PKT_NUM(did, mirror_des->pkt_num);
+                UPCM_DID_SET_SEG_NUM(did, mirror_des->seg_num);
+
+                return KAL_TRUE;
+            }
+            else
+            {
+                IPC_ASSERT(KAL_FALSE);
+                return KAL_FALSE;
+            }
+
+        }
+        else if (IPC_INVALID_NETIF_ID == mirror_des->netif_id)
+        {
+            /* The first DPFM_MATCHED packet in the DID */
+            mirror_des->mirror_did_head = upcm_did_alloc_one();
+            if (mirror_des->mirror_did_head) {
+                /* Init mirror_des */
+                mirror_des->netif_id = netif_id;
+                mirror_des->hif_type = ipc_utils_get_hif_type_by_netif_id(netif_id);
+
+                IPC_ASSERT(IPC_PKT_DES_TYPE_META == packet_des->des_type);
+
+                /*Init flow, assume USB/Wifi don't need count_L and flow info*/
+                UPCM_DID_SET_FLOW(mirror_des->mirror_did_head, 0);
+                UPCM_DID_SET_COUNT_L(mirror_des->mirror_did_head, 0);
+                mirror_des->seg_num = 0;
+                mirror_des->pkt_num = 0;
+                mirror_des->mirror_did_tail = mirror_des->mirror_did_head;
+
+                sit = UPCM_DID_GET_SIT_PTR(mirror_des->mirror_did_head);
+                si = &sit[mirror_des->seg_num];
+
+                UPCM_DID_SI_SET_EOL(si);
+                UPCM_DID_SI_SET_F(si);
+                UPCM_DID_SI_SET_LEN(si, meta->len);
+                UPCM_DID_SI_SET_DATAPTR(si, (void*)meta->addr);
+                UPCM_DID_SI_SET_HIF_TYPE(si, mirror_des->hif_type);
+                UPCM_DID_SI_SET_OFFSET(si, 0);
+
+                mirror_des->seg_num++;
+                mirror_des->pkt_num++;
+                UPCM_DID_SET_PKT_NUM(mirror_des->mirror_did_head, mirror_des->pkt_num);
+                UPCM_DID_SET_SEG_NUM(mirror_des->mirror_did_head, mirror_des->seg_num); 
+
+                return KAL_TRUE;
+            }
+            else
+            {
+                /* Fail to allocate DID for direct path, we will retry allocation next time*/
+                return KAL_FALSE;
+            }
+        }
+    }
+
+    /* More than IPC_DPFM_MAX_DEVICE_NUM direct path device. */
+    IPC_ASSERT(KAL_FALSE);
+    return KAL_FALSE;
+}
+
+kal_bool ipc_dpfm_set_pkt_in_did_mirror_des(ipc_dpfm_mirror_des_t *mirror_des_array, upcm_did *did, kal_uint32 *p_curr_si_idx, kal_uint32 netif_id)
+{
+    kal_uint32      i;
+    kal_uint32      pkt_start_idx = *p_curr_si_idx;
+
+    for (i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++) {
+        ipc_dpfm_mirror_des_t   *mirror_des = &mirror_des_array[i];
+
+        if (netif_id == mirror_des->netif_id) {
+            /* Because this is copied from original DID, so the total sit number should not exceed the original one */
+            if (mirror_des->mirror_did_head) {
+                ipc_utils_pkt_set_si_hif_type(did, mirror_des->hif_type, p_curr_si_idx);
+                mirror_des->seg_num += *p_curr_si_idx - pkt_start_idx;
+                mirror_des->pkt_num ++;
+                return KAL_TRUE;
+            } else {
+                return KAL_FALSE;
+            }
+        } else if (IPC_INVALID_NETIF_ID == mirror_des->netif_id) {
+            /* The first DPFM_MATCHED packet in the DID */
+            mirror_des->mirror_did_head = upcm_did_alloc_one();
+            if (mirror_des->mirror_did_head) {
+                /* Init mirror_des */
+                mirror_des->mirror_did_tail = mirror_des->mirror_did_head;
+                mirror_des->netif_id = netif_id;
+                mirror_des->hif_type = ipc_utils_get_hif_type_by_netif_id(netif_id);
+
+                ipc_utils_pkt_set_si_hif_type(did, mirror_des->hif_type, p_curr_si_idx);
+                mirror_des->seg_num += *p_curr_si_idx - pkt_start_idx;
+                mirror_des->pkt_num ++;
+                return KAL_TRUE;
+            } else {
+                /* Fail to allocate DID for direct path */
+                mirror_des->netif_id = netif_id;
+                return KAL_FALSE;
+            }
+        }
+    }
+
+    /* More than IPC_DPFM_MAX_DEVICE_NUM direct path device. */
+    IPC_ASSERT(KAL_FALSE);
+    return KAL_FALSE;
+}
+
+void ipc_dpfm_mirror_did(ipc_dpfm_mirror_des_t *mirror_des, upcm_did *src_did)
+{
+    kal_mem_cpy(mirror_des->mirror_did_head, src_did, sizeof(upcm_did));
+
+    UPCM_DID_SET_PKT_NUM(mirror_des->mirror_did_head, mirror_des->pkt_num);
+    UPCM_DID_SET_SEG_NUM(mirror_des->mirror_did_head, mirror_des->seg_num);
+}
+
+void ipc_dpfm_push_did_to_dpfm_queue(upcm_did *did, kal_uint32 pdn_id)
+{
+    kal_bool to_send_msg;
+
+    ipc_did_enqueue_dpfm_queue(did, did, pdn_id, IPC_DATA_DID_TAIL);
+
+    /* Send ILM to IPCore for processing DL queue */
+    to_send_msg = ipc_data_check_and_set_dl_ilm_flag();
+
+    if (to_send_msg) {
+        msg_send6(  kal_get_active_module_id(), /* src_mod_id */
+                    MOD_IPCORE, /* dest_mod_id */
+                    IPCORE_DATAPATH_SAP, /* sap_id */
+                    MSG_ID_IPCORE_PROCESS_DL_QUEUE_REQ, /* msg_id */
+                    NULL, /* local_para_ptr */
+                    NULL); /* peer_buff_ptr */
+    }
+}
+
+kal_bool
+ipc_dpfm_check_route(
+    kal_bool            uplink,
+    ipc_pkt_des_t      *pkt_des,
+    kal_uint32          netif_id)
+{
+    ipc_packet_info_t  *packet_info;
+    kal_bool    ret = KAL_FALSE;
+    kal_uint32  out_netif_id = 0;
+
+    IPC_ASSERT(pkt_des);
+
+    /* Only when DPFM is enabled, we need to check packet route. */
+    /* In inactive case, IPCore still need forwarding special packet (DPFM delet filter ACK) to DPFM */
+    if(IPC_DPFM_IS_ACTIVE() || (uplink && ( DPFM_PKT_TYPE_FILTER_DEL_ACK == DPFM_GET_PKT_TYPE_FROM_PSN(pkt_des->meta->psn)))){
+        packet_info = pkt_des->packet_info;
+
+        /* For NOT_MATCHED & BWM_MATCHED cases, check DPFM routing. */
+        HIF_SWLA_START("IM2");
+        ret = IPC_QUERY_DPFM_ROUTE(uplink, pkt_des->ip_type, pkt_des, netif_id, &out_netif_id);
+        HIF_SWLA_STOP("IM2");
+        packet_info->out_netif_id = out_netif_id;
+    }
+
+    return ret;
+}
+
+/* Return TRUE means need packet info */
+kal_bool ipc_dpfm_need_pkt_info(kal_bool is_uplink, ipc_pkt_des_t *pkt_des)
+{
+    lhif_meta_tbl_t *lhif_meta;     //UL
+    ipf_dl_meta *ipf_meta;          //DL
+    kal_bool result = KAL_TRUE;
+
+    if(is_uplink)
+    {
+        lhif_meta = (lhif_meta_tbl_t*) pkt_des->meta;
+        switch(lhif_meta->mr)
+        {
+            case IPC_HPC_MR_DPFM_MATCH:
+            case IPC_HPC_MR_DPFM_MATCH_BUT_NO_NAT:
+                result = KAL_FALSE;
+                break;
+            case IPC_HPC_MR_MATCH:
+            case IPC_HPC_MR_NEW:
+            case IPC_HPC_MR_UNKNOWN:
+                result = KAL_TRUE;
+                break;
+            default:
+                IPC_ASSERT(0);
+                break;
+        }
+    }
+    else
+    {
+        if (IPC_PKT_DES_TYPE_META == pkt_des->des_type) {
+            ipf_meta = (ipf_dl_meta*) pkt_des->ipf_meta;
+            switch(ipf_meta->mr)
+            {
+                case IPC_IPF_MR_DPFM_MATCH:
+                case IPC_IPF_MR_DPFM_MATCH_BUT_NO_NAT:
+                case IPC_IPF_MR_DPFM_OPEN_AND_DPFM_NOT_MATCH:
+                    result = KAL_FALSE;
+                    break;
+                case IPC_IPF_MR_FILTER_MATCH:
+                case IPC_IPF_MR_UNKNOWN_HEADER:
+                    result = KAL_TRUE;
+                    break;
+                default:
+                    IPC_ASSERT(0);
+                    break;
+            }
+        }
+    }
+    return result;
+}
+
+/**** Legacy code for GPD/SPD mode ****/
+qbm_spd *
+ipc_dpfm_mirror_spd(
+    qbm_spd            *p_origin_spd,
+    kal_bool           *mirror_spd_pie_idx,
+    kal_uint8           dpfm_matched_num)
+{
+    IPC_ASSERT(0);
+    return NULL;
+}
+
+void
+ipc_dpfm_push_gpd_to_routing_queue(
+    kal_bool            uplink,
+    kal_uint32          netif_id,
+    qbm_gpd            *gpd)
+{
+    IPC_ASSERT(0);
+    return;
+}
+/**** Legacy code for GPD/SPD mode ****/
+
+
+#endif
diff --git a/mcu/middleware/hif/ipcore/src/ipc_filter.c b/mcu/middleware/hif/ipcore/src/ipc_filter.c
new file mode 100644
index 0000000..0b7f163
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_filter.c
@@ -0,0 +1,4172 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_filter.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   Packet filtering.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "mw_sap.h"
+#include "ipc_packet_parser.h"
+#include "ipc_fragment_export.h"
+#include "ipc_defs.h"
+#include "ipc_debug.h"
+#include "ipc_utils.h"
+#include "ipc_filter.h"
+#include "ipc_filter_priority.h"
+#include "qmu_bm_util.h"
+#include "hif_mw_msgid.h"
+#if defined(__IPF_SUPPORT__)
+#include "ipc_data_ipf.h"
+#include "ipfc_export_plugin_dl_filter.h"
+#endif
+#include "dpcopro_custom.h"
+#include "upcm.h"
+
+#if defined (__GEN97_ESL_SPEEDUP__)
+/* reduce mips in ESL by skipping the memory init */
+#define kal_mem_set(a,b,c)
+#endif
+
+typedef struct _ipc_filter_list_t {
+    kal_uint32              count;
+    ipc_filter_t           *filter_head;
+    kal_uint8               ip_type;
+} ipc_filter_list_t;
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+kal_uint32  ipc_dl_valid_packet_len_s;
+kal_bool    ipc_is_support_ccci_fast_header_s;
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    /* For MD Direct Tethering packet routing queue */
+    ipc_dpfm_routing_packet_list_t  ipc_dpfm_packet_routing_queue[2][IPC_MAX_NETIF_CNT];
+    kal_bool                        ipc_dpfm_queue_non_empty[2];
+#endif
+#if defined(__MD97__)
+    static ipc_data_rq_info_list       g_rq_info_list = {0};
+#endif
+kal_uint8 g_ipc_dl_mode = IPC_HW_DL_MODE;
+/*------------------------------------------------------------------------------
+ * Private variables.
+ *----------------------------------------------------------------------------*/
+static ipc_filter_t         ipc_filter_pool_s[IPC_MAX_FILTER_CNT];
+static kal_bool             ipc_filter_id_s[IPC_MAX_FILTER_CNT];
+static kal_uint32           ipc_filter_cnt_s;
+static kal_uint32           ipc_filter_magic_number_s;
+static kal_int32            ipc_deregistering_filter_id_s[IPC_MAX_FILTER_CNT];
+static kal_uint32           ipc_deregistering_filter_cnt_s;
+static kal_int32            ipc_retry_deregistering_filter_id_s[IPC_MAX_FILTER_CNT];
+static kal_uint32           ipc_retry_deregistering_filter_cnt_s;
+static kal_uint32           g_ipc_filter_max_hw_entry;
+static kal_uint32           g_ipc_dereg_filter_cnt_v4;
+static kal_uint32           g_ipc_dereg_filter_cnt_v6;
+static kal_uint32           g_ipc_filter_recerved_cnt;
+static kal_bool             g_is_sw_path = KAL_FALSE;
+
+/* For downlink */
+static ipc_filter_list_t    ipc_dl_registering_filter_list_s[1];
+static ipc_filter_list_t    ipc_dl_v4_filter_list_s[1];
+static ipc_filter_list_t    ipc_dl_v6_filter_list_s[1];
+/* For uplink */
+static ipc_filter_list_t    ipc_ul_registering_filter_list_s[1];
+static ipc_filter_list_t    ipc_ul_v4_filter_list_s[1];
+static ipc_filter_list_t    ipc_ul_v6_filter_list_s[1];
+
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+#define ipc_next_filter_hash(_ip_type) ((((_ip_type) & 0x1) == 1) ? 1 : 0)
+
+#define _PRIORITY_OF_FILTER(_filter) (_filter->rules.priority)
+
+#define _FEATURES_CONTAIN(_rules, _name) \
+        (IPC_FILTER_FEATURE_ ## _name == ((_rules)->features & IPC_FILTER_FEATURE_ ## _name))
+
+#define _RULES_CONTAIN(_rules, _name) \
+        (IPC_FILTER_BY_ ## _name == ((_rules)->valid_fields & IPC_FILTER_BY_ ## _name))
+
+#define _RULES_CONTAIN_IPV4(_rules) \
+        (IPC_IP_TYPE_IPV4 == (_rules)->ip_type || IPC_IP_TYPE_MIXED == (_rules)->ip_type)
+
+#define _RULES_CONTAIN_IPV6(_rules) \
+        (IPC_IP_TYPE_IPV6 == (_rules)->ip_type || IPC_IP_TYPE_MIXED == (_rules)->ip_type)
+
+#define _IS_UNSUPPORTED_PROTOCOL(_protocol) \
+        ((IPC_HDR_PROT_UDP != (_protocol)) && \
+         (IPC_HDR_PROT_TCP != (_protocol)) && \
+         (IPC_HDR_PROT_ICMP != (_protocol)) && \
+         (IPC_HDR_PROT_ICMPV6 != (_protocol)) && \
+         (IPC_HDR_PROT_IGMP != (_protocol)) && \
+         (IPC_HDR_PROT_ESP != (_protocol)))
+
+/*------------------------------------------------------------------------------
+ * Private function.
+ *----------------------------------------------------------------------------*/
+
+static void ipc_filter_list_dump(ipc_filter_list_t *list)
+{
+    kal_uint32 i = 0;
+    kal_uint8 filter_id_list[IPC_MAX_FILTER_CNT]={0};
+    ipc_filter_t *p_cur_filter = NULL;
+
+    if(NULL == list){
+        return;
+    }
+
+    p_cur_filter = list->filter_head;
+    for(i = 0; (i < list->count) && p_cur_filter; i++){
+        filter_id_list[i] = p_cur_filter->filter_id;
+        p_cur_filter = p_cur_filter->next_filter_map[ipc_next_filter_hash(list->ip_type)];
+    }
+
+    for(i = 0; (i+3) < list->count; i+=4){
+        hif_trace_info(IPC_TR_FILTER_ID_DUMP_4, filter_id_list[i], filter_id_list[i+1], filter_id_list[i+2], filter_id_list[i+3]);
+    }
+    switch (list->count % 4){
+        case 1:
+            hif_trace_info(IPC_TR_FILTER_ID_DUMP_1, filter_id_list[i]);
+            break;
+        case 2:
+            hif_trace_info(IPC_TR_FILTER_ID_DUMP_2, filter_id_list[i], filter_id_list[i+1]);
+            break;
+        case 3:
+            hif_trace_info(IPC_TR_FILTER_ID_DUMP_3, filter_id_list[i], filter_id_list[i+1], filter_id_list[i+2]);
+            break;
+        default:
+            break;
+    }
+}
+
+static void ipc_filter_list_dump_all()
+{
+    hif_trace_info(IPC_TR_FILTER_CNT, ipc_ul_v4_filter_list_s->count, ipc_dl_v4_filter_list_s->count, ipc_ul_v6_filter_list_s->count, ipc_dl_v6_filter_list_s->count);
+
+    if(0 < ipc_ul_v4_filter_list_s->count){
+        hif_trace_info(IPC_TR_FILTER_ID_DUMP_INFO_v4, KAL_TRUE, ipc_ul_v4_filter_list_s->count);
+        ipc_filter_list_dump(ipc_ul_v4_filter_list_s);
+    }
+    if(0 < ipc_dl_v4_filter_list_s->count){
+        hif_trace_info(IPC_TR_FILTER_ID_DUMP_INFO_v4, KAL_FALSE, ipc_dl_v4_filter_list_s->count);
+        ipc_filter_list_dump(ipc_dl_v4_filter_list_s);
+    }
+    if(0 < ipc_ul_v6_filter_list_s->count){
+        hif_trace_info(IPC_TR_FILTER_ID_DUMP_INFO_v6, KAL_TRUE, ipc_ul_v6_filter_list_s->count);
+        ipc_filter_list_dump(ipc_ul_v6_filter_list_s);
+    }
+    if(0 < ipc_dl_v6_filter_list_s->count){
+        hif_trace_info(IPC_TR_FILTER_ID_DUMP_INFO_v6, KAL_FALSE, ipc_dl_v6_filter_list_s->count);
+        ipc_filter_list_dump(ipc_dl_v6_filter_list_s);
+    }
+}
+
+static void ipc_filter_dump_invalid_len_pkt(ipc_pkt_des_t *p_pkt_des)
+{
+    kal_uint8 *p_packet = p_pkt_des->packet;
+    kal_uint32 pkt_len = p_pkt_des->packet_len;
+
+    ASSERT(NULL != p_pkt_des);
+
+    /* packet info */
+    switch (p_pkt_des->des_type) {
+        case IPC_PKT_DES_TYPE_DID:
+            hif_data_trace(MD_TRC_IPC_DL_INVALID_LEN_CHK_DID, UPCM_DID_GET_FLOW(p_pkt_des->did), p_pkt_des->psn, pkt_len, ipc_dl_valid_packet_len_s);
+            break;
+        case IPC_PKT_DES_TYPE_GPD:
+        case IPC_PKT_DES_TYPE_SPD:
+            hif_data_trace(MD_TRC_IPC_DL_INVALID_LEN_CHK, p_pkt_des->gpd, p_pkt_des->bd, pkt_len, ipc_dl_valid_packet_len_s);
+            break;
+        default:
+            /* can't reach here */
+            IPC_ASSERT(KAL_FALSE);
+            break;
+    }
+
+    /* dump ip header */
+    hif_data_trace(MD_TRC_IPC_DL_INVALID_LEN_PKT_IP_HDR, 0, IPC_NE_GET_4B(p_packet));
+    hif_data_trace(MD_TRC_IPC_DL_INVALID_LEN_PKT_IP_HDR, 1, IPC_NE_GET_4B(p_packet+4));
+    hif_data_trace(MD_TRC_IPC_DL_INVALID_LEN_PKT_IP_HDR, 2, IPC_NE_GET_4B(p_packet+8));
+    hif_data_trace(MD_TRC_IPC_DL_INVALID_LEN_PKT_IP_HDR, 3, IPC_NE_GET_4B(p_packet+12));
+    hif_data_trace(MD_TRC_IPC_DL_INVALID_LEN_PKT_IP_HDR, 4, IPC_NE_GET_4B(p_packet+16));
+}
+
+static void ipc_filter_dump_matched_pkt(kal_bool is_uplink,
+                                        ipc_pkt_des_t *p_pkt_des,
+                                        kal_uint8 match_result,
+                                        kal_uint8 dpfm_rule_id)
+{
+    ASSERT(NULL != p_pkt_des);
+
+    switch (p_pkt_des->des_type) {
+        case IPC_PKT_DES_TYPE_META:
+            hif_data_trace(MD_TRC_IPC_UL_PKT_FILTER_RESULT_META, p_pkt_des->meta->psn, match_result, dpfm_rule_id);
+            break;
+        case IPC_PKT_DES_TYPE_DID:
+            hif_data_trace(MD_TRC_IPC_DL_PKT_FILTER_RESULT_DID, UPCM_DID_GET_FLOW(p_pkt_des->did), p_pkt_des->psn, match_result, dpfm_rule_id);
+            break;
+        case IPC_PKT_DES_TYPE_GPD:
+            hif_data_trace(MD_TRC_IPC_PKT_FILTER_RESULT_GPD, is_uplink, p_pkt_des->gpd, match_result, dpfm_rule_id);
+            break;
+        case IPC_PKT_DES_TYPE_SPD:
+            hif_data_trace(MD_TRC_IPC_PKT_FILTER_RESULT_SPD, is_uplink, match_result, dpfm_rule_id);
+            break;
+        default:
+            /* can't reach here */
+            IPC_ASSERT(KAL_FALSE);
+            break;
+    }
+}
+
+static void ipc_filter_dump_pkt(kal_bool is_uplink,
+                                ipc_pkt_des_t *p_des,
+                                ipc_pkt_do_filter_result_e match_result,
+                                kal_uint8 dpfm_rule_id)
+{
+    if (NULL == p_des) {
+        /* TODO : error log */
+        return;
+    }
+
+    switch (match_result) {
+        case IPC_PKT_DO_FILTER_INVALID_LEN:
+            ipc_filter_dump_invalid_len_pkt(p_des);
+            break;
+        case IPC_PKT_DO_FILTER_MATCHED:
+        case IPC_PKT_DO_FILTER_BWM_MATCHED:
+        case IPC_PKT_DO_FILTER_DPFM_MATCHED:
+        case IPC_PKT_DO_FILTER_HANDLE_FRAG:
+            ipc_filter_dump_matched_pkt(is_uplink, p_des, match_result, dpfm_rule_id);
+            break;
+        default:
+            break;
+    }
+}
+
+static kal_bool ipc_filter_chk_rules(ipc_data_path_direction_e data_path_direct, ipc_filter_rules_t *rules)
+{
+    IPC_ASSERT(NULL != rules);
+
+    if (_FEATURES_CONTAIN(rules, WC)) {
+        /* Pass other checking if it's WC filter. */
+        return KAL_TRUE;
+    }
+
+    if (0 == rules->valid_fields) {
+        hif_trace_error(IPC_TR_INVALID_RULES_ZERO_VALID_FIELD);
+        return KAL_FALSE;
+    }
+
+    if ((UL_DIRECT == data_path_direct) &&
+        (_RULES_CONTAIN(rules, EBI)    /* EBI is used for downlink filter only */||
+         _RULES_CONTAIN(rules, PDN_ID) /* PDN ID is used in downlink filter only */)) {
+        hif_trace_error(IPC_TR_INVALID_RULES_FOR_UL, data_path_direct, rules->valid_fields, rules->ip_type);
+        return KAL_FALSE;
+    }
+
+    if ((DL_DIRECT == data_path_direct) &&
+         !( _RULES_CONTAIN(rules, EBI) || _RULES_CONTAIN(rules, PDN_ID) || _FEATURES_CONTAIN(rules, PFM_DL) || _RULES_CONTAIN(rules, NETIF_ID) ||
+         _FEATURES_CONTAIN(rules, IG_PN))) {
+        /*
+         * [Gen93] downlink filter must contain either EBI or PDN_ID in filter rule,
+         * except the one registered through PFM. (to support Garbage Filter)
+         */
+        hif_trace_error(IPC_TR_INVALID_RULES_FOR_DL, data_path_direct, rules->valid_fields, rules->ip_type);
+        return KAL_FALSE;
+    }
+
+    if ((IPC_IP_TYPE_IPV4 == rules->ip_type) &&
+        (((UL_DIRECT == data_path_direct) ||
+        ((DL_DIRECT == data_path_direct) && !_RULES_CONTAIN(rules, EBI))) &&
+         !_RULES_CONTAIN(rules, NETIF_ID) &&
+         !_RULES_CONTAIN(rules, PROTOCOL) &&
+         !_RULES_CONTAIN(rules, SRC_PORT) && !_RULES_CONTAIN(rules, DST_PORT) &&
+         !_RULES_CONTAIN(rules, SRC_IPV4) && !_RULES_CONTAIN(rules, DST_IPV4) &&
+         !_RULES_CONTAIN(rules, ICMPV4_TYPE))) {
+        hif_trace_error(IPC_TR_INVALID_RULES_FOR_IPV4, data_path_direct, rules->valid_fields, rules->ip_type);
+        return KAL_FALSE;
+    }
+
+    if ((IPC_IP_TYPE_IPV6 == rules->ip_type) &&
+        (((UL_DIRECT == data_path_direct) ||
+        ((DL_DIRECT == data_path_direct) && !_RULES_CONTAIN(rules, EBI))) &&
+         !_RULES_CONTAIN(rules, NETIF_ID) &&
+         !_RULES_CONTAIN(rules, PROTOCOL) &&
+         !_RULES_CONTAIN(rules, SRC_PORT) && !_RULES_CONTAIN(rules, DST_PORT) &&
+         !_RULES_CONTAIN(rules, SRC_IPV6) && !_RULES_CONTAIN(rules, DST_IPV6) &&
+         !_RULES_CONTAIN(rules, ICMPV6_TYPE))) {
+        hif_trace_error(IPC_TR_INVALID_RULES_FOR_IPV6, data_path_direct, rules->valid_fields, rules->ip_type);
+        return KAL_FALSE;
+    }
+
+    /* Make sure user will both set L4 field value and protocol value*/
+    if ( _RULES_CONTAIN(rules, SRC_PORT) || _RULES_CONTAIN(rules, DST_PORT)) {
+        if (!((_RULES_CONTAIN(rules, PROTOCOL) && ( (IPC_HDR_PROT_UDP == rules->protocol) || (IPC_HDR_PROT_TCP == rules->protocol))))) {
+            hif_trace_error(IPC_TR_INVALID_RULES_FOR_L4_INFO, data_path_direct, rules->valid_fields, rules->ip_type);
+            return KAL_FALSE;
+        }
+    }
+
+    if (_RULES_CONTAIN(rules, ICMPV4_TYPE)) {
+        if (! (_RULES_CONTAIN(rules, PROTOCOL) && (IPC_HDR_PROT_ICMP == rules->protocol) && (IPC_IP_TYPE_IPV4 == rules->ip_type))) {
+            hif_trace_error(IPC_TR_INVALID_RULES_FOR_L4_INFO, data_path_direct, rules->valid_fields, rules->ip_type);
+            return KAL_FALSE;
+        }
+    }
+
+    if (_RULES_CONTAIN(rules, ICMPV6_TYPE)) {
+        if (! (_RULES_CONTAIN(rules, PROTOCOL) && (IPC_HDR_PROT_ICMPV6 == rules->protocol) && (IPC_IP_TYPE_IPV6 == rules->ip_type))) {
+            hif_trace_error(IPC_TR_INVALID_RULES_FOR_L4_INFO, data_path_direct, rules->valid_fields, rules->ip_type);
+            return KAL_FALSE;
+        }
+    }
+
+    if ( _RULES_CONTAIN(rules, PROTOCOL) && _IS_UNSUPPORTED_PROTOCOL(rules->protocol)) {
+        hif_trace_error(IPC_TR_INVALID_RULES_FOR_UNSUPPORTED_PROTOCOL, rules->protocol);
+        return KAL_FALSE;
+    }
+
+    /* Make sure user will set protocol value when fragment feature is set*/
+    if (_FEATURES_CONTAIN(rules, FRAG)) {
+        if (!_RULES_CONTAIN(rules, PROTOCOL)) {
+            hif_trace_error(IPC_TR_INVALID_RULES_FOR_FRAG, data_path_direct, rules->valid_fields, rules->ip_type, rules->features);
+            return KAL_FALSE;
+        }
+    }
+
+    if (_RULES_CONTAIN(rules, SPI)) {
+        if (!(_RULES_CONTAIN(rules, PROTOCOL) && (IPC_HDR_PROT_ESP == rules->protocol))) {
+            hif_trace_error(IPC_TR_INVALID_RULES_FOR_SPI, data_path_direct, rules->valid_fields, rules->ip_type, rules->features);
+            return KAL_FALSE;
+        }
+    }
+
+    if (_FEATURES_CONTAIN(rules, CUST_FILTER)) {
+        if (NULL == rules->cust_cbk_func) {
+            hif_trace_error(IPC_TR_INVALID_RULES_FOR_CUST_FILTER, data_path_direct, rules->valid_fields, rules->ip_type, rules->features);
+            return KAL_FALSE;
+        }
+    }
+
+    return KAL_TRUE;
+}
+
+static kal_int32 ipc_new_filter_id(kal_bool uplink,
+                                   ipc_filter_rules_t *rules,
+                                   void *callback_func,
+                                   module_type module_id)
+{
+    kal_uint32 i = 0;
+
+    IPC_ASSERT(KAL_FALSE == kal_if_hisr());
+
+    if ((NULL == rules) ||
+        (!(_FEATURES_CONTAIN(rules, BWM) ||
+        _FEATURES_CONTAIN(rules, IPV6_DPFM)) && NULL == callback_func && MOD_NIL == module_id)) {
+        hif_trace_error(IPC_TR_NEW_FILTER_INVALID_PARAMS, rules, callback_func, module_id);
+        goto fail;
+    }
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    if (ipc_filter_cnt_s >= IPC_MAX_FILTER_CNT) {
+        IPC_SPIN_UNLOCK(ipc_spinlock_g);
+        goto fail;
+    }
+
+    for (i = 0; i < IPC_MAX_FILTER_CNT; i++) {
+        if (KAL_FALSE == ipc_filter_id_s[i]) {
+            ipc_filter_cnt_s++;
+            ipc_filter_id_s[i] = KAL_TRUE;
+            ipc_filter_magic_number_s++;
+            IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+            return i;
+        }
+    }
+
+fail :
+    hif_trace_error(IPC_TR_NEW_FILTER_UNAVAILABLE);
+    ipc_ut_set_error(IPC_UT_REGISTER_FILTER_NG);
+    return IPC_INVALID_FILTER_ID;
+}
+
+static ipc_filter_t *ipc_new_filter(kal_int32 filter_id,
+                                    ipc_filter_t *p_filter_pool,
+                                    ipc_filter_rules_t *p_rules,
+                                    ipc_filter_ntfy_ctxt_t *p_ntfy_ctxt)
+{
+    ipc_filter_t *filter = NULL;
+
+    IPC_ASSERT(NULL != p_filter_pool);
+    IPC_ASSERT(NULL != p_rules);
+    IPC_ASSERT(NULL != p_ntfy_ctxt);
+    filter = p_filter_pool + filter_id;
+
+    IPC_ASSERT(filter->filter_id == IPC_INVALID_FILTER_ID);
+    filter->filter_id = filter_id;
+    filter->is_updated_to_list = KAL_FALSE;
+
+    kal_mem_cpy(&(filter->rules), p_rules, sizeof(ipc_filter_rules_t));
+
+    IPC_MASK_PROTOID_ON_PDNID(filter->rules.pdn_id, filter->rules.proto_idx);
+    IPC_MASK_PROTOID_ON_PDNID(filter->rules.ebi, filter->rules.proto_idx);
+
+    if ((IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO == p_ntfy_ctxt->ntfy_type) ||
+        (IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO == p_ntfy_ctxt->ntfy_type)) {
+        filter->callback_with_info = KAL_TRUE;
+    } else {
+        filter->callback_with_info = KAL_FALSE;
+    }
+
+    if (filter->callback_with_info) {
+        filter->callback_func = p_ntfy_ctxt->ntfy_mod.with_info_cbk_func;
+    } else {
+        filter->callback_func = p_ntfy_ctxt->ntfy_mod.cbk_func;
+    }
+
+    filter->module_id = p_ntfy_ctxt->ntfy_mod.cbk_mod;
+
+    if (MOD_NIL == p_ntfy_ctxt->ntfy_mod.cbk_mod) {
+        filter->callback_context = p_ntfy_ctxt->p_ntfy_args;
+        filter->module_context = NULL;
+    } else {
+        filter->callback_context = filter;
+        filter->module_context = p_ntfy_ctxt->p_ntfy_args;
+    }
+
+    filter->cust_cbk_func = p_rules->cust_cbk_func;
+    filter->p_cust_cbk_args = p_rules->p_cust_cbk_args;
+    filter->is_bypass_sync_hw = KAL_FALSE;
+
+    kal_mem_set(filter->next_filter_map, 0, sizeof(filter->next_filter_map));
+    return filter;
+}
+
+static void ipc_del_filter(ipc_filter_t *filter)
+{
+
+    if (filter) {
+        IPC_SPIN_LOCK(ipc_spinlock_g);
+        IPC_ASSERT(ipc_filter_cnt_s > 0);
+        ipc_filter_cnt_s--;
+        if ((0 <= filter->filter_id) && (IPC_MAX_FILTER_CNT > filter->filter_id)) {
+            ipc_filter_id_s[filter->filter_id] = KAL_FALSE;
+        }
+        ipc_filter_magic_number_s++;
+        filter->filter_id = IPC_INVALID_FILTER_ID;
+        filter->is_bypass_sync_hw = KAL_FALSE;
+        IPC_SPIN_UNLOCK(ipc_spinlock_g);
+    } else {
+        hif_trace_error(IPC_TR_DEL_FILTER_INVALID_OBJECT, filter);
+    }
+}
+
+static ipc_filter_t *ipc_find_filter_by_id(ipc_filter_t *filter_pool, kal_int32 filter_id)
+{
+    if ((0 <= filter_id) && (IPC_MAX_FILTER_CNT > filter_id)) {
+        return (filter_pool + filter_id);
+    } else {
+        return NULL;
+    }
+}
+
+static kal_bool ipc_add_filter_to_reg_list(ipc_filter_list_t *list,
+                                           ipc_filter_t *filter)
+{
+    ipc_filter_t *tmp = NULL;
+    kal_bool is_first_filter = KAL_FALSE;
+
+    IPC_ASSERT(list && filter);
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    is_first_filter = (NULL == list->filter_head);
+    tmp = list->filter_head;
+    list->filter_head = filter;
+    list->count++;
+    filter->next_filter_map[0] = tmp;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    return is_first_filter;
+}
+
+static void ipc_get_filter_list_from_reg_list(ipc_filter_t **ul_filter,
+                                              ipc_filter_t **dl_filter)
+{
+    IPC_ASSERT(ul_filter && dl_filter);
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    *ul_filter = ipc_ul_registering_filter_list_s->filter_head;
+    ipc_ul_registering_filter_list_s->filter_head = NULL;
+    ipc_ul_registering_filter_list_s->count = 0;
+
+    *dl_filter = ipc_dl_registering_filter_list_s->filter_head;
+    ipc_dl_registering_filter_list_s->filter_head = NULL;
+    ipc_dl_registering_filter_list_s->count = 0;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+}
+
+static void ipc_add_filter_to_list(ipc_filter_list_t *list,
+                                   ipc_filter_t *filter,
+                                   kal_uint8 ip_type)
+{
+    ipc_filter_t *curr_filter = NULL;
+    ipc_filter_t *prev_filter = NULL;
+
+    IPC_ASSERT(NULL != list);
+    IPC_ASSERT(NULL != filter);
+
+    prev_filter = NULL;
+    if (list) {
+        if (!list->filter_head) {
+            list->filter_head = filter;
+        } else {
+            curr_filter = list->filter_head;
+            while (curr_filter) {
+                if (_PRIORITY_OF_FILTER(curr_filter) >= _PRIORITY_OF_FILTER(filter)) {
+                    /* Insert the filter to this position. */
+                    if (prev_filter) {
+                        /* It's not the head of the list. */
+                        filter->next_filter_map[ipc_next_filter_hash(ip_type)] = curr_filter;
+                        prev_filter->next_filter_map[ipc_next_filter_hash(ip_type)] = filter;
+                    } else {
+                        /* Insert to the head of the list. */
+                        filter->next_filter_map[ipc_next_filter_hash(ip_type)] = curr_filter;
+                        list->filter_head = filter;
+                    }
+                    break;
+                } else if (!curr_filter->next_filter_map[ipc_next_filter_hash(ip_type)]) {
+                    /* The current filter is the last one. Insert the filter after it. */
+                    curr_filter->next_filter_map[ipc_next_filter_hash(ip_type)] = filter;
+                    break;
+                } else {
+                    /* Keep searching */
+                    prev_filter = curr_filter;
+                    curr_filter = curr_filter->next_filter_map[ipc_next_filter_hash(ip_type)];
+                }
+            }
+        }
+
+        IPC_SPIN_LOCK(ipc_spinlock_g);
+        list->count++;
+        /* SW_PATH don't check reserved_cnt */
+        if (0 != g_ipc_filter_max_hw_entry) {
+            if (IPC_IP_TYPE_IPV4 == filter->rules.ip_type) {
+                if (0 < g_ipc_filter_recerved_cnt) {
+                    g_ipc_filter_recerved_cnt = g_ipc_filter_recerved_cnt - 1;
+                } else {
+                    /* equal 0 */
+                    g_ipc_filter_recerved_cnt = 0;
+                    hif_trace_error(IPC_TR_UNEXPECTED_FILTER_CHK_RESULT, __FUNCTION__, __LINE__, g_ipc_dereg_filter_cnt_v4, g_ipc_dereg_filter_cnt_v6, g_ipc_filter_recerved_cnt);
+                }
+            } else {
+                if (1 < g_ipc_filter_recerved_cnt) {
+                    g_ipc_filter_recerved_cnt = g_ipc_filter_recerved_cnt - 2;
+                } else {
+                    /* equal 0/1 */
+                    g_ipc_filter_recerved_cnt = 0;
+                    hif_trace_error(IPC_TR_UNEXPECTED_FILTER_CHK_RESULT, __FUNCTION__, __LINE__, g_ipc_dereg_filter_cnt_v4, g_ipc_dereg_filter_cnt_v6, g_ipc_filter_recerved_cnt);
+                }
+            }
+        } else {
+            g_ipc_filter_recerved_cnt = 0;
+            hif_trace_error(IPC_TR_UNEXPECTED_FILTER_CHK_RESULT, __FUNCTION__, __LINE__, g_ipc_dereg_filter_cnt_v4, g_ipc_dereg_filter_cnt_v6, g_ipc_filter_recerved_cnt);
+        }
+        IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    } else {
+        IPC_ASSERT(KAL_FALSE);
+    }
+}
+
+static void ipc_filter_rm_filter_from_list(ipc_filter_list_t *list,
+                                           ipc_filter_t *filter,
+                                           kal_uint8 ip_type)
+{
+    ipc_filter_t *curr_filter = NULL;
+    ipc_filter_t *prev_filter = NULL;
+
+    prev_filter = NULL;
+    if (list) {
+        curr_filter = list->filter_head;
+        while (curr_filter) {
+            if (curr_filter == filter) {
+                /* Found the filter! */
+                if (prev_filter) {
+                    /* It's not the head of the list. */
+                    prev_filter->next_filter_map[ipc_next_filter_hash(ip_type)] = curr_filter->next_filter_map[ipc_next_filter_hash(ip_type)];
+                } else {
+                    /* Remove the head of the list. */
+                    list->filter_head = curr_filter->next_filter_map[ipc_next_filter_hash(ip_type)];
+                }
+
+                IPC_SPIN_LOCK(ipc_spinlock_g);
+                list->count--;
+                /* SW_PATH don't check reserved_cnt */
+                if (0 != g_ipc_filter_max_hw_entry) {
+                    if (IPC_IP_TYPE_IPV4 == curr_filter->rules.ip_type) {
+                        if (0 < g_ipc_dereg_filter_cnt_v4) {
+                            g_ipc_dereg_filter_cnt_v4--;
+                        } else {
+                            /* equal 0 */
+                            g_ipc_dereg_filter_cnt_v4 = 0;
+                            hif_trace_error(IPC_TR_UNEXPECTED_FILTER_CHK_RESULT, __FUNCTION__, __LINE__, g_ipc_dereg_filter_cnt_v4, g_ipc_dereg_filter_cnt_v6, g_ipc_filter_recerved_cnt);
+                        }
+                    } else {
+                        if (0 < g_ipc_dereg_filter_cnt_v6) {
+                            g_ipc_dereg_filter_cnt_v6--;
+                        } else {
+                            /* equal 0 */
+                            g_ipc_dereg_filter_cnt_v6 = 0;
+                            hif_trace_error(IPC_TR_UNEXPECTED_FILTER_CHK_RESULT, __FUNCTION__, __LINE__, g_ipc_dereg_filter_cnt_v4, g_ipc_dereg_filter_cnt_v6, g_ipc_filter_recerved_cnt);
+                        }
+                    }
+                } else {
+                    g_ipc_dereg_filter_cnt_v4 = 0;
+                    g_ipc_dereg_filter_cnt_v6 = 0;
+                    hif_trace_error(IPC_TR_UNEXPECTED_FILTER_CHK_RESULT, __FUNCTION__, __LINE__, g_ipc_dereg_filter_cnt_v4, g_ipc_dereg_filter_cnt_v6, g_ipc_filter_recerved_cnt);
+                }
+                IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+                break;
+            } else {
+                /* Keep searching */
+                prev_filter = curr_filter;
+                curr_filter = curr_filter->next_filter_map[ipc_next_filter_hash(ip_type)];
+            }
+        }
+    } else {
+        IPC_ASSERT(KAL_FALSE);
+    }
+}
+
+static void ipc_filter_reset_hw_filter(void)
+{
+    ipv4_filter_rule *hw_filter_base = NULL;
+    kal_bool result = KAL_FALSE;
+    kal_uint8 hw_entry_idx = 0;
+    kal_uint32 total_entry_num = 0;
+    kal_bool ipv6_unknown_proto_chk = KAL_FALSE;
+
+    result = IPC_TAKE_HW_FILTER_TABLE((void**) &hw_filter_base, &total_entry_num);
+
+    /* result shall be true. */
+    IPC_ASSERT(result);
+    hif_trace_info(IPC_TR_UPDATE_HW_FILTER_TABLE_INFO, hw_filter_base, total_entry_num);
+    kal_mem_set(hw_filter_base, 0, sizeof(ipv4_filter_rule) * total_entry_num);
+
+    hif_trace_info(IPC_RESET_HW_FILTER, __FUNCTION__);
+    IPC_SUBMIT_HW_FILTER_TABLE(hw_entry_idx, ipv6_unknown_proto_chk);
+}
+
+static void ipc_filter_chk_sw_path(void)
+{
+    kal_uint32 v4_cnt = 0;
+    kal_uint32 v6_cnt = 0;
+    kal_uint32 proto_idx = 0;
+    kal_uint32 need_hw_entry = 0;
+
+    /* already existed cnt */
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    v4_cnt = ipc_dl_v4_filter_list_s->count;
+    v6_cnt = ipc_dl_v6_filter_list_s->count;
+    need_hw_entry = v4_cnt + 2*v6_cnt;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    if (IPF_HW_FILTER_ENTRY_NUM < need_hw_entry) {
+        /* exceed hw filter entry : SW path
+         * SW => SW : no action */
+        if (KAL_FALSE == g_is_sw_path) {
+            /* HW => SW */
+            for (proto_idx = 0; proto_idx < MAX_SIM_NUM; proto_idx++) {
+                upcm_forced_sw_path_all_by_protocol(KAL_TRUE, proto_idx);
+                hif_trace_info(IPC_FORCE_SW_PATH, __FUNCTION__, KAL_TRUE, proto_idx);
+            }
+            ipc_filter_reset_hw_filter();
+        }
+        g_is_sw_path = KAL_TRUE;
+    } else {
+        /* HW path
+         * HW => HW : no action */
+        ipc_filter_update_hw_filter();
+        if (KAL_TRUE == g_is_sw_path) {
+            /* SW => HW */
+            for (proto_idx = 0; proto_idx < MAX_SIM_NUM; proto_idx++) {
+                upcm_forced_sw_path_all_by_protocol(KAL_FALSE, proto_idx);
+                hif_trace_info(IPC_FORCE_SW_PATH, __FUNCTION__, KAL_FALSE, proto_idx);
+            }
+        }
+        g_is_sw_path = KAL_FALSE;
+    }
+
+    hif_trace_info(IPC_DATA_PATH_STATUS, __FUNCTION__, g_is_sw_path);
+    return;
+}
+
+static INLINE kal_bool ipc_filter_get_ip_pkt(qbm_gpd *desc, /* GPD to get IP header */
+                                             qbm_gpd **bd, /* BD of IP header pointer (NULL if not exist) */
+                                             kal_uint8 **buffer, /* IP header pointer */
+                                             kal_uint32 *length /* GPD total length */)
+{
+    IPC_ASSERT(desc);
+    IPC_ASSERT(bd);
+    IPC_ASSERT(buffer);
+    IPC_ASSERT(length);
+
+    *bd = NULL;
+    *length = QBM_DES_GET_DATALEN(desc);
+
+    if (QBM_DES_GET_BDP(desc)) {
+        desc = (qbm_gpd *) QBM_DES_GET_DATAPTR(desc);
+        while (0 == QBM_DES_GET_DATALEN(desc)) {
+            if (!QBM_DES_GET_EOL(desc)) {
+                desc = (qbm_gpd *) QBM_DES_GET_NEXT(desc);
+            } else {
+                IPC_ASSERT(KAL_FALSE);
+                return KAL_FALSE;
+            }
+        }
+        /* Found : record BD pointer */
+        *bd = desc;
+    }
+
+    *buffer = (kal_uint8*) QBM_DES_GET_DATAPTR(desc);
+
+    return KAL_TRUE;
+}
+
+static INLINE ipc_match_result_e ipc_filter_match_ipv4_rules(ipc_filter_rules_t *rules,
+                                                             ipc_packet_info_t *content)
+{
+    ipc_match_result_e ret = IPC_MATCH_RESULT_NOT_MATCHED;
+
+    /* Start to compare multi-byte IPv4 header content, content dividing issue need to handle */
+    if (_RULES_CONTAIN(rules, SRC_IPV4)) {
+        if (!(content->info_valid_fields & IPC_FILTER_BY_SRC_IPV4)) {
+            goto not_matched;
+        }
+
+        /* Compare content */
+        if (content->src_addr[0] != rules->src_ipv4.addr32) {
+            goto not_matched;
+        }
+    }
+
+    if (_RULES_CONTAIN(rules, DST_IPV4)) {
+        if (!(content->info_valid_fields & IPC_FILTER_BY_DST_IPV4)) {
+            goto not_matched;
+        }
+
+        /* Compare content */
+        if (content->dst_addr[0] != rules->dst_ipv4.addr32) {
+            goto not_matched;
+        }
+    }
+
+    if (_RULES_CONTAIN(rules, PROTOCOL)) {
+        if (!(content->info_valid_fields & IPC_FILTER_BY_PROTOCOL)) {
+            goto not_matched;
+        }
+
+        if (content->protocol != rules->protocol) {
+            goto not_matched;
+        }
+
+        /* For IPv4, we are not handle fragment packets with different protocol. */
+        if (content->fragment) {
+            if (!_FEATURES_CONTAIN(rules, FRAG)) {
+                goto not_matched;
+            } else {
+                ret |= IPC_MATCH_RESULT_FRAG_MATCHED;
+            }
+        }
+
+        /* L4 packet content */
+        switch (rules->protocol) {
+            case IPC_HDR_PROT_UDP:
+            case IPC_HDR_PROT_TCP: {
+                if (_RULES_CONTAIN(rules, SRC_PORT)) {
+                    if (!(content->info_valid_fields & IPC_FILTER_BY_SRC_PORT)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->src_port != rules->src_port) {
+                        goto not_matched;
+                    }
+                }
+                if (_RULES_CONTAIN(rules, DST_PORT)) {
+                    if (!(content->info_valid_fields & IPC_FILTER_BY_DST_PORT)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->dst_port != rules->dst_port) {
+                        goto not_matched;
+                    }
+                }
+                if (_RULES_CONTAIN(rules, TCP_FLAGS)) {
+                    if ((IPC_HDR_PROT_TCP != rules->protocol) || !(content->info_valid_fields & IPC_FILTER_BY_TCP_FLAGS)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->tcp_flags != rules->tcp_flags) {
+                        goto not_matched;
+                    }
+                }
+
+                break;
+            }
+            case IPC_HDR_PROT_ICMP: {
+                if (_RULES_CONTAIN(rules, ICMPV4_TYPE)) {
+                    if (!(content->info_valid_fields & IPC_FILTER_BY_ICMPV4_TYPE)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->icmpv4_type != rules->icmpv4_type) {
+                        goto not_matched;
+                    }
+                }
+
+                break;
+            }
+            case IPC_HDR_PROT_ESP: {
+                if (_RULES_CONTAIN(rules, SPI)) {
+                    if (!(content->info_valid_fields & IPC_FILTER_BY_SPI)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->spi != rules->spi) {
+                        goto not_matched;
+                    }
+                }
+
+                break;
+            }
+            default:
+                /* No L4 content checking rule, pass it directly */
+                break;
+        }
+    }
+
+    ret |= IPC_MATCH_RESULT_MATCHED;
+    return ret;
+
+not_matched :
+    if (0 == (ret & IPC_MATCH_RESULT_FRAG_MATCHED)) {
+        ret = IPC_MATCH_RESULT_NOT_MATCHED;
+    }
+    return ret;
+}
+
+static INLINE ipc_match_result_e ipc_filter_match_ipv6_rules(ipc_filter_rules_t *rules,
+                                                             ipc_packet_info_t *content)
+{
+    ipc_match_result_e ret = IPC_MATCH_RESULT_NOT_MATCHED;
+
+    /* Start to compare multi-byte IPv4 header content, content dividing issue need to handle */
+
+    if (_RULES_CONTAIN(rules, SRC_IPV6)) {
+        if (!(content->info_valid_fields & IPC_FILTER_BY_SRC_IPV6)) {
+            goto not_matched;
+        }
+
+        /* Compare content */
+        if (content->src_addr[0] != rules->src_ipv6.addr32[0]) {
+            goto not_matched;
+        }
+        if (content->src_addr[1] != rules->src_ipv6.addr32[1]) {
+            goto not_matched;
+        }
+        if (content->src_addr[2] != rules->src_ipv6.addr32[2]) {
+            goto not_matched;
+        }
+        if (content->src_addr[3] != rules->src_ipv6.addr32[3]) {
+            goto not_matched;
+        }
+    }
+
+    if (_RULES_CONTAIN(rules, DST_IPV6)) {
+        if (!(content->info_valid_fields & IPC_FILTER_BY_DST_IPV6)) {
+            goto not_matched;
+        }
+
+        /* Compare content */
+        if (content->dst_addr[0] != rules->dst_ipv6.addr32[0]) {
+            goto not_matched;
+        }
+        if (content->dst_addr[1] != rules->dst_ipv6.addr32[1]) {
+            goto not_matched;
+        }
+        if (content->dst_addr[2] != rules->dst_ipv6.addr32[2]) {
+            goto not_matched;
+        }
+        if (content->dst_addr[3] != rules->dst_ipv6.addr32[3]) {
+            goto not_matched;
+        }
+    }
+
+    if (_RULES_CONTAIN(rules, PROTOCOL)) {
+        /* We only compare protocol for the first IPv6 fragment packets. */
+        if (content->fragment) {
+            if (!_FEATURES_CONTAIN(rules, FRAG)) {
+                goto not_matched;
+            } else {
+                ret |= IPC_MATCH_RESULT_FRAG_MATCHED;
+            }
+        }
+
+        if (!(content->info_valid_fields & IPC_FILTER_BY_PROTOCOL)) {
+            goto not_matched;
+        }
+
+        /* Protocol not match */
+        if (content->protocol != rules->protocol) {
+            goto not_matched;
+        }
+
+        /* L4 packet content */
+        switch (rules->protocol) {
+            case IPC_HDR_PROT_UDP:
+            case IPC_HDR_PROT_TCP: {
+                if (_RULES_CONTAIN(rules, SRC_PORT)) {
+                    if (!(content->info_valid_fields & IPC_FILTER_BY_SRC_PORT)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->src_port != rules->src_port) {
+                        goto not_matched;
+                    }
+                }
+                if (_RULES_CONTAIN(rules, DST_PORT)) {
+                    if (!(content->info_valid_fields & IPC_FILTER_BY_DST_PORT)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->dst_port != rules->dst_port) {
+                        goto not_matched;
+                    }
+                }
+                if (_RULES_CONTAIN(rules, TCP_FLAGS)) {
+                    if ((IPC_HDR_PROT_TCP != rules->protocol) ||
+                        !(content->info_valid_fields & IPC_FILTER_BY_TCP_FLAGS)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->tcp_flags != rules->tcp_flags) {
+                        goto not_matched;
+                    }
+                }
+
+                break;
+            }
+            case IPC_HDR_PROT_ICMPV6: {
+                if (_RULES_CONTAIN(rules, ICMPV6_TYPE)) {
+                    if (!(content->info_valid_fields & IPC_FILTER_BY_ICMPV6_TYPE)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->icmpv6_type != rules->icmpv6_type) {
+                        goto not_matched;
+                    }
+                }
+
+                break;
+            }
+            case IPC_HDR_PROT_ESP: {
+                if (_RULES_CONTAIN(rules, SPI)) {
+                    if (!(content->info_valid_fields & IPC_FILTER_BY_SPI)) {
+                        goto not_matched;
+                    }
+
+                    /* Compare content */
+                    if (content->spi != rules->spi) {
+                        goto not_matched;
+                    }
+                }
+
+                break;
+            }
+            default:
+                /* No L4 content checking rule, pass it directly */
+                break;
+        }
+    }
+
+    ret |= IPC_MATCH_RESULT_MATCHED;
+    return ret;
+
+not_matched :
+    if (0 == (ret & IPC_MATCH_RESULT_FRAG_MATCHED)) {
+        ret = IPC_MATCH_RESULT_NOT_MATCHED;
+    }
+
+    return ret;
+}
+
+/*------------------------------------------------------------------------------
+ * Public functions.
+ *----------------------------------------------------------------------------*/
+void ipc_filter_init(void)
+{
+    kal_uint32  idx = 0;
+    static ipc_filter_list_t  *fls_v4_set[] = {ipc_ul_v4_filter_list_s, ipc_dl_v4_filter_list_s};
+    static ipc_filter_list_t  *fls_v6_set[] = {ipc_ul_v6_filter_list_s, ipc_dl_v6_filter_list_s};
+
+#if defined(__MTK_TARGET__)
+    IPC_ASSERT(sizeof(ipc_filter_t) % 4 == 0);
+    IPC_ASSERT(sizeof(ipc_filter_list_t) % 4 == 0);
+#endif
+
+    kal_mem_set( ipc_filter_pool_s, 0, sizeof(ipc_filter_pool_s) );
+    for (idx = 0; idx < IPC_MAX_FILTER_CNT; idx++) {
+        ipc_filter_pool_s[idx].filter_id = IPC_INVALID_FILTER_ID;
+        ipc_filter_pool_s[idx].is_bypass_sync_hw = KAL_FALSE;
+        ipc_deregistering_filter_id_s[idx] = IPC_INVALID_FILTER_ID;
+        ipc_retry_deregistering_filter_id_s[idx] = IPC_INVALID_FILTER_ID;
+    }
+    kal_mem_set(ipc_filter_id_s, 0, sizeof(ipc_filter_id_s));
+    ipc_filter_cnt_s = 0;
+    ipc_filter_magic_number_s = 0;
+    ipc_deregistering_filter_cnt_s = 0;
+    ipc_retry_deregistering_filter_cnt_s = 0;
+#if defined(__MTK_TARGET__)
+    g_ipc_filter_max_hw_entry = IPF_HW_FILTER_ENTRY_NUM;
+#else
+    g_ipc_filter_max_hw_entry = 0;
+#endif
+    g_ipc_dereg_filter_cnt_v4 = 0;
+    g_ipc_dereg_filter_cnt_v6 = 0;
+    g_ipc_filter_recerved_cnt = 0;
+    g_is_sw_path = KAL_FALSE;
+
+    kal_mem_set(ipc_dl_registering_filter_list_s, 0, sizeof(ipc_filter_list_t));
+    kal_mem_set(ipc_ul_registering_filter_list_s, 0, sizeof(ipc_filter_list_t));
+
+    for (idx = 0; idx < sizeof(fls_v4_set) / sizeof(ipc_filter_list_t*); idx++) {
+        kal_mem_set( fls_v4_set[idx], 0, sizeof(ipc_filter_list_t) );
+        fls_v4_set[idx]->ip_type = IPC_IP_TYPE_IPV4;
+    }
+    for (idx = 0; idx < sizeof(fls_v6_set) / sizeof(ipc_filter_list_t*); idx++) {
+        kal_mem_set( fls_v6_set[idx], 0, sizeof(ipc_filter_list_t) );
+        fls_v6_set[idx]->ip_type = IPC_IP_TYPE_IPV6;
+    }
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    kal_mem_set(ipc_dpfm_packet_routing_queue, 0, sizeof(ipc_dpfm_packet_routing_queue));
+    kal_mem_set(ipc_dpfm_queue_non_empty, 0, sizeof(ipc_dpfm_queue_non_empty));
+#endif
+}
+
+static kal_int32 ipc_filter_add_filter(ipc_filter_t *filter, kal_bool uplink)
+{
+    ipc_filter_rules_t *rules = NULL;
+    kal_bool with_ipv4 = KAL_FALSE;
+    kal_bool with_ipv6 = KAL_FALSE;
+
+    IPC_ASSERT(filter);
+
+    rules = &(filter->rules);
+
+#if !defined(__IPF_SUPPORT__)
+    /* [Gen93] Set forced SW path when registering filter. */
+    if (_RULES_CONTAIN(rules, PDN_ID)) {
+        //IPC_FORCED_SW_PATH_BY_PDN(rules->pdn_id, KAL_TRUE);
+    }
+    if (_RULES_CONTAIN(rules, EBI)) {
+        //IPC_FORCED_SW_PATH_BY_EBI(rules->ebi, KAL_TRUE);
+    }
+#endif
+    /*
+     * [Gen93] For DL filters registered through PFM and without PDN/EBI,
+     * set forced SW path to all bearers (to support Garbage Filter).
+     */
+    if ((KAL_FALSE == uplink) && _FEATURES_CONTAIN(rules, PFM_DL) && !( _RULES_CONTAIN(rules, EBI) || _RULES_CONTAIN(rules, PDN_ID))) {
+        //IPC_FORCED_SW_PATH_ALL(KAL_TRUE);
+    }
+
+    /* WC filter should be added to both lists (ipv4 & ipv6). */
+    with_ipv4 = _RULES_CONTAIN_IPV4(rules) || _FEATURES_CONTAIN(rules, WC);
+    with_ipv6 = _RULES_CONTAIN_IPV6(rules) || _FEATURES_CONTAIN(rules, WC);
+    hif_trace_info(IPC_TR_REGISTER_FILTER_OK, uplink, filter->filter_id, rules->features, rules->ip_type, rules->valid_fields, with_ipv4, with_ipv6);
+
+    IPC_ASSERT(0 <= _PRIORITY_OF_FILTER(filter) &&
+               _PRIORITY_OF_FILTER(filter) < ((KAL_TRUE == uplink) ? MAX_IPC_UL_FILTER_PRIORITY : MAX_IPC_DL_FILTER_PRIORITY));
+
+    if (with_ipv4) {
+        ipc_add_filter_to_list(
+                (KAL_TRUE == uplink) ? ipc_ul_v4_filter_list_s : ipc_dl_v4_filter_list_s, filter, IPC_IP_TYPE_IPV4);
+        hif_trace_info(IPC_TR_REGISTER_FILTER_ADD_TO_LIST, filter->filter_id, 4, uplink, g_ipc_dereg_filter_cnt_v4, g_ipc_dereg_filter_cnt_v6, g_ipc_filter_recerved_cnt);
+    }
+    if (with_ipv6) {
+        ipc_add_filter_to_list(
+                (KAL_TRUE == uplink) ? ipc_ul_v6_filter_list_s : ipc_dl_v6_filter_list_s, filter, IPC_IP_TYPE_IPV6);
+        hif_trace_info(IPC_TR_REGISTER_FILTER_ADD_TO_LIST, filter->filter_id, 4, uplink, g_ipc_dereg_filter_cnt_v4, g_ipc_dereg_filter_cnt_v6, g_ipc_filter_recerved_cnt);
+    }
+
+    /* Set flag after filter is added to list*/
+    filter->is_updated_to_list = KAL_TRUE;
+
+    return filter->filter_id;
+}
+
+static INLINE void ipc_filter_set_filter_req_msg(ipc_register_filter_req_struct_t *p_req,
+                                                 ipc_data_path_direction_e data_path_direct,
+                                                 kal_int32 filter_id,
+                                                 ipc_filter_ntfy_ctxt_t *p_ntfy_ctxt)
+{
+    IPC_ASSERT(NULL != p_req);
+    IPC_ASSERT(NULL != p_ntfy_ctxt);
+
+    p_req->filter_id = filter_id;
+    p_req->data_path_direct = data_path_direct;
+
+    if ((IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO == p_ntfy_ctxt->ntfy_type) ||
+        (IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO == p_ntfy_ctxt->ntfy_type)) {
+        p_req->callback_with_info = KAL_TRUE;
+    } else {
+        p_req->callback_with_info = KAL_FALSE;
+    }
+
+    if (p_req->callback_with_info) {
+        p_req->callback_func = p_ntfy_ctxt->ntfy_mod.with_info_cbk_func;
+    } else {
+        p_req->callback_func = p_ntfy_ctxt->ntfy_mod.cbk_func;
+    }
+
+    p_req->callback_context = p_ntfy_ctxt->p_ntfy_args;
+    p_req->module_id = p_ntfy_ctxt->ntfy_mod.cbk_mod;
+
+    return;
+}
+
+kal_int32 ipc_filter_reg_filter_by_ilm(ipc_data_path_direction_e data_path_direct,
+                                       ipc_filter_rules_t *p_rules,
+                                       ipc_filter_ntfy_ctxt_t *p_ntfy_ctxt)
+{
+    ipc_filter_t *p_filter = NULL;
+    kal_int32 filter_id = 0;
+    kal_bool is_send_msg = KAL_FALSE;
+
+    if (!ipc_filter_chk_rules(data_path_direct, p_rules)) {
+        hif_trace_error(IPC_TR_REGISTER_FILTER_VALIDATE_FAIL, data_path_direct);
+        ipc_ut_set_error(IPC_UT_REGISTER_FILTER_VALIDATE_FAIL);
+        return IPC_INVALID_FILTER_ID;
+    }
+
+    if ((IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO == p_ntfy_ctxt->ntfy_type) ||
+        (IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO == p_ntfy_ctxt->ntfy_type)) {
+        filter_id = ipc_new_filter_id(data_path_direct, p_rules, p_ntfy_ctxt->ntfy_mod.with_info_cbk_func, p_ntfy_ctxt->ntfy_mod.cbk_mod);
+    } else {
+        filter_id = ipc_new_filter_id(data_path_direct, p_rules, p_ntfy_ctxt->ntfy_mod.cbk_func, p_ntfy_ctxt->ntfy_mod.cbk_mod);
+    }
+
+    if (filter_id < 0) {
+        hif_trace_info(IPC_TR_REGISTER_FILTER_NG);
+        ipc_ut_set_error(IPC_UT_REGISTER_FILTER_NG);
+        return IPC_INVALID_FILTER_ID;
+    }
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    if (IPC_IP_TYPE_IPV4 == p_rules->ip_type) {
+        if (IPF_HW_FILTER_ENTRY_NUM > g_ipc_filter_recerved_cnt) {
+            g_ipc_filter_recerved_cnt = g_ipc_filter_recerved_cnt + 1;
+        }
+    } else {
+        if (IPF_HW_FILTER_ENTRY_NUM - 1 > g_ipc_filter_recerved_cnt) {
+            g_ipc_filter_recerved_cnt = g_ipc_filter_recerved_cnt + 2;
+        }
+    }
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    p_filter = ipc_new_filter(filter_id, ipc_filter_pool_s, p_rules, p_ntfy_ctxt);
+
+    is_send_msg = ipc_add_filter_to_reg_list(
+            (data_path_direct) ? ipc_ul_registering_filter_list_s : ipc_dl_registering_filter_list_s, p_filter);
+
+    if (is_send_msg) {
+        ipc_register_filter_req_struct_t *p_req = NULL;
+
+        p_req = (ipc_register_filter_req_struct_t *)construct_local_para(sizeof(ipc_register_filter_req_struct_t), TD_RESET);
+        IPC_ASSERT(NULL != p_req);
+        ipc_filter_set_filter_req_msg(p_req, data_path_direct, filter_id, p_ntfy_ctxt);
+        kal_mem_cpy(&(p_req->rules), p_rules, sizeof(ipc_filter_rules_t));
+
+        msg_send6(FILTER_SRC_MOD,
+                  MOD_IPCORE,
+                  IPCORE_USER_SENSITIVE_SAP,
+                  MSG_ID_IPCORE_REGISTER_FILTER_REQ,
+                  (local_para_struct *)p_req,
+                  NULL);
+    } else {
+        /* Dump filter structure (ILM like) when registering ILM aggregated. */
+        ipc_register_filter_req_struct_t req_msg = {0};
+
+        req_msg.msg_len = sizeof(ipc_register_filter_req_struct_t);
+        ipc_filter_set_filter_req_msg(&req_msg, data_path_direct, filter_id, p_ntfy_ctxt);
+        kal_mem_cpy(&(req_msg.rules), p_rules, sizeof(ipc_filter_rules_t));
+
+        dhl_log_primitive6(FILTER_SRC_MOD,
+                           MOD_IPCORE,
+                           IPCORE_USER_SENSITIVE_SAP,
+                           MSG_ID_IPCORE_REGISTER_FILTER_REQ,
+                           (local_para_struct *)&req_msg,
+                           NULL);
+    }
+
+    return filter_id;
+}
+
+void ipc_filter_reg_handler(local_para_struct *local_para_ptr)
+{
+    ipc_filter_t *filter_list[2];
+    ipc_filter_t *curr_filter, *next_filter;
+    kal_uint32 i = 0;
+#if defined(__IPF_SUPPORT__)
+    kal_bool is_DL_updated = KAL_FALSE;
+#endif
+
+    ipc_get_filter_list_from_reg_list(&filter_list[0], &filter_list[1]);
+
+    for (i = 0; i < 2; i++) {
+        curr_filter = filter_list[i];
+        while (curr_filter) {
+            next_filter = curr_filter->next_filter_map[0];
+            curr_filter->next_filter_map[0] = NULL;
+            ipc_filter_add_filter(curr_filter, (0 == i) ? KAL_TRUE : KAL_FALSE);
+#if defined(__IPF_SUPPORT__)
+            if (!(0 == i)) {
+                is_DL_updated = KAL_TRUE;
+            }
+#endif
+            curr_filter = next_filter;
+        }
+    }
+
+#if defined(__IPF_SUPPORT__)
+    if (is_DL_updated && (IPC_HW_DL_MODE == g_ipc_dl_mode)) {
+        ipc_filter_chk_sw_path();
+    }
+#endif
+
+    ipc_filter_list_dump_all();
+}
+
+void ipc_filter_dereg(kal_int32 filter_id)
+{
+    ipc_filter_t *filter = NULL;
+    ipc_filter_rules_t *rules = NULL;
+    kal_bool with_ipv4 = KAL_FALSE;
+    kal_bool with_ipv6 = KAL_FALSE;
+
+    filter = ipc_find_filter_by_id(ipc_filter_pool_s, filter_id);
+    if ((NULL != filter) && (filter->filter_id != IPC_INVALID_FILTER_ID)) {
+
+        /* Check if the filter is already stored to IPcore internal list. */
+        if (filter->is_updated_to_list != KAL_TRUE) {
+            ipc_retry_deregistering_filter_id_s[ipc_retry_deregistering_filter_cnt_s] = filter->filter_id;
+            ipc_retry_deregistering_filter_cnt_s++;
+            hif_trace_info(IPC_TR_REMOVE_DL_FILTER_RETRY, filter->filter_id);
+            return;
+        }
+
+        rules = &(filter->rules);
+
+#if !defined(__IPF_SUPPORT__)
+        /* [Gen93] Clear forced SW path when deregistering filter. */
+        if (_RULES_CONTAIN(rules, PDN_ID)) {
+            //IPC_FORCED_SW_PATH_BY_PDN(rules->pdn_id, KAL_FALSE);
+        }
+        if (_RULES_CONTAIN(rules, EBI)) {
+            //IPC_FORCED_SW_PATH_BY_EBI(rules->ebi, KAL_FALSE);
+        }
+#endif
+        /*
+         * [Gen93] For DL filters registered through PFM and without PDN/EBI,
+         * clear forced SW path to all bearers (to support Garbage Filter).
+         */
+        if ( _FEATURES_CONTAIN(rules, PFM_DL) && !( _RULES_CONTAIN(rules, EBI) || _RULES_CONTAIN(rules, PDN_ID))) {
+            //IPC_FORCED_SW_PATH_ALL(KAL_FALSE);
+        }
+
+        with_ipv4 = _RULES_CONTAIN_IPV4(rules) || _FEATURES_CONTAIN(rules, WC);
+        with_ipv6 = _RULES_CONTAIN_IPV6(rules) || _FEATURES_CONTAIN(rules, WC);
+        hif_trace_info(IPC_TR_DEREGISTER_FILTER_INFO, filter->filter_id, rules->features, rules->valid_fields, with_ipv4, with_ipv6);
+
+        if (with_ipv4) {
+            /* Remove from UL filter list */
+            ipc_filter_rm_filter_from_list(ipc_ul_v4_filter_list_s, filter, IPC_IP_TYPE_IPV4);
+            /* Remove from DL filter list */
+            ipc_filter_rm_filter_from_list(ipc_dl_v4_filter_list_s, filter, IPC_IP_TYPE_IPV4);
+            hif_trace_info(IPC_TR_REMOVE_DL_FILTER_FROM_LIST, filter->filter_id, 4);
+        }
+        if (with_ipv6) {
+            /* Remove from UL filter list */
+            ipc_filter_rm_filter_from_list(ipc_ul_v6_filter_list_s, filter, IPC_IP_TYPE_IPV6);
+            /* Remove from DL filter list */
+            ipc_filter_rm_filter_from_list(ipc_dl_v6_filter_list_s, filter, IPC_IP_TYPE_IPV6);
+            hif_trace_info(IPC_TR_REMOVE_DL_FILTER_FROM_LIST, filter->filter_id, 6);
+        }
+
+        ipc_del_filter(filter);
+    } else {
+        hif_trace_error(IPC_TR_DEREGISTER_FILTER_NOT_FOUND, filter_id);
+        ipc_ut_set_error(IPC_UT_DEREGISTER_FILTER_NOT_FOUND);
+    }
+}
+
+kal_bool ipc_filter_dereg_filter_by_ilm(kal_int32 filter_id)
+{
+    kal_bool to_send_msg = KAL_FALSE;
+    ipc_filter_t *p_filter = NULL;
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    p_filter = ipc_find_filter_by_id(ipc_filter_pool_s, filter_id);
+    if ((0 > filter_id) ||
+        (IPC_MAX_FILTER_CNT <= filter_id) ||
+        (NULL == p_filter) ||
+        (IPC_INVALID_FILTER_ID == p_filter->filter_id)) {
+        IPC_SPIN_UNLOCK(ipc_spinlock_g);
+        hif_trace_error(IPC_TR_DEREGISTER_FILTER_WITH_INVALID_ID, filter_id);
+        ipc_ut_set_error(IPC_UT_DEREGISTER_FILTER_WITH_INVALID_ID);
+        return KAL_FALSE;
+    }
+
+    to_send_msg = (0 == ipc_deregistering_filter_cnt_s);
+    ipc_deregistering_filter_id_s[ipc_deregistering_filter_cnt_s] = filter_id;
+    if (IPC_IP_TYPE_IPV4 == p_filter->rules.ip_type) {
+        if (IPC_MAX_FILTER_CNT > g_ipc_dereg_filter_cnt_v4) {
+            g_ipc_dereg_filter_cnt_v4++;
+        }
+    } else {
+        if (IPC_MAX_FILTER_CNT > g_ipc_dereg_filter_cnt_v6) {
+            g_ipc_dereg_filter_cnt_v6++;
+        }
+    }
+    ipc_deregistering_filter_cnt_s++;
+
+    /* add tag in register list and pending register list */
+    if (filter_id == p_filter->filter_id) {
+        /* already in filter list */
+        p_filter->is_bypass_sync_hw = KAL_TRUE;
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+        hif_trace_info(IPC_TR_SET_BYPASS_HW_FILTER_SYNC, __FUNCTION__, filter_id);
+    } else {
+        IPC_SPIN_UNLOCK(ipc_spinlock_g);
+    }
+
+    if (to_send_msg) {
+        ipc_deregister_filter_req_struct_t *p_req_msg = NULL;
+
+        p_req_msg = (ipc_deregister_filter_req_struct_t *) construct_local_para(sizeof(ipc_deregister_filter_req_struct_t), TD_RESET);
+        IPC_ASSERT(p_req_msg);
+
+        p_req_msg->filter_id = filter_id;
+
+        msg_send6(FILTER_SRC_MOD, /* src_mod_id */
+                  MOD_IPCORE,     /* dest_mod_id */
+                  IPCORE_SAP,     /* sap_id */
+                  MSG_ID_IPCORE_DEREGISTER_FILTER_REQ, /* msg_id */
+                  (local_para_struct *)p_req_msg,     /* local_para_ptr */
+                  NULL);                               /* peer_buff_ptr */
+    } else {
+        /* Dump filter structure (ILM like) when registering ILM aggregated. */
+        ipc_deregister_filter_req_struct_t tmp = {0};
+        ipc_deregister_filter_req_struct_t *p_req_msg = &tmp;
+
+        p_req_msg->msg_len = sizeof(ipc_deregister_filter_req_struct_t);
+        p_req_msg->filter_id = filter_id;
+
+        dhl_log_primitive6(FILTER_SRC_MOD, /* src_mod_id */
+                           MOD_IPCORE,     /* dest_mod_id */
+                           IPCORE_SAP,     /* sap_id */
+                           MSG_ID_IPCORE_DEREGISTER_FILTER_REQ, /* msg_id */
+                           (local_para_struct *)p_req_msg,      /* local_para_ptr */
+                           NULL);                               /* peer_buff_ptr */
+    }
+
+    return KAL_TRUE;
+}
+
+void ipc_filter_dereg_handler(local_para_struct *local_para_ptr)
+{
+    static kal_int32 deregistering_filter_id[IPC_MAX_FILTER_CNT] = {0};
+    kal_uint32 deregistering_filter_cnt = 0;
+    kal_uint32 i = 0;
+    kal_bool to_send_msg = KAL_FALSE;
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    deregistering_filter_cnt = ipc_deregistering_filter_cnt_s;
+    ipc_deregistering_filter_cnt_s = 0;
+    for (i = 0; i < deregistering_filter_cnt; i++) {
+        IPC_ASSERT(ipc_deregistering_filter_id_s[i] >= 0);
+        deregistering_filter_id[i] = ipc_deregistering_filter_id_s[i];
+        ipc_deregistering_filter_id_s[i] = IPC_INVALID_FILTER_ID;
+    }
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    for (i = 0; i < deregistering_filter_cnt; i++) {
+        IPC_ASSERT(deregistering_filter_id[i] >= 0);
+        ipc_filter_dereg(deregistering_filter_id[i]);
+    }
+
+#if defined(__IPF_SUPPORT__)
+    if(IPC_HW_DL_MODE == g_ipc_dl_mode){
+         ipc_filter_chk_sw_path();
+    }
+#endif
+
+    ipc_filter_list_dump_all();
+
+    /* If retry list is not NULL, insert retry ids back to ipc_deregistering_filter_id_s*/
+    if (ipc_retry_deregistering_filter_cnt_s != 0) {
+        IPC_SPIN_LOCK(ipc_spinlock_g);
+        to_send_msg = (0 == ipc_deregistering_filter_cnt_s);
+        for (i = 0; i < ipc_retry_deregistering_filter_cnt_s; i++) {
+            IPC_ASSERT(ipc_retry_deregistering_filter_id_s[i] >= 0);
+            ipc_deregistering_filter_id_s[ipc_deregistering_filter_cnt_s] = ipc_retry_deregistering_filter_id_s[i];
+            ipc_retry_deregistering_filter_id_s[i] = IPC_INVALID_FILTER_ID;
+            ipc_deregistering_filter_cnt_s++;
+        }
+        ipc_retry_deregistering_filter_cnt_s = 0;
+        IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+        if (to_send_msg) {
+            ipc_deregister_filter_req_struct_t *req_msg_p = NULL;
+            ilm_struct ilm = {0};
+
+            req_msg_p = (ipc_deregister_filter_req_struct_t *) construct_local_para(sizeof(ipc_deregister_filter_req_struct_t), TD_RESET);
+            IPC_ASSERT(req_msg_p);
+
+            req_msg_p->filter_id = IPC_INVALID_FILTER_ID;
+
+            ilm.src_mod_id = IPCORE_SRC_MOD;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.msg_id = MSG_ID_IPCORE_DEREGISTER_FILTER_REQ;
+            ilm.local_para_ptr = (local_para_struct *)req_msg_p;
+            ilm.peer_buff_ptr = NULL;
+            ilm.sap_id = IPCORE_SAP;
+
+            /* Be careful that this message should send to IPcore's external queue, */
+            /* Otherwise, it will block in infinite loop for processing internal message. */
+            msg_send_ext_queue(&ilm);
+
+        } else {
+            /* Dump filter structure (ILM like) when registering ILM aggregated. */
+            ipc_deregister_filter_req_struct_t tmp;
+            ipc_deregister_filter_req_struct_t *req_msg_p = &tmp;
+
+            req_msg_p->msg_len = sizeof(ipc_deregister_filter_req_struct_t);
+            req_msg_p->filter_id = IPC_INVALID_FILTER_ID;
+
+            dhl_log_primitive6(IPCORE_SRC_MOD,
+                               MOD_IPCORE, /* dest_mod_id */
+                               IPCORE_SAP, /* sap_id */
+                               MSG_ID_IPCORE_DEREGISTER_FILTER_REQ, /* msg_id */
+                               (local_para_struct *) req_msg_p,     /* local_para_ptr */
+                               NULL);                               /* peer_buff_ptr */
+        }
+    }
+}
+
+static INLINE ipc_pkt_do_filter_result_e ipc_pkt_do_one_filter(kal_bool uplink,
+                                                               kal_uint8 ip_type,
+                                                               ipc_packet_info_t *packet_info,
+                                                               ipc_filter_t *filter,
+                                                               kal_uint32 pdn_id,
+                                                               kal_uint32 netif_id,
+                                                               kal_uint8 ebi_info,
+                                                               ipc_filter_t **matched_filter,
+                                                               ipc_filter_info_t *filter_info)
+{
+    ipc_pkt_do_filter_result_e ret;
+    ipc_match_result_e matched = KAL_FALSE;
+
+    /* Check if its the Wild Card filter */
+    if (_FEATURES_CONTAIN(&filter->rules, WC)) {
+        goto filter_matched;
+    }
+
+    /* PDN ID is only valid for downlink filter */
+    if ((KAL_FALSE == uplink) && _RULES_CONTAIN(&filter->rules, PDN_ID) && pdn_id != filter->rules.pdn_id) {
+        ret = IPC_PKT_DO_FILTER_NOT_MATCHED;
+        goto done;
+        /* Skip the filter if PDN ID mismatched. */
+    }
+
+    if (_RULES_CONTAIN(&filter->rules, NETIF_ID) && netif_id != filter->rules.netif_id) {
+        ret = IPC_PKT_DO_FILTER_NOT_MATCHED;
+        goto done;
+        /* Skip the filter if Network interface ID mismatched. */
+    }
+
+    /*
+     * 1. ebi is only valid for downlink filter
+     * 2. (2013/11/4) According to UPCM comment, EBI is only brought in first GPD of GPD list.
+     * 3. (2015/1/14)  EBI info in the 1st GPD is recorded before filtering. (saved in ebi_info)
+     */
+    if ((KAL_FALSE == uplink) && _RULES_CONTAIN(&filter->rules, EBI) && ebi_info != 0xff && ebi_info != filter->rules.ebi) {
+        ret = IPC_PKT_DO_FILTER_NOT_MATCHED;
+        goto done;
+    }
+
+    do {
+        /* Check for IP version : single byte check, no content dividing issue */
+        if (IPC_IP_TYPE_IPV4 == ip_type) {
+            if (_RULES_CONTAIN_IPV4(&filter->rules)) {
+                matched = ipc_filter_match_ipv4_rules(&filter->rules, packet_info);
+            }
+        } else {
+            if (_RULES_CONTAIN_IPV6(&filter->rules)) {
+                matched = ipc_filter_match_ipv6_rules(&filter->rules, packet_info);
+            }
+        }
+    } while (0);
+
+    if (!matched) {
+        ret = IPC_PKT_DO_FILTER_NOT_MATCHED;
+        goto done;
+    }
+
+filter_matched:
+    hif_data_trace(MD_TRC_IPC_GE_FILTER_RULE_MATCHED, 0, &filter->rules, filter->rules.features, filter->rules.valid_fields, matched);
+
+    if (0 != (matched & IPC_MATCH_RESULT_FRAG_MATCHED)) {
+        /*
+         * Handle "FRAG_MATCHED" fragment packets.
+         * Note that the filter should be set to support fragment.
+         */
+        IPC_ASSERT(_FEATURES_CONTAIN(&filter->rules, FRAG));
+
+        *matched_filter = filter;
+
+        ret = IPC_PKT_DO_FILTER_HANDLE_FRAG;
+        goto done;
+    }
+
+    if (_FEATURES_CONTAIN(&filter->rules, BWM)) {
+        /* For BWM filter, there is no filter callback funtion, so it's not necessary to cache filter info. */
+
+        ret = IPC_PKT_DO_FILTER_BWM_MATCHED;
+        goto done;
+    }
+
+    *matched_filter = filter;
+
+    if (KAL_TRUE == filter->callback_with_info) {
+        /* Fill filter_info */
+        ipc_netif_t *netif;
+
+        kal_mem_set(filter_info, 0, sizeof(ipc_filter_info_t));
+        filter_info->netif_id = netif_id;
+
+        netif = ipc_find_netif(netif_id);
+        if (netif) {
+            filter_info->ip_id = ipc_map_netif_to_ip_id(netif);
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+        } else {
+            filter_info->ip_id = -1;
+        }
+
+        /*
+         *      1. ebi is only valid for downlink filter
+         *      2. (2013/11/4)  According to UPCM comment, EBI is only brought in first GPD of GPD list.
+         */
+        if (KAL_FALSE == uplink) {
+
+            if (0xFF == ebi_info) {
+                filter_info->ebi = -1;
+            } else {
+                filter_info->ebi = ebi_info;
+                IPC_RETRIEVE_PROTOID_FROM_PDNID(filter_info->ebi, filter_info->proto_idx);
+                IPC_UNMASK_PROTOID_FROM_PDNID(filter_info->ebi);
+            }
+        } else {
+            filter_info->ebi = -1;
+        }
+
+        /* (2014/11/11) Based on LTECSR's requirement, carry RTP data_offset info to them. */
+        filter_info->data_offset = packet_info->data_offset;
+    }
+
+    ret = IPC_PKT_DO_FILTER_MATCHED;
+    goto done;
+
+done :
+    if (_FEATURES_CONTAIN(&filter->rules, CLONE) && (IPC_PKT_DO_FILTER_MATCHED == ret)) {
+        ret = IPC_PKT_DO_FILTER_HANDLE_CLONE;
+        hif_trace_info(IPC_TR_FILTER_MATCHED_CLONED);
+    }
+
+    return ret;
+}
+
+static INLINE ipc_pkt_do_filter_result_e ipc_pkt_do_filter(kal_bool uplink,
+                                                           ipc_filter_list_t **fls_set_p,
+                                                           kal_uint32 fls_set_cnt,
+                                                           kal_uint8 session_type,
+                                                           kal_uint32 pdn_id,
+                                                           kal_uint32 netif_id,
+                                                           kal_uint8 ebi_info, /*< for record ebi, which is saved in the 1st GPD */
+                                                           ipc_pkt_des_t *packet_des)
+{
+    ipc_filter_list_t *filter_list = NULL;
+    kal_uint8 filter_list_type = 0;
+    ipc_filter_t *filter = NULL;
+    kal_uint32 fls_idx = 0;
+    ipc_pkt_do_filter_result_e ret = IPC_PKT_DO_FILTER_NOT_MATCHED;
+    kal_uint8 dpfm_rule_id = 0;
+    kal_uint8 ip_type = session_type;
+
+    /* Alias local parameter */
+    kal_uint8 *ip_packet = packet_des->packet;
+    kal_uint32 packet_len = packet_des->packet_len;
+    qbm_gpd *curr_gpd = packet_des->gpd;
+    qbm_gpd *curr_bd = packet_des->bd;
+    ipc_filter_t **matched_filter = packet_des->matched_filter;
+    ipc_filter_info_t *filter_info = packet_des->filter_info;
+    ipc_packet_info_t *packet_info = packet_des->packet_info;
+    upcm_did *did = packet_des->did;
+    kal_uint32 pkt_start_si_idx = packet_des->pkt_start_idx;
+    kal_bool get_pkt_info = packet_des->is_packet_info; //No need to parse packet again if TRUE
+
+#if (IPC_DL_INVALID_LEN_DROP_EN)
+    if ((!uplink) && (packet_len > ipc_dl_valid_packet_len_s)) {
+        ret = IPC_PKT_DO_FILTER_INVALID_LEN;
+        goto done;
+    }
+#endif
+
+    filter_list = NULL; // init per GPD start
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    /*
+     * When MD Direct Tethering is activated, we need packet_info for every packets.
+     */
+    if (IPC_DPFM_IS_ACTIVE()) {
+
+        if(!get_pkt_info && ipc_dpfm_need_pkt_info(uplink, packet_des))
+        {
+            /* get packet info */
+            if (IPC_PKT_DES_TYPE_GPD == packet_des->des_type) {
+                IPC_ASSERT(ip_packet && curr_gpd);
+                ipc_get_packet_info_gpd(ip_packet, curr_gpd, curr_bd, packet_info);
+            } else if (IPC_PKT_DES_TYPE_DID == packet_des->des_type) {
+                IPC_ASSERT(ip_packet && did);
+                ipc_get_packet_info_did(ip_packet, did, pkt_start_si_idx, packet_info);
+            } else {
+                IPC_ASSERT(ip_packet);
+                ipc_get_packet_info(ip_packet, packet_len, packet_info);
+            }
+
+            get_pkt_info = KAL_TRUE; /* already get info, get info GPD */
+        }
+
+        /* Check if the packet should be tracked (UL only)*/
+        if (uplink) {
+            HIF_SWLA_START("IM1");
+            IPC_DPFM_TRACK_PACKET(uplink, packet_des, netif_id);
+            HIF_SWLA_STOP("IM1");
+        }
+    }
+#endif
+
+    for (fls_idx = 0; fls_idx < fls_set_cnt; fls_idx++) {
+        filter_list = fls_set_p[fls_idx];
+
+        if (!filter_list || 0 == filter_list->count) {
+            continue; /* Skip empty filter list. */
+        }
+
+        filter_list_type = filter_list->ip_type;
+
+        if (IPC_IP_TYPE_IPV4 == session_type) {
+            if (IPC_IP_TYPE_IPV4 != filter_list_type) {
+                continue; /* Skip the filter list if IP type mismatched. */
+            }
+        } else if (IPC_IP_TYPE_IPV6 == session_type) {
+            if (IPC_IP_TYPE_IPV6 != filter_list_type) {
+                continue; /* Skip the filter list if IP type mismatched. */
+            }
+        }
+
+        if (KAL_FALSE == get_pkt_info) {
+            /* get packet info */
+            if (IPC_PKT_DES_TYPE_GPD == packet_des->des_type) {
+                IPC_ASSERT(ip_packet && curr_gpd);
+                get_pkt_info = ipc_get_packet_info_gpd(ip_packet, curr_gpd, curr_bd, packet_info);
+            } else if (IPC_PKT_DES_TYPE_DID == packet_des->des_type) {
+                IPC_ASSERT(ip_packet && did);
+                get_pkt_info = ipc_get_packet_info_did(ip_packet, did, pkt_start_si_idx, packet_info);
+            } else {
+                IPC_ASSERT(ip_packet);
+                get_pkt_info = ipc_get_packet_info(ip_packet, packet_len, packet_info);
+            }
+
+            if (get_pkt_info) {
+                packet_des->is_packet_info = KAL_TRUE;
+            }
+        }
+
+        for (filter = filter_list->filter_head;
+             filter;
+             filter = filter->next_filter_map[ipc_next_filter_hash(filter_list_type)]) {
+
+            ret = ipc_pkt_do_one_filter(uplink,
+                                        ip_type,
+                                        packet_info,
+                                        filter,
+                                        pdn_id,
+                                        netif_id,
+                                        ebi_info,
+                                        matched_filter,
+                                        filter_info);
+        #ifdef __TEMP_MDDP_WH_SUPPORT__
+            /* If filter feature contains IPV6_MDT, skip quick filtering */
+            if ((_FEATURES_CONTAIN(&(filter->rules), IPV6_DPFM)) && (IPC_PKT_DO_FILTER_MATCHED == ret)) {
+                ret = IPC_PKT_DO_FILTER_NOT_MATCHED;
+                goto dpfm_check_route;
+            }
+        #endif 
+
+            if (_FEATURES_CONTAIN(&filter->rules, CUST_FILTER) && (IPC_PKT_DO_FILTER_MATCHED == ret)) {
+                if (KAL_FALSE == filter->cust_cbk_func(packet_des->packet,
+                                                       packet_des->packet_len,
+                                                       filter->filter_id,
+                                                       filter->p_cust_cbk_args)) {
+                    ret = IPC_PKT_DO_FILTER_NOT_MATCHED;
+                }
+                hif_data_trace(MD_TRC_IPC_TR_CUST_FILTER_CBK, packet_des->packet, packet_des->packet_len, filter->filter_id, ret);
+            }else if (_FEATURES_CONTAIN(&filter->rules, CUST_FILTER_W_INFO) && (IPC_PKT_DO_FILTER_MATCHED == ret)) {
+                if(IPC_PKT_DES_TYPE_DID == packet_des->des_type){
+                    filter_info->src_desc_type = IPC_FI_DESC_TYPE_DID;
+                    filter_info->src_desc_ptr = packet_des->did;
+                    filter_info->src_desc_indx = packet_des->pkt_start_idx;
+                }else{
+                    filter_info->src_desc_type = IPC_FI_DESC_TYPE_NONE;
+                }
+                if (KAL_FALSE == filter->cust_cbk_func(packet_des->packet,
+                                                       packet_des->packet_len,
+                                                       filter->filter_id,
+                                                       filter_info)) {
+                    ret = IPC_PKT_DO_FILTER_NOT_MATCHED;
+                }
+                hif_data_trace(MD_TRC_IPC_TR_CUST_FILTER_CBK, packet_des->packet, packet_des->packet_len, filter->filter_id, ret);
+            }
+
+            if (IPC_PKT_DO_FILTER_NOT_MATCHED != ret) {
+                if (IPC_PKT_DO_FILTER_BWM_MATCHED == ret || IPC_PKT_DO_FILTER_HANDLE_CLONE == ret) {
+                    goto dpfm_check_route;
+                } else {
+                    goto done;
+                }
+            }
+        }
+    } /* for each filter_list, fls_idx */
+
+    ret = IPC_PKT_DO_FILTER_NOT_MATCHED;
+    goto dpfm_check_route;
+
+dpfm_check_route :
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    /* For NOT_MATCHED & BWM_MATCHED cases, check DPFM routing before return. */
+
+    if (ipc_dpfm_check_route(uplink, packet_des, netif_id)) {
+        hif_data_trace(MD_TRC_IPC_DPFM_CHECK_ROUTE_MATCHED, uplink, session_type, packet_info->out_netif_id);
+        ret = IPC_PKT_DO_FILTER_DPFM_MATCHED;
+    }
+
+#endif
+    goto done;
+
+done :
+    ipc_filter_dump_pkt(uplink, packet_des, (kal_uint8) ret, dpfm_rule_id);
+    return ret;
+}
+
+static INLINE void ipc_call_filter_cbk(kal_bool uplink,
+                                       qbm_gpd *p_head,
+                                       qbm_gpd *p_tail,
+                                       kal_uint16 callback_gpd_data_len,
+                                       ipc_filter_t *filter,
+                                       ipc_filter_info_t *filter_info)
+{
+    IPC_ASSERT(p_head && p_tail);
+    IPC_ASSERT(filter);
+    IPC_ASSERT(filter_info);
+
+    hif_data_trace(MD_TRC_IPC_GE_FILTER_OUT_INFO, uplink, filter->callback_context, filter->filter_id);
+    hif_data_trace(MD_TRC_IPC_GE_FILTER_OUT_GPD, uplink, p_head, p_tail, callback_gpd_data_len);
+
+    HIF_SWLA_START("IF1");
+
+    if (KAL_TRUE == filter->callback_with_info) {
+        ipc_filter_with_info_callback_t callback_func;
+
+        callback_func = (ipc_filter_with_info_callback_t)(filter->callback_func);
+        callback_func(filter_info, filter->callback_context, filter->filter_id, p_head, p_tail, (kal_uint32) callback_gpd_data_len);
+    } else {
+        ipc_filter_callback_t callback_func;
+
+        callback_func = (ipc_filter_callback_t) (filter->callback_func);
+        callback_func(filter->callback_context, filter->filter_id, p_head, p_tail, (kal_uint32) callback_gpd_data_len);
+    }
+
+    HIF_SWLA_STOP("IF1");
+}
+
+static INLINE kal_uint32 ipc_spd_do_filter(kal_bool uplink,
+                                           ipc_filter_list_t **fls_set_p,
+                                           kal_uint32 fls_set_cnt,
+                                           kal_uint8 session_type,
+                                           kal_uint32 pdn_id,
+                                           kal_uint32 netif_id,
+                                           kal_uint8 ebi_info, // for record ebi, which is saved in the 1st GPD
+                                           qbm_gpd *curr_gpd)
+{
+    kal_uint8 *ip_packet = NULL;
+    kal_uint32 length = 0;
+    ipc_filter_t *filter = NULL;
+    ipc_filter_info_t filter_info = {0};
+    ipc_packet_info_t packet_info = {0};
+    qbm_spd_pi *p_spd_pi = NULL;
+    qbm_spd_pie *p_spd_pie = NULL; // spd payload info element
+    qbm_spd_pie *p_prev_spd_pie = NULL;
+    kal_uint8 idx = 0;
+    kal_uint32 payload_len = 0;
+    kal_uint16 packet_num = 0;
+    kal_uint16 remain_packet_num = 0; // the num of packets not filtered out
+    ipc_pkt_do_filter_result_e result = IPC_PKT_DO_FILTER_NOT_MATCHED;
+    ipc_pkt_des_t packet_des = {0};
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    kal_uint8 dpfm_matched_num = 0;
+    kal_bool mirror_spd_pie_idx[QBM_SPD_MAX_PKTNUM];
+    kal_uint32 dpfm_out_netif_id = 0;
+
+    kal_mem_set(mirror_spd_pie_idx, 0, sizeof(mirror_spd_pie_idx));
+#endif
+    kal_uint8 ip_type = 0;
+
+    /* SPD only supports for downlink traffic. */
+    IPC_ASSERT(!uplink);
+
+    /* Init packet_des */
+    kal_mem_set(&packet_des, 0, sizeof(ipc_pkt_des_t));
+    packet_des.des_type = IPC_PKT_DES_TYPE_SPD;
+    packet_des.matched_filter = &filter;
+    packet_des.filter_info = &filter_info;
+    packet_des.packet_info = &packet_info;
+
+    ip_packet = QBM_DES_GET_DATAPTR(curr_gpd);
+    length = QBM_DES_GET_DATALEN(curr_gpd);
+    IPC_ASSERT(length > 0);
+    p_spd_pi = QBM_SPD_GET_PI((qbm_spd *) curr_gpd);
+    p_prev_spd_pie = NULL;
+
+    packet_num = QBM_SPD_PI_GET_PKTNUM(p_spd_pi);
+    IPC_ASSERT(packet_num > 0);
+
+    hif_data_trace(MD_TRC_IPC_GE_SPD_DO_FILTER, 0, curr_gpd, length, packet_num);
+    remain_packet_num = 0;
+    for (idx = 0; idx < packet_num; idx++) {
+        if (idx == 0) {
+            p_spd_pie = QBM_SPD_PI_GET_FIRST_PIE(p_spd_pi);
+        } else {
+            ip_packet = QBM_SPD_PAYLOAD_NEXT(ip_packet, payload_len);
+            p_spd_pie = QBM_SPD_PIE_NEXT(p_spd_pie);
+            IPC_ASSERT(p_spd_pie != NULL);
+        }
+
+        payload_len = QBM_SPD_PIE_GET_PAYLOAD_LEN(p_spd_pie);
+
+        /* Bypass the packets with IGR bit set. */
+        if (!QBM_SPD_PIE_GET_IGR(p_spd_pie)) {
+            IPC_ASSERT(payload_len > 0);
+
+            /* Fill packet_des */
+            packet_des.packet = ip_packet;
+            packet_des.packet_len = payload_len;
+            packet_des.ip_type = ip_type = (IPC_HDR_IS_V4(ip_packet)) ? IPC_IP_TYPE_IPV4 : IPC_IP_TYPE_IPV6;
+
+            result = ipc_pkt_do_filter(uplink, fls_set_p, fls_set_cnt, ip_type, pdn_id, netif_id, ebi_info, &packet_des);
+
+            if ((IPC_PKT_DO_FILTER_MATCHED == result) || (IPC_PKT_DO_FILTER_INVALID_LEN == result) || (IPC_PKT_DO_FILTER_DPFM_MATCHED == result)) {
+                hif_data_trace(MD_TRC_IPC_GE_SPD_ENTRY_IGR_INFO, uplink, curr_gpd, idx, payload_len);
+
+                QBM_SPD_PIE_SET_IGR(p_spd_pie);
+                length -= payload_len;
+
+                if (QBM_SPD_PIE_GET_EOL(p_spd_pie) && (NULL != p_prev_spd_pie)) {
+                    /* Move the EOL bit to the previous SPD entry */
+                    IPC_ASSERT(remain_packet_num > 0);
+
+                    QBM_SPD_PIE_SET_EOL(p_prev_spd_pie);
+                }
+
+                if (IPC_PKT_DO_FILTER_MATCHED == result) {
+                    qbm_gpd *callback_gpd_p = NULL;
+                    kal_uint8 *callback_gpd_data_p = NULL;
+                    /*
+                     * 1. A packet is indivisible from the SPD, so we need to allocate a GPD for it.
+                     * 2. Uplink SPD is not used.
+                     * 3. (2014/8/13 Stan.Chen) Use QBM_TYPE_NET_DL, if it use out, use QBM_TYPE_HIF_DL instead.
+                     * 4. (2016/10/14 Wen-Jiunn.Liu) QBM_TYPE_HIF_DL is not provided anymore in Gen93.
+                     */
+                    if (1 != qbmt_alloc_q_no_tail((KAL_TRUE == uplink) ? QBM_TYPE_NET_UL_SHRD : QBM_TYPE_NET_DL,
+                                                  1,
+                                                  (void**)&callback_gpd_p,
+                                                  (void**) &callback_gpd_p)) {
+
+                        hif_trace_error(IPC_TR_DO_FILTER_ALLOC_GPD_NG, uplink, 0, curr_gpd, idx, payload_len);
+                        continue;
+                    }
+
+                    /* Copy data from SPD payload to output GPD */
+                    IPC_ASSERT(callback_gpd_p);
+                    ipc_utils_set_gpd_datalen(callback_gpd_p, payload_len, (void**) &callback_gpd_data_p);
+                    IPC_ASSERT(callback_gpd_data_p);
+
+                    QBM_CACHE_INVALID(ip_packet, payload_len);
+                    kal_mem_cpy(callback_gpd_data_p, ip_packet, payload_len);
+                    QBM_CACHE_FLUSH(callback_gpd_data_p, payload_len);
+
+                    /* Forward GPD by filter's callback function */
+                    ipc_call_filter_cbk(uplink, callback_gpd_p, callback_gpd_p, payload_len, filter, &filter_info);
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+                } else if (IPC_PKT_DO_FILTER_DPFM_MATCHED == result) {
+                    dpfm_matched_num++;
+                    mirror_spd_pie_idx[idx] = KAL_TRUE;
+                    dpfm_out_netif_id = packet_info.out_netif_id;
+#endif
+                }
+            } else {
+                remain_packet_num++;
+                p_prev_spd_pie = p_spd_pie;
+            }
+        }
+
+        if (QBM_SPD_PIE_GET_EOL(p_spd_pie)) {
+            /* end of packet list */
+            break;
+        }
+    }
+
+    /* If there is no remain packet, then the SPD's Transfer Data Length should be zero. */
+    IPC_ASSERT((0 != remain_packet_num) || (0 == length));
+
+    /* Update SPD's Transfer Data Length */
+    QBM_DES_SET_DATALEN(curr_gpd, length);
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    /* Mirror the SPD if there is any packet routing to direct path. */
+    if (dpfm_matched_num) {
+        qbm_spd *p_mirror_spd;
+
+        p_mirror_spd = ipc_dpfm_mirror_spd((qbm_spd *)curr_gpd, mirror_spd_pie_idx, dpfm_matched_num);
+        IPC_ASSERT(p_mirror_spd);
+
+        ipc_dpfm_push_gpd_to_routing_queue(uplink, dpfm_out_netif_id, (qbm_gpd *)p_mirror_spd);
+    }
+#endif
+
+    return remain_packet_num;
+}
+
+static INLINE kal_uint16 ipc_do_filter(kal_bool uplink,
+                                       ipc_filter_list_t **fls_set_p,
+                                       kal_uint32 fls_set_cnt,
+                                       kal_uint8 session_type,
+                                       kal_uint32 pdn_id,
+                                       kal_uint32 netif_id,
+                                       qbm_gpd **pp_head,
+                                       qbm_gpd **pp_tail)
+{
+    qbm_gpd *first_gpd = NULL;
+    qbm_gpd *last_gpd = NULL;
+    qbm_gpd *curr_gpd = NULL;
+    qbm_gpd *prev_gpd = NULL;
+    qbm_gpd *next_gpd = NULL;
+    qbm_gpd *curr_bd = NULL;
+    kal_bool end_of_list = KAL_FALSE;
+    kal_uint8 ebi_info = 0; // for record ebi, which is saved in the 1st GPD
+    kal_uint8 *ip_packet = NULL;
+    kal_uint32 length = 0;
+    ipc_filter_t *filter = NULL;
+    ipc_filter_info_t filter_info = {0};
+    ipc_packet_info_t packet_info = {0};
+    kal_bool spd = KAL_FALSE;
+    kal_uint8 remain_packet_num = 0; // the num of packets not filtered out
+    kal_uint32 total_remain_packet_num = 0; // the total num of packets not filtered out
+    ipc_pkt_do_filter_result_e result = IPC_PKT_DO_FILTER_NOT_MATCHED;
+    ipc_pkt_des_t packet_des = {0};
+    kal_uint8 ip_type = 0;
+    kal_uint8 idx = (KAL_TRUE == uplink) ? 1 : 0;
+
+    first_gpd = *pp_head;
+    last_gpd = *pp_tail;
+
+    if (first_gpd) {
+        ebi_info = ((upcm_dlvr_dl_info_t *) QBM_DES_GET_SW_CTRL_FIELD(first_gpd))->ebi;
+    }
+
+    prev_gpd = NULL;
+    end_of_list = (NULL == first_gpd);
+
+    /* Init packet_des */
+    kal_mem_set(&packet_des, 0, sizeof(ipc_pkt_des_t));
+    packet_des.des_type = IPC_PKT_DES_TYPE_GPD;
+    packet_des.matched_filter = &filter;
+    packet_des.filter_info = &filter_info;
+    packet_des.packet_info = &packet_info;
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    {
+        /*
+         * Check ipc_dpfm_packet_routing_queue has been set to 0 or not.
+         * It should be done before calling ipc_do_filter().
+         */
+        kal_uint32 i;
+
+        for (i = 0; i < IPC_MAX_NETIF_CNT; i++) {
+            IPC_ASSERT( (ipc_dpfm_packet_routing_queue[idx][i].first_gpd == NULL) &&
+                        (ipc_dpfm_packet_routing_queue[idx][i].last_gpd == NULL) );
+        }
+        IPC_ASSERT(!ipc_dpfm_queue_non_empty[idx]);
+    }
+#endif
+
+    for (curr_gpd = first_gpd; curr_gpd && !end_of_list; curr_gpd = next_gpd) {
+        spd = (QBM_DES_GET_PDT(curr_gpd) != 0);
+
+        next_gpd = QBM_DES_GET_NEXT(curr_gpd);
+        end_of_list = (curr_gpd == last_gpd);
+        result = IPC_PKT_DO_FILTER_NONE; // reset for each GPD
+
+        if (spd) {
+            /*
+             * It's SPD (PDT != 0)
+             * Need to traverse all of the packets in it.
+             */
+            remain_packet_num = ipc_spd_do_filter(uplink, fls_set_p, fls_set_cnt, session_type, pdn_id, netif_id, ebi_info, curr_gpd);
+
+            if (0 == remain_packet_num) {
+                /*
+                 * All packets of the SPD were filtered out,
+                 * extract the SPD from the list.
+                 */
+                ipc_utils_gpd_list_del_entry(&first_gpd, &last_gpd, &curr_gpd, &prev_gpd, &next_gpd);
+
+                /* Destroy SPD since there is no packet remained. */
+                hif_data_trace(MD_TRC_IPC_GE_SPD_ALL_IGR_INFO, uplink, curr_gpd, QBM_SPD_PI_GET_PKTNUM(QBM_SPD_GET_PI((qbm_spd *) curr_gpd)));
+                qbmt_dest_q(curr_gpd, curr_gpd);
+            } else {
+                /* Update prev_gpd if the curr_gpd is not deleted from the list. */
+                prev_gpd = curr_gpd;
+                total_remain_packet_num += remain_packet_num;
+            }
+        } else {
+            /*
+             * It's GPD (PDT == 0)
+             * There is only one packet, so just do it.
+             */
+            /*
+             * For DL 3G packet, packet content might be divided in several pieces in BD list.
+             * To handle this situation, IPCore MUST aware this during packet content checking.
+             */
+            if (KAL_TRUE != ipc_filter_get_ip_pkt(curr_gpd, &curr_bd, &ip_packet, &length)) {
+                hif_trace_error(IPC_TR_DO_FILTER_INVALID_GPD, curr_gpd);
+                result = IPC_PKT_DO_FILTER_ERROR;
+            } else {
+                /* Fill packet_des */
+                packet_des.packet = ip_packet;
+                packet_des.packet_len = length;
+                packet_des.gpd = curr_gpd;
+                packet_des.bd = curr_bd;
+                packet_des.is_packet_info = KAL_FALSE;
+                packet_des.ip_type = ip_type = (IPC_HDR_IS_V4(ip_packet)) ? IPC_IP_TYPE_IPV4 : IPC_IP_TYPE_IPV6;
+
+                result = ipc_pkt_do_filter(uplink, fls_set_p, fls_set_cnt, ip_type, pdn_id, netif_id, ebi_info, &packet_des);
+            }
+
+            if (IPC_PKT_DO_FILTER_MATCHED == result) {
+                /* Delete curr_gpd from the list */
+                ipc_utils_gpd_list_del_entry(&first_gpd, &last_gpd, &curr_gpd, &prev_gpd, &next_gpd);
+
+                {
+                    /* Forward "curr_gpd" to callback function */
+                    qbm_gpd *callback_gpd_p;
+
+                    length = QBM_DES_GET_DATALEN(curr_gpd);
+
+                    if (KAL_TRUE == uplink) { /* For UL GPD, NO unite issue */
+                        callback_gpd_p = curr_gpd;
+                    } else {
+                        /* For DL GPD, do unite before actually calling callback functions */
+                        ipc_utils_unite_gpd(uplink, curr_gpd, &callback_gpd_p);
+
+                        if (callback_gpd_p != curr_gpd) {
+                            hif_data_trace(MD_TRC_IPC_GE_DO_FILTER_GPD_UPDATE, uplink, curr_gpd, callback_gpd_p,
+                                           (callback_gpd_p) ? (QBM_DES_GET_DATALEN(callback_gpd_p)) : 0);
+
+                            /* Always destroy "curr_gpd" */
+                            QBM_DES_SET_NEXT(curr_gpd, NULL);
+                            qbmt_dest_q(curr_gpd, curr_gpd);
+                        }
+
+                        if (!callback_gpd_p) {
+                            hif_data_trace(MD_TRC_IPC_GE_UNITE_FAIL_DROP, length, curr_gpd);
+                            hif_data_trace(MD_TRC_IPC_GE_UNITE_FAIL_DROP_INFO, filter->filter_id, curr_gpd, pdn_id, netif_id);
+                            continue;
+                        }
+                    }
+
+                    /* Forward GPD by filter's callback function */
+                    ipc_call_filter_cbk(uplink, callback_gpd_p, callback_gpd_p, length, filter, &filter_info);
+                }
+            } else if (IPC_PKT_DO_FILTER_HANDLE_FRAG == result) {
+                qbm_gpd *callback_gpd_p;
+                ipc_frag_refilter_info_t info;
+
+                /* Delete curr_gpd from the list */
+                ipc_utils_gpd_list_del_entry(&first_gpd, &last_gpd, &curr_gpd, &prev_gpd, &next_gpd);
+                ipc_utils_unite_gpd(uplink, curr_gpd, &callback_gpd_p);
+
+                if (callback_gpd_p != curr_gpd) {
+                    /* Always destroy "curr_gpd" */
+                    QBM_DES_SET_NEXT(curr_gpd, NULL);
+                    qbmt_dest_q(curr_gpd, curr_gpd);
+                }
+
+                info.netif_id = netif_id;
+                info.pdn_id = pdn_id;
+                info.uplink = KAL_FALSE;
+                info.is_pkt_info = KAL_TRUE;
+                info.packet_info = &packet_info;
+                info.filter_id = filter->filter_id;
+                info.filter_magic_number = ipc_filter_magic_number_s;
+                ((upcm_dlvr_dl_info_t *) QBM_DES_GET_SW_CTRL_FIELD(callback_gpd_p))->ebi = ebi_info;
+
+                ipc_fragment_defrag(callback_gpd_p, &info, (IPC_HDR_IS_V4(ip_packet)) ? IPC_IP_TYPE_IPV4 : IPC_IP_TYPE_IPV6);
+
+            } else if (IPC_PKT_DO_FILTER_INVALID_LEN == result) {
+                /* Delete curr_gpd from the list & destroy the GPD */
+                ipc_utils_gpd_list_del_entry(&first_gpd, &last_gpd, &curr_gpd, &prev_gpd, &next_gpd);
+                qbmt_dest_q(curr_gpd, curr_gpd);
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+            } else if (IPC_PKT_DO_FILTER_DPFM_MATCHED == result) {
+                /* Delete curr_gpd from the list & push the GPD to DPFM queue */
+                ipc_utils_gpd_list_del_entry(&first_gpd, &last_gpd, &curr_gpd, &prev_gpd, &next_gpd);
+                ipc_dpfm_push_gpd_to_routing_queue(uplink, packet_info.out_netif_id, curr_gpd);
+#endif
+            } else {
+                /* Update prev_gpd if the curr_gpd is not deleted from the list. */
+                prev_gpd = curr_gpd;
+                total_remain_packet_num++;
+                total_remain_packet_num |= IPC_HAS_GPD_MASK;
+            }
+        }
+
+    } /* for each GPD, curr_gpd */
+
+    *pp_head = first_gpd;
+    *pp_tail = last_gpd;
+
+    return total_remain_packet_num;
+}
+
+kal_uint16 ipc_do_ul_filter(kal_uint8 session_type,
+                            kal_uint32 netif_id,
+                            qbm_gpd **pp_head,
+                            qbm_gpd **pp_tail)
+{
+    static ipc_filter_list_t *fls_set[] = {ipc_ul_v4_filter_list_s,
+                                           ipc_ul_v6_filter_list_s};
+
+    return ipc_do_filter(KAL_TRUE, fls_set, sizeof(fls_set) / sizeof(ipc_filter_list_t*), session_type, 0, netif_id, pp_head, pp_tail);
+}
+
+kal_uint16 ipc_do_dl_filter(kal_uint8 session_type,
+                            kal_uint32 netif_id,
+                            kal_uint32 pdn_id,
+                            qbm_gpd **pp_head,
+                            qbm_gpd **pp_tail)
+{
+    static ipc_filter_list_t *fls_set[] = {ipc_dl_v4_filter_list_s,
+                                           ipc_dl_v6_filter_list_s};
+
+    return ipc_do_filter(KAL_FALSE, fls_set, sizeof(fls_set) / sizeof(ipc_filter_list_t*), session_type, pdn_id, netif_id, pp_head, pp_tail);
+}
+
+void ipc_frag_refilter(kal_uint8 ip_type,
+                       ipc_frag_refilter_info_t *info,
+                       qbm_gpd *p_head,
+                       qbm_gpd *p_tail)
+{
+    static ipc_filter_list_t *fls_ul_set[] = {ipc_ul_v4_filter_list_s,
+                                              ipc_ul_v6_filter_list_s};
+    static ipc_filter_list_t *fls_dl_set[] = {ipc_dl_v4_filter_list_s,
+                                              ipc_dl_v6_filter_list_s};
+
+    ipc_pkt_do_filter_result_e match_result = IPC_PKT_DO_FILTER_NOT_MATCHED;
+    kal_uint8 ebi_info = 0;
+    qbm_gpd *curr_bd = NULL;
+    kal_uint8 *ip_packet = NULL;
+    kal_uint32 length = 0;
+    ipc_pkt_des_t packet_des = {0};
+    ipc_filter_t *filter = NULL;
+    ipc_filter_t *matched_filter = NULL;
+    ipc_filter_info_t filter_info = {0};
+
+    IPC_ASSERT(p_head && p_tail && info);
+
+    if (p_head) {
+        ebi_info = ((upcm_dlvr_dl_info_t *) QBM_DES_GET_SW_CTRL_FIELD(p_head))->ebi;
+    }
+
+    /* Set fragment to KAL_FALSE */
+    info->packet_info->fragment = KAL_FALSE;
+
+    /* Get packet and len*/
+    if (KAL_TRUE != ipc_filter_get_ip_pkt(p_head, &curr_bd, &ip_packet, &length)) {
+        IPC_ASSERT(KAL_FALSE);
+    }
+
+    /*
+     * If filter lists haven't been changed (magic number hasn't changed),
+     * do Quick-Refiltering: only match the original matched filter.
+     */
+    if ((info->filter_magic_number == ipc_filter_magic_number_s) &&
+        (IPC_INVALID_FILTER_ID != info->filter_id) && info->is_pkt_info == KAL_TRUE) {
+
+        filter = ipc_find_filter_by_id(ipc_filter_pool_s, info->filter_id);
+        if ((NULL != filter) && (IPC_INVALID_FILTER_ID != filter->filter_id)) {
+            match_result = ipc_pkt_do_one_filter(info->uplink, ip_type, info->packet_info, filter, info->pdn_id, info->netif_id, ebi_info, &matched_filter, &filter_info);
+
+            if (match_result) {
+                IPC_ASSERT(matched_filter == filter);
+                IPC_ASSERT(IPC_PKT_DO_FILTER_HANDLE_FRAG != match_result);
+
+                goto match_done;
+            }
+        }
+    }
+
+    /* Refiltering: go through all filters */
+
+    /* Init packet_des */
+    kal_mem_set(&packet_des, 0, sizeof(ipc_pkt_des_t));
+    packet_des.des_type = IPC_PKT_DES_TYPE_GPD;
+    packet_des.matched_filter = &filter;
+    packet_des.filter_info = &filter_info;
+    packet_des.packet_info = info->packet_info;
+
+    if (info->is_pkt_info == KAL_FALSE) {
+        IPC_ASSERT(ip_packet && p_head);
+        ipc_get_packet_info_gpd(ip_packet, p_head, curr_bd, packet_des.packet_info);
+        //Debug fragment, spi, protocol
+    } else {
+        /* Clear fragment indicator in packet_info */
+        packet_des.packet_info->fragment = KAL_FALSE;
+    }
+    packet_des.is_packet_info = KAL_TRUE; /* already get info, get info GPD */
+
+
+    /* Fill packet_des */
+    packet_des.packet = ip_packet;
+    packet_des.packet_len = length;
+    packet_des.gpd = p_head;
+    packet_des.bd = curr_bd;
+
+
+    if (info->uplink) {
+        match_result = ipc_pkt_do_filter(KAL_TRUE, fls_ul_set, sizeof(fls_ul_set) / sizeof(ipc_filter_list_t*), ip_type, info->pdn_id, info->netif_id, ebi_info, &packet_des);
+    } else {
+        match_result = ipc_pkt_do_filter(KAL_FALSE, fls_dl_set, sizeof(fls_dl_set) / sizeof(ipc_filter_list_t*), ip_type, info->pdn_id, info->netif_id, ebi_info, &packet_des);
+    }
+
+match_done:
+    if ((NULL != filter) && (IPC_PKT_DO_FILTER_MATCHED == match_result)) {
+        if (_FEATURES_CONTAIN(&filter->rules, CUST_FILTER)) {
+            if (KAL_FALSE == filter->cust_cbk_func(ip_packet,
+                                                   length,
+                                                   filter->filter_id,
+                                                   filter->p_cust_cbk_args)) {
+                match_result = IPC_PKT_DO_FILTER_NOT_MATCHED;
+            }
+        }
+        hif_data_trace(MD_TRC_IPC_TR_CUST_FILTER_CBK, ip_packet, length, filter->filter_id, match_result);
+    }
+
+    switch (match_result) {
+        ipc_pkt_t pkt;
+
+        case IPC_PKT_DO_FILTER_MATCHED:
+            ipc_call_filter_cbk(info->uplink, p_head, p_tail, length, filter, &filter_info);
+            break;
+        case IPC_PKT_DO_FILTER_NOT_MATCHED:
+        case IPC_PKT_DO_FILTER_BWM_MATCHED:
+            pkt.buf_type = IPC_PKT_DES_TYPE_GPD;
+            pkt.head = p_head;
+            pkt.tail = p_tail;
+
+            if (info->uplink) {
+                ipc_send_ul_pkt_by_netif_id(&pkt, NULL, info->netif_id, ip_type);
+            } else {
+                ipc_send_dl_pkt_in_did_internal(&pkt, NULL, info->netif_id);
+            }
+            break;
+        case IPC_PKT_DO_FILTER_HANDLE_FRAG:
+            ipc_fragment_defrag(p_head, info, (IPC_HDR_IS_V4(ip_packet)) ? IPC_IP_TYPE_IPV4 : IPC_IP_TYPE_IPV6);
+            break;
+        default:
+            IPC_ASSERT(KAL_FALSE);
+            break;
+    }
+}
+
+void ipc_frag_send_pkt(kal_uint8 ip_type,
+                       ipc_frag_refilter_info_t *info,
+                       qbm_gpd *p_head,
+                       qbm_gpd *p_tail)
+{
+    ipc_pkt_t pkt;
+
+    IPC_ASSERT(p_head && p_tail && info);
+
+    pkt.buf_type = IPC_PKT_DES_TYPE_GPD;
+    pkt.head = p_head;
+    pkt.tail = p_tail;
+
+    if (info->uplink) {
+        ipc_send_ul_pkt_by_netif_id(&pkt, NULL, info->netif_id, ip_type);
+    } else {
+        ipc_send_dl_pkt_in_did_internal(&pkt, NULL, info->netif_id);
+    }
+}
+
+static void ipc_filter_fwd_pkt_by_msg(msg_type msg_id,
+                                      void *context,
+                                      kal_int32 filter_id,
+                                      qbm_gpd *head_gpd,
+                                      qbm_gpd *tail_gpd,
+                                      kal_uint32 length)
+{
+    ipc_filter_t *filter = (ipc_filter_t *)context;
+    ipc_packet_filtered_req_t *req = NULL;
+
+    req = (ipc_packet_filtered_req_t *) construct_local_para(sizeof(ipc_packet_filtered_req_t), TD_RESET);
+    req->context = filter->module_context;
+    req->filter_id = filter_id;
+    req->head_gpd = head_gpd;
+    req->tail_gpd = tail_gpd;
+    req->length = length;
+
+    msg_send6(IPCORE_SRC_MOD,    /* src mod id */
+              filter->module_id, /* dest_mod_id */
+              IPCORE_SAP,        /* sap_id */
+              msg_id,            /* msg_id */
+              (local_para_struct *)req, /* local_para_ptr */
+              NULL);                    /* peer_buff_ptr */
+}
+
+static void ipc_filter_fwd_pkt_with_info_by_msg(msg_type msg_id,
+                                                ipc_filter_info_t *info_p,
+                                                void *context,
+                                                kal_int32 filter_id,
+                                                qbm_gpd *head_gpd,
+                                                qbm_gpd *tail_gpd,
+                                                kal_uint32 length)
+{
+    ipc_filter_t *filter = (ipc_filter_t *)context;
+    ipc_packet_filtered_with_info_req_t *req = NULL;
+
+    req = (ipc_packet_filtered_with_info_req_t *) construct_local_para(sizeof(ipc_packet_filtered_with_info_req_t), TD_RESET);
+    kal_mem_cpy(&(req->info), info_p, sizeof(ipc_filter_info_t));
+    req->context = filter->module_context;
+    req->filter_id = filter_id;
+    req->head_gpd = head_gpd;
+    req->tail_gpd = tail_gpd;
+    req->length = length;
+
+    msg_send6(IPCORE_SRC_MOD,    /* src_mod_id */
+              filter->module_id, /* dest_mod_id */
+              IPCORE_SAP,        /* sap_id */
+              msg_id,            /* msg_id */
+              (local_para_struct *)req, /* local_para_ptr */
+              NULL);                    /* peer_buff_ptr */
+}
+
+void ipc_filter_fwd_ul_pkt_by_msg(void *context,
+                                  kal_int32 filter_id,
+                                  qbm_gpd *head_gpd,
+                                  qbm_gpd *tail_gpd,
+                                  kal_uint32 length)
+{
+    ipc_filter_fwd_pkt_by_msg(MSG_ID_IPCORE_UL_PACKET_FILTERED_REQ,
+                              context,
+                              filter_id,
+                              head_gpd,
+                              tail_gpd,
+                              length);
+}
+
+void ipc_filter_fwd_dl_pkt_by_msg(void *context,
+                                  kal_int32 filter_id,
+                                  qbm_gpd *head_gpd,
+                                  qbm_gpd *tail_gpd,
+                                  kal_uint32 length)
+{
+    ipc_filter_fwd_pkt_by_msg(MSG_ID_IPCORE_DL_PACKET_FILTERED_REQ,
+                              context,
+                              filter_id,
+                              head_gpd,
+                              tail_gpd,
+                              length);
+}
+
+void ipc_filter_fwd_ul_pkt_with_info_by_msg(ipc_filter_info_t *info_p,
+                                            void *context,
+                                            kal_int32 filter_id,
+                                            qbm_gpd *head_gpd,
+                                            qbm_gpd *tail_gpd,
+                                            kal_uint32 length)
+{
+    ipc_filter_fwd_pkt_with_info_by_msg(MSG_ID_IPCORE_UL_PACKET_FILTERED_WITH_INFO_REQ,
+                                        info_p,
+                                        context,
+                                        filter_id,
+                                        head_gpd,
+                                        tail_gpd,
+                                        length);
+}
+
+void ipc_filter_fwd_dl_pkt_with_info_by_msg(ipc_filter_info_t *info_p,
+                                            void *context,
+                                            kal_int32 filter_id,
+                                            qbm_gpd *head_gpd,
+                                            qbm_gpd *tail_gpd,
+                                            kal_uint32 length)
+{
+    ipc_filter_fwd_pkt_with_info_by_msg(MSG_ID_IPCORE_DL_PACKET_FILTERED_WITH_INFO_REQ,
+                                        info_p,
+                                        context,
+                                        filter_id,
+                                        head_gpd,
+                                        tail_gpd,
+                                        length);
+}
+
+/*------------------------------------------------------------------------------
+ * Public functions. (Gen93)
+ *----------------------------------------------------------------------------*/
+kal_uint16 ipc_meta_do_filter(kal_uint8 ip_type,
+                              kal_uint32 netif_id,
+                              lhif_meta_tbl_t *meta,
+                              ipc_dpfm_mirror_des_t *dpfm_mirror_des,
+                              ipc_pkt_des_t *p_packet_des)
+{
+    kal_uint8 *ip_packet = NULL;
+    kal_uint32 length = 0;
+    ipc_pkt_do_filter_result_e result;
+    ipc_filter_t *matched_filter = NULL; /*< alias */
+
+    static ipc_filter_list_t *fls_set[] = {ipc_ul_v4_filter_list_s,
+                                           ipc_ul_v6_filter_list_s};
+
+    IPC_ASSERT(NULL != p_packet_des);
+
+    /* Alias parameter */
+    ip_packet = p_packet_des->packet;
+    length = p_packet_des->packet_len;
+
+    result = ipc_pkt_do_filter(KAL_TRUE, fls_set, sizeof(fls_set) / sizeof(ipc_filter_list_t*), ip_type, 0, netif_id, 0, p_packet_des);
+    matched_filter = *(p_packet_des->matched_filter); //alias
+
+    switch (result) {
+        qbm_gpd *callback_gpd_p = NULL;
+        kal_uint8 *callback_gpd_data_p = NULL;
+
+    case IPC_PKT_DO_FILTER_MATCHED:
+    case IPC_PKT_DO_FILTER_HANDLE_FRAG:
+    case IPC_PKT_DO_FILTER_HANDLE_CLONE:
+        /*
+         * 1. A packet is indivisible from the meta, so we need to allocate a GPD for it.
+         * 2. Meta is for uplink only.
+         */
+        if (1 != qbmt_alloc_q_no_tail(QBM_TYPE_NET_UL_SHRD, 1, (void**) &callback_gpd_p, (void**) &callback_gpd_p)) {
+            hif_trace_error(IPC_TR_META_DO_FILTER_ALLOC_GPD_NG, KAL_FALSE, meta);
+            meta->ignore = 1;
+            IPC_FREE_META_VRB(meta);
+            return 0;
+        }
+
+        /* Copy data from UL META to output GPD */
+        IPC_ASSERT(callback_gpd_p);
+        ipc_utils_set_gpd_datalen(callback_gpd_p, length, (void**) &callback_gpd_data_p);
+        IPC_ASSERT(callback_gpd_data_p);
+
+        QBM_CACHE_INVALID(ip_packet, length);
+        kal_mem_cpy(callback_gpd_data_p, ip_packet, length);
+        QBM_CACHE_FLUSH(callback_gpd_data_p, length);
+
+        if ((IPC_PKT_DO_FILTER_MATCHED == result) || (IPC_PKT_DO_FILTER_HANDLE_CLONE == result)) {
+            /* Forward GPD by filter's callback function */
+            ipc_call_filter_cbk(KAL_TRUE, callback_gpd_p, callback_gpd_p, length, matched_filter, p_packet_des->filter_info);
+        } else {
+            /* Forward GPD to ipc_fragment sub-module to handle fragment. */
+            ipc_frag_refilter_info_t info;
+
+            info.netif_id = netif_id;
+            info.pdn_id = IPC_INVALID_PDN_ID;
+            info.uplink = KAL_TRUE;
+            info.is_pkt_info = KAL_TRUE;
+            info.packet_info = p_packet_des->packet_info;
+            info.filter_id = matched_filter->filter_id;
+            info.filter_magic_number = ipc_filter_magic_number_s;
+
+            ipc_fragment_defrag(callback_gpd_p, &info, ((ip_type == IPC_IP_TYPE_IPV4) ? KAL_TRUE : KAL_FALSE));
+        }
+
+        if (IPC_PKT_DO_FILTER_HANDLE_CLONE == result) {
+            return 1;
+        } else {
+            meta->ignore = KAL_TRUE;
+            IPC_FREE_META_VRB(meta);
+            return 0;
+        }
+
+    case IPC_PKT_DO_FILTER_INVALID_LEN:
+        meta->ignore = KAL_TRUE;
+        IPC_FREE_META_VRB(meta);
+        return 0;
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    case IPC_PKT_DO_FILTER_DPFM_MATCHED: {
+        ipc_packet_info_t* p_packet_info;
+        p_packet_info = p_packet_des->packet_info;
+
+        /* DPFM will set meta ignore and release buffer for delelte filter ACK packet. */
+        if (1 != meta->ignore) {
+            /* Because LAN NETIF is not bound, so HW can't fill corresponding PDN info into meta*/
+            ipc_dpfm_set_pdn_id_in_meta(dpfm_mirror_des, meta, p_packet_info->out_netif_id, ip_type);
+        }
+    }
+        return 0;
+#endif
+
+    case IPC_PKT_DO_FILTER_NOT_MATCHED:
+    case IPC_PKT_DO_FILTER_BWM_MATCHED:
+    default:
+        return 1;
+    }
+}
+
+kal_uint16 ipc_did_do_filter(kal_uint8 session_type,
+                             kal_uint32 netif_id,
+                             kal_uint32 pdn_id,
+                             upcm_did *did)
+{
+    kal_uint8                  *ip_packet;
+    kal_uint8                   ip_type;
+    kal_uint32                  packet_len;
+    ipc_filter_t               *filter;
+    ipc_filter_info_t           filter_info;
+    ipc_packet_info_t           packet_info;
+    ipc_pkt_do_filter_result_e  result;
+    ipc_pkt_des_t               packet_des;
+    kal_uint32                  pkt_num, seg_num;
+    kal_uint16                  base_psn;
+    kal_uint8                   remain_pkt_cnt = 0;
+    kal_uint8                   total_pkt_cnt = 0;
+    kal_uint8                   remain_seg_cnt = 0;
+    upcm_did_si                *sit;
+    upcm_did_si                *curr_si;
+    kal_uint32                  pkt_start_idx;
+    kal_uint32                  curr_idx = 0;
+    kal_bool                    uplink = KAL_FALSE; // DID is for uplink only.
+    kal_uint8                   comm_buff[16];// max is ipv6 src/dest addr
+    kal_uint8                  *comm_continuous_p = NULL;
+    ipc_si_hif_type_e           hif_type;
+    kal_uint8                   ebi_info;
+    kal_uint32                  bypass_seg_num = 0; /* the number of sit which is ignore && zero length and to be skipped*/
+    static ipc_filter_list_t   *fls_set[] = {ipc_dl_v4_filter_list_s, ipc_dl_v6_filter_list_s};
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    ipc_dpfm_mirror_des_t        dpfm_mirror_des[IPC_DPFM_MAX_DEVICE_NUM];
+    kal_bool                    is_mirror_did = KAL_FALSE;
+    kal_uint32                  i;
+
+    kal_mem_set(dpfm_mirror_des, 0, sizeof(dpfm_mirror_des));
+    for (i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++) {
+        dpfm_mirror_des[i].netif_id = IPC_INVALID_NETIF_ID;
+    }
+#endif
+
+    IPC_ASSERT(did);
+
+    pkt_num = UPCM_DID_GET_PKT_NUM(did);
+    seg_num = UPCM_DID_GET_SEG_NUM(did);    /* this num only count valid seg number in DID */
+    base_psn = UPCM_DID_GET_COUNT_L(did);
+    sit = UPCM_DID_GET_SIT_PTR(did);
+    ebi_info = (kal_uint8)UPCM_DID_GET_SW_CTRL_FIELD(did);
+
+    /* Init packet_des */
+    kal_mem_set(&packet_des, 0, sizeof(ipc_pkt_des_t));
+    packet_des.des_type = IPC_PKT_DES_TYPE_DID;
+    packet_des.matched_filter = &filter;
+    packet_des.filter_info = &filter_info;
+    packet_des.packet_info = &packet_info;
+
+    hif_type = ipc_utils_get_hif_type_by_netif_id(netif_id);
+    curr_idx = 0;
+
+#if defined(__MD97__)
+    kal_mem_set(&g_rq_info_list, 0, sizeof(g_rq_info_list));
+    g_rq_info_list.cnt = 0;
+#endif
+
+    while (curr_idx < (seg_num + bypass_seg_num)) {
+        IPC_ASSERT(curr_idx < UPCM_DID_MAX_SIT_ENT_NUM);
+        curr_si = &sit[curr_idx];
+
+        if((IPC_SI_HIF_TYPE_IGR == UPCM_DID_SI_GET_HIF_TYPE(curr_si)) && (UPCM_DID_SI_GET_LEN(curr_si) == 0))
+        {
+            /* if we found the hif_type is ignore and sit length is 0,
+               it means this sit entry is processed last time because of HIF retry.
+               So we have to skip the sit entry and update totoal sit entries for while loop */
+            hif_data_trace(MD_TRC_IPC_DL_DO_FILTER_DID_ZERO_SIT, curr_idx, bypass_seg_num+1, seg_num);
+            curr_idx++;
+            bypass_seg_num++;
+            continue;
+        }
+
+        /* SIT length should not be zero */
+        IPC_ASSERT(UPCM_DID_SI_GET_LEN(curr_si));
+
+        pkt_start_idx = curr_idx;
+        ip_packet = (kal_uint8 *)UPCM_DID_SI_GET_DATAPTR(curr_si) + UPCM_DID_SI_GET_OFFSET(curr_si);
+
+        /* Can't get packet length from the descriptor, so get it from IP header instead. */
+        if (KAL_TRUE != ipc_get_continuous_content_did(ip_packet, 0, did, curr_idx, 6, &comm_continuous_p, comm_buff))
+        {
+            hif_trace_error(IPC_TR_DID_GET_PKT_LENGTH_FAILED, ip_packet, did, curr_idx);
+            result = IPC_PKT_DO_FILTER_ERROR;
+            goto process_pkt;
+        }
+        if (IPC_HDR_IS_V4(comm_continuous_p)) {
+            packet_len = IPC_HDR_V4_GET_TOTAL_LENGTH(comm_continuous_p);
+            ip_type = IPC_IP_TYPE_IPV4;
+        } else if (IPC_HDR_IS_V6(comm_continuous_p)) {
+            packet_len = IPC_HDR_V6_GET_LENGTH(comm_continuous_p) + IPC_HDR_V6_HEADER_SIZE;
+            ip_type = IPC_IP_TYPE_IPV6;
+        } else {
+            result = IPC_PKT_DO_FILTER_ERROR;
+            goto process_pkt;
+        }
+
+        /* Fill packet_des */
+        packet_des.packet = ip_packet;
+        packet_des.packet_len = packet_len;
+        packet_des.did = did;
+        packet_des.pkt_start_idx = pkt_start_idx;
+        packet_des.psn = base_psn + total_pkt_cnt;
+        packet_des.ip_type = ip_type;
+        packet_des.is_packet_info = KAL_FALSE;
+        kal_mem_set(&packet_info, 0, sizeof(ipc_packet_info_t));
+
+        result = ipc_pkt_do_filter(KAL_FALSE, fls_set, sizeof(fls_set)/sizeof(ipc_filter_list_t*), ip_type, pdn_id, netif_id, ebi_info, &packet_des);
+
+process_pkt:
+        switch (result) {
+            qbm_gpd    *callback_gpd_p;
+            qbm_type   type;
+            ipc_data_usage_info_t data_usage = {0};
+
+            case IPC_PKT_DO_FILTER_HANDLE_CLONE:
+            case IPC_PKT_DO_FILTER_MATCHED:
+                type = (uplink)?QBM_TYPE_NET_UL_SHRD:QBM_TYPE_NET_DL;
+                if (KAL_FALSE == ipc_utils_sit_to_gpd(type, did, curr_idx, packet_des.packet_len, &callback_gpd_p)) {
+                    /* Free the data when GPD is exhausted */
+                    ipc_utils_pkt_set_si_hif_type(did, IPC_SI_HIF_TYPE_IGR, &curr_idx);
+                    break;
+                }
+
+                /*Set Data usage for current packet*/
+                data_usage.downlink_bytes = packet_len;
+                data_usage.downlink_packets = 1;
+                ipc_set_data_usage_by_pdn_sim_id(DL_DIRECT, pdn_id, &data_usage);
+
+                if (IPC_PKT_DO_FILTER_MATCHED == result) {
+                    ipc_utils_pkt_set_si_hif_type(did, IPC_SI_HIF_TYPE_IGR, &curr_idx);
+                } else {
+                    ipc_utils_pkt_set_si_hif_type(did, hif_type, &curr_idx);
+                    remain_seg_cnt += curr_idx - pkt_start_idx;
+                    remain_pkt_cnt ++;
+                    hif_trace_info(IPC_TR_FILTER_MATCHED_CLONED_DEFAULT_PATH);
+                }
+
+                if (callback_gpd_p) {
+                    if(KAL_TRUE == filter->callback_with_info)
+                    {
+                        filter_info.src_desc_ptr = (void*) did;
+                        filter_info.src_desc_type = IPC_FI_DESC_TYPE_DID;
+                        filter_info.src_desc_indx = pkt_start_idx;
+                    }
+                    /* Forward GPD by filter's callback function */
+                    ipc_call_filter_cbk(KAL_FALSE, callback_gpd_p, callback_gpd_p, packet_len, filter, &filter_info);
+                }
+                break;
+
+            case IPC_PKT_DO_FILTER_INVALID_LEN:
+                ipc_utils_pkt_set_si_hif_type(did, IPC_SI_HIF_TYPE_IGR, &curr_idx);
+                break;
+
+            case IPC_PKT_DO_FILTER_HANDLE_FRAG:
+                type = (uplink)?QBM_TYPE_NET_UL_SHRD:QBM_TYPE_NET_DL;
+                ipc_utils_sit_to_gpd(type, did, curr_idx, packet_des.packet_len, &callback_gpd_p);
+                ipc_utils_pkt_set_si_hif_type(did, IPC_SI_HIF_TYPE_IGR, &curr_idx);
+
+                if (callback_gpd_p) {
+                    /* Forward GPD to ipc_fragment sub-module to handle fragment. */
+                    ipc_frag_refilter_info_t    info;
+
+                    info.netif_id = netif_id;
+                    info.pdn_id = pdn_id;
+                    info.uplink = KAL_FALSE;
+                    info.is_pkt_info = KAL_TRUE;
+                    info.packet_info = &packet_info;
+                    info.filter_id = filter->filter_id;
+                    info.filter_magic_number = ipc_filter_magic_number_s;
+                    ((upcm_dlvr_dl_info_t *)QBM_DES_GET_SW_CTRL_FIELD(callback_gpd_p))->ebi = ebi_info;
+
+                    ipc_fragment_defrag(callback_gpd_p, &info, ((ip_type == IPC_IP_TYPE_IPV4) ? KAL_TRUE : KAL_FALSE) );
+                }
+                break;
+
+        #if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+            case IPC_PKT_DO_FILTER_DPFM_MATCHED:
+                if (!ipc_dpfm_set_pkt_in_did_mirror_des(dpfm_mirror_des, did, &curr_idx, packet_info.out_netif_id)) {
+                    /*
+                     * Direct path is not available.
+                     * Send packets to default route (indirect path).
+                     */
+                    ipc_utils_pkt_set_si_hif_type(did, hif_type, &curr_idx);
+
+                    remain_seg_cnt += curr_idx - pkt_start_idx;
+                    remain_pkt_cnt ++;
+                    break;
+                }
+                is_mirror_did = KAL_TRUE;
+                break;
+        #endif
+
+            case IPC_PKT_DO_FILTER_NOT_MATCHED:
+            case IPC_PKT_DO_FILTER_BWM_MATCHED:
+            case IPC_PKT_DO_FILTER_ERROR:
+            default:
+                ipc_utils_pkt_set_si_hif_type(did, hif_type, &curr_idx);
+
+                remain_seg_cnt += curr_idx - pkt_start_idx;
+                remain_pkt_cnt ++;
+                break;
+        }
+
+#if defined(__MD97__)
+        if ((IPC_PKT_DO_FILTER_ERROR != result) && (curr_si->nrqi)) {
+            ipc_rq_info_t rq_info = {0};
+
+            if (KAL_FALSE == packet_des.is_packet_info) {
+                if (KAL_FALSE == ipc_get_packet_info_did(ip_packet, did, curr_idx, packet_des.packet_info)) {
+                    hif_trace_error(IPC_TR_NO_PKT_INFO_DID);
+                } else {
+                    packet_des.is_packet_info = KAL_TRUE;
+                }
+            }
+
+            if (ipc_data_set_rq_info(&rq_info, pdn_id, &packet_des, IPC_DATA_QFI_SRC_DL_DID)) {
+                ipc_data_saved_rq_info_list(&g_rq_info_list, &rq_info);
+            }
+        }
+#endif
+
+        total_pkt_cnt ++;
+    }
+
+#if defined(__MD97__)
+    ipc_data_send_rq_info(&g_rq_info_list);
+#endif
+
+    IPC_ASSERT(remain_pkt_cnt <= pkt_num);
+    IPC_ASSERT(total_pkt_cnt == pkt_num);
+    IPC_ASSERT(remain_seg_cnt <= seg_num);
+
+    UPCM_DID_SET_PKT_NUM(did, remain_pkt_cnt);
+    UPCM_DID_SET_SEG_NUM(did, remain_seg_cnt);
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+    if (is_mirror_did) {
+        for (i = 0; i < IPC_DPFM_MAX_DEVICE_NUM; i++) {
+            if (dpfm_mirror_des[i].mirror_did_head) {
+                ipc_pkt_t           pkt;
+
+                ipc_dpfm_mirror_did(&(dpfm_mirror_des[i]), did);
+                IPC_ASSERT(dpfm_mirror_des[i].netif_id != IPC_INVALID_NETIF_ID);
+
+                pkt.buf_type = IPC_PKT_DES_TYPE_DID;
+                pkt.did_head = dpfm_mirror_des[i].mirror_did_head;
+                pkt.did_tail = dpfm_mirror_des[i].mirror_did_tail;
+
+                ipc_send_dl_pkt_in_did_internal(&pkt, NULL, dpfm_mirror_des[i].netif_id);
+            }
+        }
+    }
+#endif
+
+    return remain_pkt_cnt;
+}
+
+/*------------------------------------------------------------------------------
+ * Public functions. (Gen95)
+ *----------------------------------------------------------------------------*/
+#if defined(__IPF_SUPPORT__)
+
+/* check if the specified filter is matched, otherwise go through all filters */
+void ipc_ipf_meta_do_filter(kal_int32 filter_id,
+                            ipc_pkt_des_t *packet_des,
+                            kal_uint8 ip_type,
+                            kal_uint8 pdn_sim_id,
+                            kal_uint32 netif_id,
+                            ipc_dpfm_mirror_des_t *dpfm_mirror_des,
+                            kal_bool *is_mirror_did,
+                            kal_bool *is_saved)
+{
+    static ipc_filter_list_t *fls_dl_set[] = {ipc_dl_v4_filter_list_s,
+                                              ipc_dl_v6_filter_list_s};
+    ipc_filter_t *filter = NULL;
+    ipc_pkt_do_filter_result_e match_result = IPC_PKT_DO_FILTER_NOT_MATCHED;
+    kal_bool ret = KAL_FALSE;
+    ipc_pkt_t pkt = {0};
+    ipf_dl_meta *meta = (ipf_dl_meta *) (packet_des->ipf_meta);
+
+    /* Alias local parameter */
+    kal_uint8 *ip_packet = packet_des->packet;
+    kal_uint32 packet_len = packet_des->packet_len;
+    ipc_filter_t **pp_matched_filter = packet_des->matched_filter;
+    ipc_filter_info_t *p_filter_info = packet_des->filter_info;
+    ipc_packet_info_t *p_packet_info = packet_des->packet_info;
+    kal_uint32 fls_set_cnt = sizeof(fls_dl_set) / sizeof(ipc_filter_list_t*);
+
+    /* Check IP Type */
+    if (IPC_IP_TYPE_INVALID == ip_type) {
+        QBM_CACHE_INVALID(ip_packet, 1);
+        if (IPC_HDR_IS_V4(ip_packet)) {
+            ip_type = IPC_IP_TYPE_IPV4;
+        } else if (IPC_HDR_IS_V6(ip_packet)) {
+            ip_type = IPC_IP_TYPE_IPV6;
+        } else {
+            match_result = IPC_PKT_DO_FILTER_ERROR;
+            goto _process_pkt;
+        }
+        packet_des->ip_type = ip_type;
+    }
+
+    /* Process meta match result */
+    switch (meta->mr) {
+        case IPC_IPF_MR_FILTER_MATCH:
+        case IPC_IPF_MR_UNKNOWN_HEADER:
+            if (filter_id != IPC_INVALID_FILTER_ID) {
+                filter = ipc_find_filter_by_id(ipc_filter_pool_s, filter_id);
+                if ((NULL != filter) && (IPC_INVALID_FILTER_ID != filter->filter_id)) {
+                    /* Get packet info for quick filtering */
+                    ret = ipc_get_packet_info(ip_packet, packet_len, p_packet_info);
+                    if (KAL_FALSE == ret) {
+                        match_result = IPC_PKT_DO_FILTER_NOT_MATCHED;
+                        break;
+                    }
+
+                    packet_des->is_packet_info = KAL_TRUE;
+
+                    /* If filter feature contains IPV6_MDT, skip quick filtering */
+                    if (_FEATURES_CONTAIN(&(filter->rules), IPV6_DPFM)) {
+                        *(packet_des->matched_filter) = filter;
+                        goto _dpfm_check_route;
+                    }
+
+                    /* Do quick filtering for specified filter */
+                    match_result = ipc_pkt_do_one_filter(KAL_FALSE,
+                                                         ip_type,
+                                                         p_packet_info,
+                                                         filter,
+                                                         pdn_sim_id,
+                                                         netif_id,
+                                                         0xFF, /* HW Path no EBI */
+                                                         pp_matched_filter,
+                                                         p_filter_info);
+
+                    if (_FEATURES_CONTAIN(&filter->rules, CUST_FILTER) && (IPC_PKT_DO_FILTER_MATCHED == match_result)) {
+                        if (KAL_FALSE == filter->cust_cbk_func(packet_des->packet,
+                                                               packet_des->packet_len,
+                                                               filter->filter_id,
+                                                               filter->p_cust_cbk_args)) {
+                            match_result = IPC_PKT_DO_FILTER_NOT_MATCHED;
+                        }
+                        hif_data_trace(MD_TRC_IPC_TR_CUST_FILTER_CBK, packet_des->packet, packet_des->packet_len, filter->filter_id, ret);
+                    } else if (_FEATURES_CONTAIN(&filter->rules, CUST_FILTER_W_INFO) && (IPC_PKT_DO_FILTER_MATCHED == match_result)) {
+                        p_filter_info->src_desc_type = IPC_FI_DESC_TYPE_NONE;
+                        if (KAL_FALSE == filter->cust_cbk_func(packet_des->packet,
+                                                               packet_des->packet_len,
+                                                               filter->filter_id,
+                                                               p_filter_info)) {
+                            match_result = IPC_PKT_DO_FILTER_NOT_MATCHED;
+                        }
+                        hif_data_trace(MD_TRC_IPC_TR_CUST_FILTER_CBK, packet_des->packet, packet_des->packet_len, filter->filter_id, ret);
+                    }
+
+                    if (match_result) {
+                        IPC_ASSERT(*pp_matched_filter == filter);
+                        break;
+                    }
+                }
+            }
+
+            /* Do full check when unknown packet and quick match failed */
+            match_result = ipc_pkt_do_filter(KAL_FALSE,
+                                             fls_dl_set,
+                                             fls_set_cnt,
+                                             ip_type,
+                                             pdn_sim_id,
+                                             netif_id,
+                                             0xFF, /* HW Path no EBI */
+                                             packet_des);
+            break;
+
+        case IPC_IPF_MR_DPFM_MATCH:
+_dpfm_check_route :
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+            ret = ipc_dpfm_check_route(KAL_FALSE, packet_des, netif_id);
+
+            if(KAL_TRUE == ret)
+            {
+                hif_data_trace(MD_TRC_IPC_DPFM_CHECK_ROUTE_MATCHED, 0, ip_type, p_packet_info->out_netif_id);
+                match_result = IPC_PKT_DO_FILTER_DPFM_MATCHED;
+            }
+            else
+            {
+                /* forward to AP (default NETIF) */
+                match_result = IPC_PKT_DO_FILTER_NOT_MATCHED;
+            }
+
+            break;
+#endif
+            default:
+            IPC_ASSERT(KAL_FALSE);
+            break;
+    }
+
+_process_pkt :
+    /* Process filter match result */
+    switch (match_result) {
+        case IPC_PKT_DO_FILTER_MATCHED:
+        case IPC_PKT_DO_FILTER_HANDLE_FRAG: {
+            qbm_gpd *callback_gpd_p = NULL;
+            kal_uint8 *callback_gpd_data_p = NULL;
+
+            if (QBM_NET_DL_DATA_LEN < packet_len) {
+                hif_trace_error(IPC_TR_META_TO_GPD_FAIL, __FUNCTION__, packet_len, QBM_TYPE_NET_DL);
+                /* release IPF PRB buffer */
+                IPC_FREE_DL_META_PRB(meta, meta->len);
+                break;
+            }
+
+            filter = *(packet_des->matched_filter);
+
+            if (1 != qbmt_alloc_q_no_tail(QBM_TYPE_NET_DL, /* type */
+                                          1, /* buff_num */
+                                          (void**) &callback_gpd_p, /* pp_head */
+                                          (void**) &callback_gpd_p /* pp_tail */)) {
+
+                hif_trace_error(IPC_TR_META_DO_FILTER_ALLOC_GPD_NG, KAL_FALSE, packet_des->ipf_meta);
+                /* Release PRB when GPD is exhausted */
+                IPC_FREE_DL_META_PRB(meta, meta->len);
+                break;
+            }
+
+            /* Copy data from UL META to output GPD */
+            IPC_ASSERT(callback_gpd_p);
+            ipc_utils_set_gpd_datalen(callback_gpd_p, packet_len, (void**) &callback_gpd_data_p);
+            IPC_ASSERT(callback_gpd_data_p);
+
+            QBM_CACHE_INVALID(ip_packet, packet_len);
+            kal_mem_cpy(callback_gpd_data_p, ip_packet, packet_len);
+            QBM_CACHE_FLUSH(callback_gpd_data_p, packet_len);
+
+            if (IPC_PKT_DO_FILTER_MATCHED == match_result) {
+                /*Set Data usage for current packet*/
+                ipc_data_usage_info_t data_usage = {0};
+                data_usage.downlink_bytes = packet_len;
+                data_usage.downlink_packets = 1;
+                ipc_set_data_usage_by_pdn_sim_id(DL_DIRECT, pdn_sim_id, &data_usage);
+
+                if (KAL_TRUE == filter->callback_with_info) {
+                    /* This case is not SW path, so we can't provide source DID pointer */
+                    p_filter_info->src_desc_ptr = NULL;
+                    p_filter_info->src_desc_type = IPC_FI_DESC_TYPE_NONE;
+                    p_filter_info->src_desc_indx = 0;
+                }
+                /* Forward GPD by filter's callback function */
+                ipc_call_filter_cbk(KAL_FALSE, callback_gpd_p, callback_gpd_p, packet_len, *pp_matched_filter, p_filter_info);
+            } else {
+                /* Forward GPD to ipc_fragment sub-module to handle fragment. */
+                ipc_frag_refilter_info_t info;
+
+                info.netif_id = netif_id;
+                info.pdn_id = pdn_sim_id;
+                info.uplink = KAL_FALSE;
+                info.is_pkt_info = KAL_TRUE;
+                info.packet_info = p_packet_info;
+                info.filter_id = filter->filter_id;
+                info.filter_magic_number = ipc_filter_magic_number_s;
+
+                ipc_fragment_defrag(callback_gpd_p,
+                                    &info,
+                                    ((ip_type == IPC_IP_TYPE_IPV4) ? KAL_TRUE : KAL_FALSE));
+            }
+
+            /* release IPF PRB buffer */
+            IPC_FREE_DL_META_PRB(meta, meta->len);
+        }
+            break;
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+            case IPC_PKT_DO_FILTER_DPFM_MATCHED:
+            {
+                if(!ipc_dpfm_set_ipf_pkt_in_did_mirror_des(dpfm_mirror_des, packet_des, p_packet_info->out_netif_id))
+                {
+                    /* DID is failed to allocate, drop it. */
+                    hif_data_trace(MD_TRC_IPC_DL_META_DROP_DID_ALLOC_NG, p_packet_info->out_netif_id);
+                    IPC_FREE_DL_META_PRB(meta, meta->len);
+                }
+                *is_mirror_did = KAL_TRUE;
+            }
+            break;
+#endif
+        case IPC_PKT_DO_FILTER_ERROR:
+        case IPC_PKT_DO_FILTER_NOT_MATCHED:
+        case IPC_PKT_DO_FILTER_BWM_MATCHED: {
+            pkt.buf_type = IPC_PKT_DES_TYPE_NO_DESC;
+            pkt.data_len = packet_len;
+            pkt.data = ip_packet;
+            if (!ipc_send_dl_pkt_in_did_internal(&pkt, NULL, netif_id)) {
+                /* DID is failed to allocate, drop it. */
+                hif_data_trace(MD_TRC_IPC_DL_META_DROP_DID_ALLOC_NG, netif_id);
+                IPC_FREE_DL_META_PRB(meta, meta->len);
+            }
+        }
+            break;
+        default:
+            IPC_ASSERT(KAL_FALSE);
+            break;
+    }
+
+#if defined(__MD97__)
+    if (meta->mr == IPC_IPF_MR_UNKNOWN_HEADER && match_result != IPC_PKT_DO_FILTER_ERROR) {
+        if (IPC_DATA_GET_QFI(meta->tcp_flag)) {
+            hif_trace_info(IPC_TR_NR_RQI_IS_SET, __FUNCTION__, meta, meta->mr, match_result, meta->tcp_flag);
+            *is_saved = KAL_TRUE;
+        }
+    }
+#endif
+
+    return;
+}
+
+kal_bool ipc_update_one_hw_filter(kal_int32 filter_id,
+                                  ipc_filter_rules_t *p_rules,
+                                  void *p_cur_base)
+{
+    ipv4_filter_rule *hw_filter = NULL;
+    ipv6_filter_rule *hw_filter_v6 = NULL;
+
+    if (NULL == p_rules) {
+        hif_trace_info(IPC_TR_INVALID_FILTER_RULES, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    /*Note : if the value is more than 1 byte, we should transform it to big-endian format. */
+
+    /* do casting with same base address. */
+    hw_filter = (ipv4_filter_rule*) p_cur_base;
+    hw_filter_v6 = (ipv6_filter_rule*) p_cur_base;
+
+    if (_RULES_CONTAIN(p_rules, PDN_ID)) {
+        hw_filter->pdn_sim_id = IPC_MASK_PROTOID_ON_PDNID(p_rules->pdn_id, p_rules->proto_idx);
+        IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_PDNSIM_ID);
+    }
+
+    if (_RULES_CONTAIN_IPV4(p_rules)) {
+        hw_filter->ip = IPF_HW_FILTER_IPV4;
+        if (_RULES_CONTAIN(p_rules, SRC_IPV4)) {
+            /* SRC ADDR means Remote ADDR (DL) */
+            hw_filter->remote_addr0 = p_rules->src_ipv4.addr32;
+            IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_R_ADDR);
+        } else if (_RULES_CONTAIN(p_rules, DST_IPV4)) {
+            //hw_filter->remote_addr0 = p_rules->dst_ipv4.addr32;
+            //IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_L_ADDR);
+        }
+    }
+
+    if (_RULES_CONTAIN_IPV6(p_rules)) {
+        hw_filter_v6->ip = IPF_HW_FILTER_IPV6;
+        hw_filter_v6->ip1 = IPF_HW_FILTER_IPV6_1;
+        if (_RULES_CONTAIN(p_rules, SRC_IPV6)) /* SRC ADDR means Remote ADDR (DL) */
+        {
+            hw_filter_v6->remote_addr0 = p_rules->src_ipv6.addr32[0];
+            hw_filter_v6->remote_addr1 = p_rules->src_ipv6.addr32[1];
+            hw_filter_v6->remote_addr2 = p_rules->src_ipv6.addr32[2];
+            hw_filter_v6->remote_addr3 = p_rules->src_ipv6.addr32[3];
+            IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_R_ADDR);
+        } else if (_RULES_CONTAIN(p_rules, DST_IPV6)) {
+            //hw_filter_v6->remote_addr0 = p_rules->dst_ipv6.addr32[0];
+            //hw_filter_v6->remote_addr1 = p_rules->dst_ipv6.addr32[1];
+            //hw_filter_v6->remote_addr2 = p_rules->dst_ipv6.addr32[2];
+            //hw_filter_v6->remote_addr3 = p_rules->dst_ipv6.addr32[3];
+            //IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_L_ADDR);
+        }
+    }
+
+    if (_RULES_CONTAIN(p_rules, PROTOCOL)) {
+        hw_filter->protocol = p_rules->protocol;
+        IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_PROTO);
+
+        if (_FEATURES_CONTAIN(p_rules, FRAG)) {
+            IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_FRAG);
+        }
+
+        switch (p_rules->protocol) {
+            case IPC_HDR_PROT_UDP:
+            case IPC_HDR_PROT_TCP:
+                if (_RULES_CONTAIN(p_rules, SRC_PORT) && _RULES_CONTAIN(p_rules, DST_PORT)) {
+                    IPC_NE_SET_2B(&(hw_filter->f_pro_word), p_rules->dst_port);
+                    hw_filter->f_pro_word = hw_filter->f_pro_word << 16;
+                    IPC_NE_SET_2B(&(hw_filter->f_pro_word), p_rules->src_port);
+                    IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_F_WORD_TYPE4);
+                } else if (_RULES_CONTAIN(p_rules, DST_PORT)) {
+                    IPC_NE_SET_2B(&(hw_filter->f_pro_word), p_rules->dst_port);
+                    hw_filter->f_pro_word = hw_filter->f_pro_word << 16;
+                    IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_F_WORD_TYPE3);
+                } else if (_RULES_CONTAIN(p_rules, SRC_PORT)) {
+                    IPC_NE_SET_2B(&(hw_filter->f_pro_word), p_rules->src_port);
+                    IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_F_WORD_TYPE2);
+                }
+                break;
+            case IPC_HDR_PROT_ICMP:
+            case IPC_HDR_PROT_ICMPV6:
+                if (_RULES_CONTAIN(p_rules, ICMPV4_TYPE)) {
+                    hw_filter->f_pro_word = p_rules->icmpv4_type;
+                    IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_F_WORD_TYPE);
+                }
+
+                if (_RULES_CONTAIN(p_rules, ICMPV6_TYPE)) {
+                    hw_filter->f_pro_word = p_rules->icmpv6_type;
+                    IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_F_WORD_TYPE);
+                }
+                break;
+            case IPC_HDR_PROT_ESP:
+                if (_RULES_CONTAIN(p_rules, SPI)) {
+                    IPC_NE_SET_4B(&(hw_filter->f_pro_word), p_rules->spi);
+                    IPF_HW_FILTER_SET_VALID(hw_filter->valid, IPF_HW_FILTER_V_F_WORD_TYPE4);
+                }
+                break;
+            default:
+                IPC_ASSERT(KAL_FALSE);
+                break;
+        }
+    }
+
+    /*
+     * a trick for storing filter id in hw table,
+     * then we can quickly get the corresponding filter id when IPF match by match index
+     */
+    hw_filter->resv1 = filter_id;
+
+    return KAL_TRUE;
+}
+
+void ipc_filter_update_hw_filter(void)
+{
+    static ipc_filter_list_t *fls_dl_set[] = {ipc_dl_v4_filter_list_s,
+                                              ipc_dl_v6_filter_list_s};
+    ipv4_filter_rule *hw_filter_base = NULL;
+    ipv4_filter_rule *p_cur_base = NULL;
+    kal_bool result = KAL_FALSE;
+    kal_uint8 fls_set_idx = 0;
+    kal_uint8 fls_set_cnt = sizeof(fls_dl_set) / sizeof(ipc_filter_list_t*);
+    ipc_filter_list_t *filter_list = NULL;
+    ipc_filter_t *filter = NULL;
+    kal_uint8 hw_entry_idx = 0;
+    kal_uint8 filter_num = 0;
+    kal_uint32 total_entry_num = 0;
+    kal_uint8 entry_num_for_each_filter = 0;
+    kal_bool ipv6_unknown_proto_chk = KAL_FALSE;
+
+    result = IPC_TAKE_HW_FILTER_TABLE((void**) &hw_filter_base, &total_entry_num);
+
+    /* result shall be true. */
+    IPC_ASSERT(result);
+    hif_trace_info(IPC_TR_UPDATE_HW_FILTER_TABLE_INFO, hw_filter_base, total_entry_num);
+    kal_mem_set(hw_filter_base, 0, sizeof(ipv4_filter_rule) * total_entry_num);
+
+    for (fls_set_idx = 0; fls_set_idx < fls_set_cnt; fls_set_idx++) {
+        filter_list = fls_dl_set[fls_set_idx];
+
+        if (!filter_list || 0 == filter_list->count) {
+            /* skip the loop */
+            continue;
+        }
+
+        (IPC_IP_TYPE_IPV4 == filter_list->ip_type) ? (entry_num_for_each_filter = 1) : (entry_num_for_each_filter = 2);
+
+        if ((IPC_IP_TYPE_IPV6 == filter_list->ip_type) && (filter_list->count > 0)) {
+            ipv6_unknown_proto_chk = KAL_TRUE;
+        }
+
+        hif_trace_info(IPC_TR_UPDATE_HW_FILTER_COUNT, filter_list->ip_type, filter_list->count);
+
+        for (filter = filter_list->filter_head; filter;
+                filter = filter->next_filter_map[ipc_next_filter_hash(filter_list->ip_type)]) {
+            if (KAL_TRUE == filter->is_bypass_sync_hw) {
+                /* skip deregistered filter */
+                hif_trace_info(IPC_TR_BYPASS_HW_FILTER_SYNC, __FUNCTION__, filter->filter_id);
+                continue;
+            }
+
+            if (hw_entry_idx <= (total_entry_num - entry_num_for_each_filter)) {
+                p_cur_base = &hw_filter_base[hw_entry_idx]; /* 1 entry = 16 Bytes */
+                if (KAL_TRUE == ipc_update_one_hw_filter(filter->filter_id, &filter->rules, (void*) p_cur_base)) {
+                    hw_entry_idx = hw_entry_idx + entry_num_for_each_filter;
+                    filter_num++;
+                }
+            } else {
+                /* exceed HW filter count */
+                hif_trace_info(IPC_TR_UPDATE_HW_FILTER_TOO_MUCH, filter_list->ip_type, filter_num, hw_entry_idx);
+                IPC_ASSERT(KAL_FALSE);
+            }
+        }
+    }
+
+    hif_trace_info(IPC_TR_UPDATE_HW_FILTER_OK, hw_entry_idx, ipv6_unknown_proto_chk);
+    IPC_SUBMIT_HW_FILTER_TABLE(hw_entry_idx, ipv6_unknown_proto_chk);
+}
+
+#endif
+
+static void ipc_filter_update_sit_idx_by_skip_segment(upcm_did *did, kal_uint32 *p_curr_si_idx)
+{
+    kal_bool end_of_seg_list;
+    upcm_did_si *sit;
+    kal_uint32 pkt_start_idx;
+
+    IPC_ASSERT((did) && (p_curr_si_idx));
+    sit = UPCM_DID_GET_SIT_PTR(did);
+    pkt_start_idx = *p_curr_si_idx;
+
+    IPC_ASSERT( pkt_start_idx < UPCM_DID_MAX_SIT_ENT_NUM );
+
+    end_of_seg_list = KAL_FALSE;
+
+    for ( *p_curr_si_idx = pkt_start_idx;
+          *p_curr_si_idx < UPCM_DID_MAX_SIT_ENT_NUM && !end_of_seg_list;
+          (*p_curr_si_idx) ++) {
+        upcm_did_si *curr_si = &sit[*p_curr_si_idx];
+        end_of_seg_list = UPCM_DID_SI_GET_EOL(curr_si);
+    }
+}
+
+void ipc_filter_did_drop_pkt_handler(kal_uint32 pdn_id, upcm_did *p_head, upcm_did *p_tail)
+{
+    upcm_did *did = NULL;
+    upcm_did *next_did = NULL;
+    kal_bool end_of_list = KAL_FALSE;
+    upcm_did_si *curr_si = NULL;
+    kal_uint32 pkt_start_idx = 0;
+    kal_uint8 comm_buff[16] = {0}; /*< max is ipv6 src/dest addr */
+    kal_uint8 *comm_continuous_p = NULL;
+    kal_uint8 seg_num = 0;
+    upcm_did_si *sit = NULL;
+    kal_uint32 curr_idx = 0;
+    kal_uint8 *ip_packet = NULL;
+    kal_uint32 packet_len = 0;
+    qbm_gpd *p_gpd = NULL;
+    ipc_packet_info_t packet_info;
+
+    if(!p_head || !p_tail){
+        hif_trace_info(IPC_TR_DID_DROP_HDR_INVALID_PARAM, __FUNCTION__, p_head, p_tail);
+        return;
+    }
+
+    for (did = p_head; did && !end_of_list; did = next_did) {
+        next_did = UPCM_DID_GET_NEXT(did);
+        end_of_list = (did == p_tail);
+
+        /* operate on each did */
+        IPC_ASSERT(did);
+        seg_num = UPCM_DID_GET_SEG_NUM(did);
+        sit = UPCM_DID_GET_SIT_PTR(did);
+
+        curr_idx = 0;
+        while (curr_idx < seg_num) {
+            curr_si = &sit[curr_idx];
+            IPC_ASSERT(UPCM_DID_SI_GET_LEN(curr_si));
+            pkt_start_idx = curr_idx;
+            ip_packet = (kal_uint8 *)UPCM_DID_SI_GET_DATAPTR(curr_si) + UPCM_DID_SI_GET_OFFSET(curr_si);
+
+            if(KAL_TRUE == ipc_get_continuous_content_did(ip_packet, 0, did, curr_idx, 6, &comm_continuous_p, comm_buff)) {
+                if (IPC_HDR_IS_V4(comm_continuous_p)) {
+                    packet_len = IPC_HDR_V4_GET_TOTAL_LENGTH(comm_continuous_p);
+                } else if (IPC_HDR_IS_V6(comm_continuous_p)) {
+                    packet_len = IPC_HDR_V6_GET_LENGTH(comm_continuous_p) + IPC_HDR_V6_HEADER_SIZE;
+                } else{
+                    /* Invalid IP type, skip this packet */
+                    ipc_filter_update_sit_idx_by_skip_segment(did, &curr_idx);
+                    continue;
+                }
+                kal_mem_set(&packet_info, 0, sizeof(ipc_packet_info_t));
+                if(ipc_get_packet_info_did(ip_packet, did, pkt_start_idx, &packet_info)){
+                    if(IPC_HDR_ICMPV6_TYPE_RA == packet_info.icmpv6_type) {
+                        /*call did ra check*/
+                        ipc_data_ipv6_ra_pool_push(pdn_id, NULL);
+                        packet_len = IPC_HDR_V6_GET_LENGTH(comm_continuous_p) + IPC_HDR_V6_HEADER_SIZE;
+                        ipc_utils_sit_to_gpd(QBM_TYPE_NET_DL, did, curr_idx, packet_len, &p_gpd);
+                        if(p_gpd) {
+                            ipc_data_ipv6_ra_pool_push(pdn_id, p_gpd);
+                            hif_trace_info(IPC_TR_DOWNLINK_RA_PROXY_GPD, __FUNCTION__, pdn_id, p_gpd);
+                        }else{
+                            hif_trace_info(IPC_TR_DROP_HDR_GPD_ALLOC_NG, __FUNCTION__, __LINE__);
+                        }
+                    } else if(IPC_HDR_PROT_TCP == packet_info.protocol){
+                        if( (IPC_HDR_TCP_FLAG_RST != (packet_info.tcp_flags & IPC_HDR_TCP_FLAG_RST)) && (packet_info.tcp_flags) ){
+                            /* Skipped if received [RST] packet */
+                            /* make sure packet content is continuous : copy data to continuous buffer(GPD) */
+                            ipc_utils_sit_to_gpd(QBM_TYPE_NET_DL, did, curr_idx, packet_len, &p_gpd);
+                            if(p_gpd) {
+                                kal_uint8 *p_packet;
+                                if(KAL_TRUE == ipc_utils_get_gpd_dataptr(p_gpd, (void**)&p_packet)){
+                                    ipc_ipf_dhlr_for_tcp_rst(p_packet, packet_info, pdn_id);
+                                }
+                                qbm_free_one(p_gpd);
+                            }else{
+                                hif_trace_info(IPC_TR_DROP_HDR_GPD_ALLOC_NG, __FUNCTION__, __LINE__);
+                            }
+                        }
+                    } else if(IPC_HDR_PROT_UDP == packet_info.protocol) {
+                        /*udp packet is going to drop*/
+                        /*fill data in p_gpd*/
+                        ipc_utils_sit_to_gpd(QBM_TYPE_NET_DL, did, curr_idx, packet_len, &p_gpd);
+                        if(p_gpd) {
+                            kal_uint8 *p_packet;
+                            if(KAL_TRUE == ipc_utils_get_gpd_dataptr(p_gpd, (void**)&p_packet)){
+                                ipc_ipf_dhlr_for_udp_rst(p_packet, pdn_id);
+                            }
+                            qbm_free_one(p_gpd);
+                        }else{
+                            hif_trace_info(IPC_TR_DROP_HDR_GPD_ALLOC_NG, __FUNCTION__, __LINE__);
+                        }
+
+                    } else {
+                        hif_trace_info(IPC_TR_DROP_HDLR_NG_PROTO, __FUNCTION__, packet_info.protocol);
+                    }
+                }else{
+                    hif_trace_info(IPC_TR_DROP_HDLR_PKT_INFO_NG, __FUNCTION__);
+                }
+            }
+            ipc_filter_update_sit_idx_by_skip_segment(did, &curr_idx);
+        }
+    }
+    return;
+}
+
+void ipc_filter_switch_dl_mode(kal_uint8 mode)
+{
+#if defined(__IPF_SUPPORT__)    
+    kal_bool result = KAL_FALSE;
+    ipv4_filter_rule *hw_filter_base = NULL;
+    ipv6_filter_rule *hw_filter_v6 = NULL;
+    ipv4_filter_rule *hw_filter_v4 = NULL;
+    kal_uint32 total_entry_num = 0;
+    kal_uint8 hw_filter_idx = 0;
+    kal_bool ipv6_unknown_proto_chk = KAL_FALSE;
+
+    hif_trace_info(IPC_TR_IPF_DL_MODE_SWITCH, __FUNCTION__, mode, g_ipc_dl_mode);
+    if (mode & IPC_SW_DL_MODE_MAX) {
+        mode = g_ipc_dl_mode & mode;
+    } else {
+        mode = g_ipc_dl_mode | mode;
+    }
+
+    if(mode == g_ipc_dl_mode || ((mode != IPC_HW_DL_MODE) && (g_ipc_dl_mode != IPC_HW_DL_MODE))){
+        /* Update mode to include  */
+        g_ipc_dl_mode = mode;
+        hif_trace_info(IPC_TR_IPF_DL_MODE_SWITCH_NOTHING, __FUNCTION__);
+        return;
+    }
+
+    /* Force SW DL mode */
+    if (IPC_HW_DL_MODE != mode) {
+        result = IPC_TAKE_HW_FILTER_TABLE((void**) &hw_filter_base, &total_entry_num);
+        IPC_ASSERT(result);
+        kal_mem_set(hw_filter_base, 0, sizeof(ipv4_filter_rule) * total_entry_num);
+        
+        /* Set IPv4 rule */
+        hw_filter_v4 = (ipv4_filter_rule*) &hw_filter_base[hw_filter_idx];
+        hw_filter_v4->ip = IPF_HW_FILTER_IPV4;
+        IPF_HW_FILTER_SET_VALID(hw_filter_v4->valid, IPF_HW_FILTER_V_FRAG);
+        hw_filter_idx++;
+        hw_filter_v4->resv1 = IPC_SW_DL_FILTER_ID;
+
+        /* Set IPv6 rule */
+        hw_filter_v6 = (ipv6_filter_rule*) &hw_filter_base[hw_filter_idx];
+        hw_filter_v6->ip = IPF_HW_FILTER_IPV6;
+        hw_filter_v6->ip1 = IPF_HW_FILTER_IPV6_1;
+        IPF_HW_FILTER_SET_VALID(hw_filter_v6->valid, IPF_HW_FILTER_V_FRAG);
+        hw_filter_idx += 2;
+        hw_filter_v6->resv1 = IPC_SW_DL_FILTER_ID;
+
+        ipv6_unknown_proto_chk = KAL_TRUE;
+        hif_trace_info(IPC_TR_UPDATE_HW_FILTER_OK, hw_filter_idx, ipv6_unknown_proto_chk);
+        IPC_SUBMIT_HW_FILTER_TABLE(hw_filter_idx, ipv6_unknown_proto_chk);
+
+        g_ipc_dl_mode = mode;
+    } else {
+        /* restore HW filter */
+        ipc_filter_chk_sw_path();
+        g_ipc_dl_mode = IPC_HW_DL_MODE;
+    }
+#endif
+    return;
+}
+
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment.h b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment.h
new file mode 100644
index 0000000..d977c34
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment.h
@@ -0,0 +1,38 @@
+#ifndef _IPC_FRAGMENT_INC
+#define _IPC_FRAGMENT_INC
+
+#include "ipc_api.h"
+#include "ipc_fragment_def.h"
+#include "kal_public_api.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+#include "hif_mw_msgid.h"
+
+#define HIF_DATA_TRACE_ENABLED 1
+#define HIF_CONSOLE_TRACE_ENABLED 0
+
+#include "TrcMod.h"
+#include "hif_trace.h"
+#include "ipc_utils.h"
+
+#define IPC_FRAGMENT_DL_PKT_DUMP(buf_p, len) ipc_utils_pkt_dump_buf(MSG_ID_IPC_FRAG_DL_RAW_DATA, MOD_IPC_FRAGMENT, (unsigned char*)buf_p, len)
+#define IPC_FRAGMENT_UL_PKT_DUMP(buf_p, len) ipc_utils_pkt_dump_buf(MSG_ID_IPC_FRAG_UL_RAW_DATA, MOD_IPC_FRAGMENT, (unsigned char*)buf_p, len)
+
+#define IPC_FRAG_INVALID_FILTER_ID -1
+#define IPC_FRAG_IPV6_MAX_LEN 65535
+#define IPC_FRAG_FLAG_MF 0x01
+#define IPC_FRAG_INFO_RECEIVE_FIRST_PKT 0x1
+#define IPC_FRAG_INFO_RECEIVE_LAST_PKT 0x2
+#define IPC_FRAG_INFO_RECEIVE_COMPLETE 0x4
+#define IPC_FRAG_INFO_RECEIVE_DROPPED 0x8
+
+void ipc_fragment_mp_init();
+void ipc_fragment_mp_deinit();
+
+void ipc_fragment_queuing_expire_init();
+void ipc_fragment_queuing_expire_deinit();
+
+void ipc_fragment_queuing_v4(qbm_gpd *new_gpd, ipc_packet_info_t *packet_info, kal_uint32 matched_filter_id, ipc_frag_refilter_info_t *refilter_info);
+void ipc_fragment_queuing_v6(qbm_gpd *new_gpd, ipc_packet_info_t *packet_info, kal_uint32 matched_filter_id, ipc_frag_refilter_info_t *refilter_info);
+
+#endif /* _IPC_FRAGMENT_INC */
\ No newline at end of file
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_data_path_trace_utmd.json b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_data_path_trace_utmd.json
new file mode 100644
index 0000000..e97db50
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_data_path_trace_utmd.json
@@ -0,0 +1,172 @@
+{
+  "legacyParameters": {
+    "codeSection": "TCMFORCE", 
+    "l2BufferSetting": "L2_BUFFER_HIF", 
+    "l2MaxArg": 7, 
+    "modemType": "Generic"
+  }, 
+  "module": "IPC_FRAGMENT_L2", 
+  "stringTranslationDefs": [], 
+  "startGen": "Legacy",
+  "endGen": "-",
+  "traceClassDefs": [
+    {
+      "IPC_FRAG_UH": {
+        "debugLevel": "Ultra-High",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "IPC_FRAG_H": {
+        "debugLevel": "High",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "IPC_FRAG_M": {
+        "debugLevel": "Medium",
+        "filterDefaultValue": "ON",
+        "tag": [
+          "Baseline"
+        ],
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "IPC_FRAG_L": {
+        "debugLevel": "Low",
+        "filterDefaultValue": "ON",
+        "tag": [
+         "Baseline"
+        ],
+        "traceType": "CoreDesign"
+      }
+    }
+  ],
+  "traceDefs": [
+    {
+      "IPC_FRAG_QUE_V4_KEY_INFO": {
+        "format": "[IPC_FRAG] ipc_fragment_queuing_v4(): src = %xl, dst = %xl, ip_id = %xl, protocol = %d", 
+        "traceClass": "IPC_FRAG_L"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_V6_KEY_INFO_SRC": {
+        "format": "[IPC_FRAG] ipc_fragment_queuing_v6(): src = %xl %xl %xl %xl", 
+        "traceClass": "IPC_FRAG_L"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_V6_KEY_INFO_DST": {
+        "format": "[IPC_FRAG] dst = %xl %xl %xl %xl", 
+        "traceClass": "IPC_FRAG_L"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_V6_KEY_INFO_ID": {
+        "format": "[IPC_FRAG] ip_id = %xl", 
+        "traceClass": "IPC_FRAG_M"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_FRAG_INFO": {
+        "format": "[IPC_FRAG] frag_offset = %xd, frag_len = %xd, frag_flag = %xd, frag_end = %xd", 
+        "traceClass": "IPC_FRAG_M"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_GRP_INFO": {
+        "format": "[IPC_FRAG] info_mask = %xd, accumulate_len = %xl, total_len = %xl, head_gpd = %xl", 
+        "traceClass": "IPC_FRAG_M"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_FIND_POS": {
+        "format": "[IPC_FRAG] Find position in v4 queuing: priv_gpd = %xl, priv_meta = %xl, next_gpd = %xl, next_meta = %xl", 
+        "traceClass": "IPC_FRAG_M"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_OVERLAP_PRIV": {
+        "format": "[IPC_FRAG] Overlap with priv fragment: priv_offset = %xd, priv_len = %xd, shrink_len = %xd", 
+        "traceClass": "IPC_FRAG_L"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_OVERLAP_NXT": {
+        "format": "[IPC_FRAG] Overlap with next fragment: next_offset = %xd, next_len = %xd, shrink_len = %xd", 
+        "traceClass": "IPC_FRAG_L"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_INSERT": {
+        "format": "[IPC_FRAG] Insert new fragment into list: new_offset = %xd, new_len = %xd, accumulate_len = %xd, offset(new) = %xl", 
+        "traceClass": "IPC_FRAG_M"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_ERR": {
+        "format": "[IPC_FRAG] Queuing error: release gpd = %xl, meta = %xl", 
+        "traceClass": "IPC_FRAG_UH"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_FIRST_FRAG": {
+        "format": "[IPC_FRAG] First fragment is received!! filter_id = %xl", 
+        "traceClass": "IPC_FRAG_H"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_LAST_FRAG": {
+        "format": "[IPC_FRAG] Last fragment is received!!", 
+        "traceClass": "IPC_FRAG_H"
+      }
+    }, 
+    {
+      "IPC_FRAG_QUE_COMPLETE": {
+        "format": "[IPC_FRAG] Queuing completing!! ba~ba~la~la~la~la~", 
+        "traceClass": "IPC_FRAG_H"
+      }
+    }, 
+    {
+      "IPC_FRAG_RECYCLE_NO_SPACE": {
+        "format": "[IPC_FRAG] Queuing recycle when space is not enough: is_v4 = %ub, ip_id = %xl", 
+        "traceClass": "IPC_FRAG_H"
+      }
+    }, 
+    {
+      "IPC_FRAG_RECYCLE": {
+        "format": "[IPC_FRAG] Queuing recycle: is_v4 = %ub, ip_id = %xl", 
+        "traceClass": "IPC_FRAG_H"
+      }
+    }, 
+    {
+      "IPC_FRAG_FRAG_START": {
+        "format": "[IPC_FRAG] ipc_fragment_frag start: is_v4 = %ub, buffer_addr = %xl, buffer_len = %ud, ip_id = %xl", 
+        "traceClass": "IPC_FRAG_M"
+      }
+    }, 
+    {
+      "IPC_FRAG_FRAG_END": {
+        "format": "[IPC_FRAG] ipc_fragment_frag end: frag_gpd_num = %ud, frag_gpd_head = %ul, frag_gpd_tail = %ul", 
+        "traceClass": "IPC_FRAG_M"
+      }
+    }, 
+    {
+      "IPC_FRAG_REASM": {
+        "format": "[IPC_FRAG] ipc_fragment_reassemble: is_v4 = %ub, reasm_gpd = %ul", 
+        "traceClass": "IPC_FRAG_H"
+      }
+    }
+  ], 
+  "traceFamily": "L2",
+  "userModule": "MOD_IPC_FRAGMENT"
+}
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_defrag.c b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_defrag.c
new file mode 100644
index 0000000..cdffa4f
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_defrag.c
@@ -0,0 +1,1057 @@
+#include "ipc_fragment.h"
+#include "ipc_fragment_struct.h"
+#include "ipc_fragment_utility.h"
+
+// Todo: reasm is disabled by default, we are waiting for the implementation of IPCORE filter
+// Users can set the on/off of reasm of a IPCORE filter, and ipc_fragment will do reassemble if the reasm is on in IPCORE filter
+#define IPC_FRAGMENT_DEFRAG_REASM_EN KAL_FALSE
+#define IPCF_CHK_TO(_k, _e, _c) ((_e > _k && _c > _e) || (_e > _k && _k >= _c) || (_c > _e && _k >= _c) ? KAL_TRUE : KAL_FALSE)
+#define IPCF_Q_EXP_NXTP(_i) ((_i + 1) % IPC_FRAG_EXPIRE_CB_NUM)
+
+kal_bool ipc_fragment_defrag_reasm_en = IPC_FRAGMENT_DEFRAG_REASM_EN;
+
+static IpcFragIpv4L3KeyWithTStamp ipc_q_exp_buff_v4[IPC_FRAG_EXPIRE_CB_NUM];
+static IpcFragIpv6L3KeyWithTStamp ipc_q_exp_buff_v6[IPC_FRAG_EXPIRE_CB_NUM];
+static kal_uint32 ipc_q_exp_pw_v4 = 0, ipc_q_exp_pr_v4 = 0, ipc_q_exp_pw_v6 = 0, ipc_q_exp_pr_v6 = 0;
+static IpcFragUM4 ipc_ipv4_mp;
+static IpcFragUM6 ipc_ipv6_mp;
+
+void ipc_fragment_mp_clear(kal_bool is_v4)
+{
+    IpcFragMnd4 *curr_node4 = NULL;
+    IpcFragMnd6 *curr_node6 = NULL;
+    kal_uint32 index;
+
+    if (is_v4 == KAL_TRUE)
+    {
+        for (index = 0; index < ipc_ipv4_mp.mp_num; ++index)
+        {
+            curr_node4 = ipc_ipv4_mp.mp[index];
+
+            while (curr_node4)
+            {
+                ipc_ipv4_mp.mp[index] = curr_node4->next;
+                ipc_fragment_pktg_rel_gpd_list(&(curr_node4->val));
+                ipc_fragment_pktg_rel_meta_list(&(curr_node4->val));
+                ipc_fragment_mem_free(curr_node4);
+                curr_node4 = ipc_ipv4_mp.mp[index];
+            }
+        }
+    }
+    else
+    {
+        for (index = 0; index < ipc_ipv6_mp.mp_num; ++index)
+        {
+            curr_node6 = ipc_ipv6_mp.mp[index];
+
+            while (curr_node6)
+            {
+                ipc_ipv6_mp.mp[index] = curr_node6->next;
+                ipc_fragment_pktg_rel_gpd_list(&(curr_node6->val));
+                ipc_fragment_pktg_rel_meta_list(&(curr_node6->val));
+                ipc_fragment_mem_free(curr_node6);
+                curr_node6 = ipc_ipv6_mp.mp[index];
+            }
+        }
+    }
+}
+
+void ipc_fragment_mp_erase(void *pk, kal_bool is_v4)
+{
+    IpcFragMnd4 *curr_node4 = NULL, *priv_node4 = NULL;
+    IpcFragMnd6 *curr_node6 = NULL, *priv_node6 = NULL;
+    kal_uint32 index;
+
+    if (is_v4 == KAL_TRUE)
+    {
+        index = ipc_fragment_mf(pk, sizeof(IpcFragIpv4L3Key)) % ipc_ipv4_mp.mp_num;
+        curr_node4 = ipc_ipv4_mp.mp[index];
+        while (curr_node4 && KAL_FALSE == ipc_fragment_ipv4_l3eq((IpcFragIpv4L3Key *)pk, &(curr_node4->key)))
+        {
+            priv_node4 = curr_node4;
+            curr_node4 = curr_node4->next;
+        }
+
+        if (curr_node4)
+        {
+            if (!priv_node4)
+            {
+                ipc_ipv4_mp.mp[index] = curr_node4->next;
+            }
+            else
+            {
+                priv_node4->next = curr_node4->next;
+            }
+            ipc_fragment_pktg_rel_gpd_list(&(curr_node4->val));
+            ipc_fragment_pktg_rel_meta_list(&(curr_node4->val));
+            ipc_fragment_mem_free(curr_node4);
+        }
+    }
+    else
+    {
+        index = ipc_fragment_mf(pk, sizeof(IpcFragIpv6L3Key)) % ipc_ipv6_mp.mp_num;
+        curr_node6 = ipc_ipv6_mp.mp[index];
+        while (curr_node6 && KAL_FALSE == ipc_fragment_ipv6_l3eq((IpcFragIpv6L3Key *)pk, &(curr_node6->key)))
+        {
+            priv_node6 = curr_node6;
+            curr_node6 = curr_node6->next;
+        }
+
+        if (curr_node6)
+        {
+            if (!priv_node6)
+            {
+                ipc_ipv6_mp.mp[index] = curr_node6->next;
+            }
+            else
+            {
+                priv_node6->next = curr_node6->next;
+            }
+            ipc_fragment_pktg_rel_gpd_list(&(curr_node6->val));
+            ipc_fragment_pktg_rel_meta_list(&(curr_node6->val));
+            ipc_fragment_mem_free(curr_node6);
+        }
+    }
+}
+
+void *ipc_fragment_mp_getMN(void *pk, kal_bool is_v4)
+{
+    IpcFragMnd4 *curr_node4 = NULL;
+    IpcFragMnd6 *curr_node6 = NULL;
+    kal_uint32 index;
+
+    if (is_v4 == KAL_TRUE)
+    {
+        index = ipc_fragment_mf(pk, sizeof(IpcFragIpv4L3Key)) % ipc_ipv4_mp.mp_num;
+        curr_node4 = ipc_ipv4_mp.mp[index];
+        while (curr_node4 && KAL_FALSE == ipc_fragment_ipv4_l3eq((IpcFragIpv4L3Key *)pk, &(curr_node4->key)))
+        {
+            curr_node4 = curr_node4->next;
+        }
+        return curr_node4;
+    }
+    else
+    {
+        index = ipc_fragment_mf(pk, sizeof(IpcFragIpv6L3Key)) % ipc_ipv6_mp.mp_num;
+        curr_node6 = ipc_ipv6_mp.mp[index];
+        while (curr_node6 && KAL_FALSE == ipc_fragment_ipv6_l3eq((IpcFragIpv6L3Key *)pk, &(curr_node6->key)))
+        {
+            curr_node6 = curr_node6->next;
+        }
+        return curr_node6;
+    }
+}
+
+IpcFragPktGroupInfo *ipc_fragment_mp_addMN(void *pk, kal_bool is_v4)
+{
+    IpcFragMnd4 *curr_node4 = NULL;
+    IpcFragMnd6 *curr_node6 = NULL;
+    kal_uint32 index;
+
+    if (is_v4 == KAL_TRUE)
+    {
+        index = ipc_fragment_mf(pk, sizeof(IpcFragIpv4L3Key)) % ipc_ipv4_mp.mp_num;
+        curr_node4 = ipc_ipv4_mp.mp[index];
+        while (curr_node4 && KAL_FALSE == ipc_fragment_ipv4_l3eq((IpcFragIpv4L3Key *)pk, &(curr_node4->key)))
+        {
+            curr_node4 = curr_node4->next;
+        }
+        if (!curr_node4)
+        {
+            curr_node4 = (IpcFragMnd4 *)ipc_fragment_mem_alloc(sizeof(IpcFragMnd4));
+            ASSERT(curr_node4);
+            ipc_fragment_pktg_init(&(curr_node4->val));
+            curr_node4->key = *((IpcFragIpv4L3Key *)pk);
+            curr_node4->next = ipc_ipv4_mp.mp[index];
+            ipc_ipv4_mp.mp[index] = curr_node4;
+        }
+
+        return &(curr_node4->val);
+    }
+    else
+    {
+        index = ipc_fragment_mf(pk, sizeof(IpcFragIpv6L3Key)) % ipc_ipv6_mp.mp_num;
+        curr_node6 = ipc_ipv6_mp.mp[index];
+        while (curr_node6 && KAL_FALSE == ipc_fragment_ipv6_l3eq((IpcFragIpv6L3Key *)pk, &(curr_node6->key)))
+        {
+            curr_node6 = curr_node6->next;
+        }
+        if (!curr_node6)
+        {
+            curr_node6 = (IpcFragMnd6 *)ipc_fragment_mem_alloc(sizeof(IpcFragMnd6));
+            ASSERT(curr_node6);
+            ipc_fragment_pktg_init(&(curr_node6->val));
+            curr_node6->key = *((IpcFragIpv6L3Key *)pk);
+            curr_node6->next = ipc_ipv6_mp.mp[index];
+            ipc_ipv6_mp.mp[index] = curr_node6;
+        }
+
+        return &(curr_node6->val);
+    }
+}
+
+void ipc_fragment_queuing_recycle(kal_bool is_v4)
+{
+    IpcFragPktGroupInfo *pkt_grp_info;
+
+    if (is_v4)
+    {
+        IpcFragIpv4L3Key v4_key = ipc_q_exp_buff_v4[ipc_q_exp_pr_v4].v4_key;
+        ipc_q_exp_pr_v4 = IPCF_Q_EXP_NXTP(ipc_q_exp_pr_v4);
+
+        if (ipc_fragment_mp_getMN(&v4_key, KAL_TRUE))
+        {
+            pkt_grp_info = ipc_fragment_mp_addMN(&v4_key, KAL_TRUE);
+
+            hif_data_trace(MD_TRC_IPC_FRAG_RECYCLE, 1, v4_key.ip_id);
+
+            if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_COMPLETE) == 0)
+            {
+                if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_FIRST_PKT) != 0)
+                {
+                    ipc_fragment_icmp4_send(IPC_ICMP4_TYPE_TIME_EXCEEDED, IPC_ICMP4_CODE_FRAG_REASM_TIME_EXCEEDED, pkt_grp_info->head_gpd);
+                }
+                ipc_frag_send_pkt(IPC_IP_TYPE_IPV4, &(pkt_grp_info->first_packet_refilter_info), pkt_grp_info->head_gpd, pkt_grp_info->tail_gpd);
+                pkt_grp_info->head_gpd = pkt_grp_info->tail_gpd = NULL;
+            }
+            ipc_fragment_mp_erase(&v4_key, KAL_TRUE);
+        }
+    }
+    else
+    {
+        IpcFragIpv6L3Key v6_key = ipc_q_exp_buff_v6[ipc_q_exp_pr_v6].v6_key;
+        ipc_q_exp_pr_v6 = IPCF_Q_EXP_NXTP(ipc_q_exp_pr_v6);
+
+        if (ipc_fragment_mp_getMN(&v6_key, KAL_FALSE))
+        {
+            pkt_grp_info = ipc_fragment_mp_addMN(&v6_key, KAL_FALSE);
+
+            hif_data_trace(MD_TRC_IPC_FRAG_RECYCLE, 0, v6_key.ip_id);
+
+            if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_COMPLETE) == 0)
+            {
+                if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_FIRST_PKT) != 0)
+                {
+                    ipc_fragment_icmp6_send(IPC_ICMP6_TYPE_TIME_EXCEEDED, IPC_ICMP6_CODE_FRAG_REASM_TIME_EXCEEDED, pkt_grp_info->head_gpd);
+                }
+                ipc_frag_send_pkt(IPC_IP_TYPE_IPV6, &(pkt_grp_info->first_packet_refilter_info), pkt_grp_info->head_gpd, pkt_grp_info->tail_gpd);
+                pkt_grp_info->head_gpd = pkt_grp_info->tail_gpd = NULL;
+            }
+            ipc_fragment_mp_erase(&v6_key, KAL_FALSE);
+        }
+    }
+}
+
+kal_bool ipc_fragment_queuing_recycle_meta_in_insufficient_space(kal_bool is_v4)
+{
+    kal_bool result = KAL_FALSE;
+    IpcFragIpv4L3Key v4_key;
+    IpcFragIpv6L3Key v6_key;
+    IpcFragPktGroupInfo *pkt_grp_info;
+    kal_uint32 pr = 0;
+
+    if (is_v4 && ipc_q_exp_pw_v4 != ipc_q_exp_pr_v4)
+    {
+        pr = ipc_q_exp_pr_v4;
+        while (pr != ipc_q_exp_pw_v4 && result == KAL_FALSE)
+        {
+            v4_key = ipc_q_exp_buff_v4[pr].v4_key;
+            if (ipc_fragment_mp_getMN(&v4_key, KAL_TRUE))
+            {
+                pkt_grp_info = ipc_fragment_mp_addMN(&v4_key, KAL_TRUE);
+                if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_COMPLETE) == 0 && (pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_DROPPED) == 0)
+                {
+                    hif_data_trace(MD_TRC_IPC_FRAG_RECYCLE_NO_SPACE, 1, v4_key.ip_id);
+                    pkt_grp_info->info_mask |= IPC_FRAG_INFO_RECEIVE_DROPPED;
+                    ipc_fragment_pktg_rel_meta_list(pkt_grp_info);
+                    result = KAL_TRUE;
+                }
+            }
+            pr = IPCF_Q_EXP_NXTP(pr);
+        }
+    }
+    else if (!is_v4 && ipc_q_exp_pw_v6 != ipc_q_exp_pr_v6)
+    {
+        pr = ipc_q_exp_pr_v6;
+        while (pr != ipc_q_exp_pw_v6 && result == KAL_FALSE)
+        {
+            v6_key = ipc_q_exp_buff_v6[pr].v6_key;
+            if (ipc_fragment_mp_getMN(&v6_key, KAL_FALSE))
+            {
+                pkt_grp_info = ipc_fragment_mp_addMN(&v6_key, KAL_FALSE);
+                if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_COMPLETE) == 0 && (pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_DROPPED) == 0)
+                {
+                    hif_data_trace(MD_TRC_IPC_FRAG_RECYCLE_NO_SPACE, 0, v6_key.ip_id);
+                    pkt_grp_info->info_mask |= IPC_FRAG_INFO_RECEIVE_DROPPED;
+                    ipc_fragment_pktg_rel_meta_list(pkt_grp_info);
+                    result = KAL_TRUE;
+                }
+            }
+            pr = IPCF_Q_EXP_NXTP(pr);
+        }
+    }
+
+    return result;
+}
+
+void ipc_fragment_queueing_timeout(void *parm);
+
+void ipc_fragment_queuing_set_expire_timer()
+{
+    ipc_fragment_t *p = ipc_fragment_get_inst();
+
+    if (p->ipc_frag_queue_expire_es && !p->ipc_frag_queue_expire_evt)
+    {
+        p->ipc_frag_queue_expire_evt = evshed_set_event(p->ipc_frag_queue_expire_es,
+                                                        ipc_fragment_queueing_timeout, // timeout handler
+                                                        NULL,                          // event_hf_param
+                                                        IPC_FRAG_POLLING_EXPIRE_SEC);
+
+        ASSERT(p->ipc_frag_queue_expire_evt);
+    }
+}
+
+void ipc_fragment_queueing_timeout(void *parm)
+{
+    kal_uint32 curr_tick = 0, end_tick = 0, key_tick = 0;
+    kal_bool is_timeout = KAL_TRUE;
+    ipc_fragment_t *p = ipc_fragment_get_inst();
+
+    p->ipc_frag_queue_expire_evt = NULL;
+    curr_tick = kal_get_systicks();
+
+    is_timeout = KAL_TRUE;
+    while (ipc_q_exp_pw_v4 != ipc_q_exp_pr_v4 && is_timeout == KAL_TRUE)
+    {
+        key_tick = ipc_q_exp_buff_v4[ipc_q_exp_pr_v4].tickStamp;
+        end_tick = key_tick + IPC_FRAG_QUEUING_EXPIRE_SEC;
+
+        is_timeout = IPCF_CHK_TO(key_tick, end_tick, curr_tick);
+        if (is_timeout == KAL_TRUE)
+        {
+            ipc_fragment_queuing_recycle(KAL_TRUE);
+        }
+    }
+
+    is_timeout = KAL_TRUE;
+    while (ipc_q_exp_pw_v6 != ipc_q_exp_pr_v6 && is_timeout == KAL_TRUE)
+    {
+        key_tick = ipc_q_exp_buff_v6[ipc_q_exp_pr_v6].tickStamp;
+        end_tick = key_tick + IPC_FRAG_QUEUING_EXPIRE_SEC;
+
+        is_timeout = IPCF_CHK_TO(key_tick, end_tick, curr_tick);
+        if (is_timeout == KAL_TRUE)
+        {
+            ipc_fragment_queuing_recycle(KAL_FALSE);
+        }
+    }
+
+    if (ipc_q_exp_pw_v4 != ipc_q_exp_pr_v4 || ipc_q_exp_pw_v6 != ipc_q_exp_pr_v6)
+    {
+        ipc_fragment_queuing_set_expire_timer();
+    }
+}
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+void ipc_fragment_mp_init()
+{
+    kal_uint32 i;
+
+    kal_mem_set(&ipc_ipv4_mp, 0, sizeof(ipc_ipv4_mp));
+    ipc_ipv4_mp.mp_num = IPC_FRAG_HASH_TABLE_BUCK_NUM;
+    ipc_ipv4_mp.mp = (IpcFragMnd4 **)ipc_fragment_mem_alloc(sizeof(IpcFragMnd4 *) * IPC_FRAG_HASH_TABLE_BUCK_NUM);
+    ASSERT(ipc_ipv4_mp.mp);
+    for (i = 0; i < IPC_FRAG_HASH_TABLE_BUCK_NUM; ++i)
+    {
+        ipc_ipv4_mp.mp[i] = NULL;
+    }
+
+    kal_mem_set(&ipc_ipv6_mp, 0, sizeof(ipc_ipv6_mp));
+    ipc_ipv6_mp.mp_num = IPC_FRAG_HASH_TABLE_BUCK_NUM;
+    ipc_ipv6_mp.mp = (IpcFragMnd6 **)ipc_fragment_mem_alloc(sizeof(IpcFragMnd6 *) * IPC_FRAG_HASH_TABLE_BUCK_NUM);
+    ASSERT(ipc_ipv6_mp.mp);
+    for (i = 0; i < IPC_FRAG_HASH_TABLE_BUCK_NUM; ++i)
+    {
+        ipc_ipv6_mp.mp[i] = NULL;
+    }
+}
+
+void ipc_fragment_mp_deinit()
+{
+    kal_uint32 index;
+    IpcFragMnd4 *curr_node4 = NULL;
+    IpcFragMnd6 *curr_node6 = NULL;
+
+    if (ipc_ipv4_mp.mp && (ipc_ipv4_mp.mp_num > 0))
+    {
+        for (index = 0; index < ipc_ipv4_mp.mp_num; ++index)
+        {
+            curr_node4 = ipc_ipv4_mp.mp[index];
+            while (curr_node4)
+            {
+                ipc_ipv4_mp.mp[index] = curr_node4->next;
+                ipc_fragment_pktg_rel_gpd_list(&(curr_node4->val));
+                ipc_fragment_pktg_rel_meta_list(&(curr_node4->val));
+                ipc_fragment_mem_free(curr_node4);
+                curr_node4 = ipc_ipv4_mp.mp[index];
+            }
+        }
+        ipc_fragment_mem_free(ipc_ipv4_mp.mp);
+    }
+    kal_mem_set(&ipc_ipv4_mp, 0, sizeof(ipc_ipv4_mp));
+
+    if (ipc_ipv6_mp.mp && (ipc_ipv6_mp.mp_num > 0))
+    {
+        for (index = 0; index < ipc_ipv6_mp.mp_num; ++index)
+        {
+            curr_node6 = ipc_ipv6_mp.mp[index];
+            while (curr_node6)
+            {
+                ipc_ipv6_mp.mp[index] = curr_node6->next;
+                ipc_fragment_pktg_rel_gpd_list(&(curr_node6->val));
+                ipc_fragment_pktg_rel_meta_list(&(curr_node6->val));
+                ipc_fragment_mem_free(curr_node6);
+                curr_node6 = ipc_ipv6_mp.mp[index];
+            }
+        }
+        ipc_fragment_mem_free(ipc_ipv6_mp.mp);
+    }
+    kal_mem_set(&ipc_ipv6_mp, 0, sizeof(ipc_ipv6_mp));
+}
+
+void ipc_fragment_queuing_expire_init()
+{
+    char ipc_fragment_es[] = {'I', 'P', 'C', '_', 'F', 'R', 'A', 'G', '_', 'E', 'S', '\0'};
+    ipc_fragment_t *p = ipc_fragment_get_inst();
+
+    if (ipc_q_exp_pw_v4 != ipc_q_exp_pr_v4 || ipc_q_exp_pw_v6 != ipc_q_exp_pr_v6)
+    {
+        ASSERT(0);
+    }
+
+    p->ipc_frag_queue_expire_evt = NULL;
+    p->ipc_frag_queue_expire_es = evshed_create(ipc_fragment_es,  /* timer_name: event scheduler name */
+                                                MOD_IPC_FRAGMENT, /* dest_mod_id: system sends timeout message to this module when event scheduler timeout happens */
+                                                0,                /* fuzz */
+                                                0);               /* max_delay_ticks */
+
+    if (p->ipc_frag_queue_expire_es)
+    {
+        evshed_set_index(p->ipc_frag_queue_expire_es, IPC_FRAG_ES_IDX_QUEUE_EXPIRE);
+    }
+    else
+    {
+        ASSERT(0);
+    }
+}
+
+void ipc_fragment_queuing_expire_deinit()
+{
+    ipc_fragment_t *p = ipc_fragment_get_inst();
+
+    evshed_delete_all_events(p->ipc_frag_queue_expire_es);
+    p->ipc_frag_queue_expire_evt = NULL;
+    ipc_q_exp_pr_v4 = ipc_q_exp_pw_v4;
+    ipc_q_exp_pr_v6 = ipc_q_exp_pw_v6;
+}
+
+void ipc_fragment_queuing_v4(qbm_gpd *new_gpd, ipc_packet_info_t *packet_info, kal_uint32 matched_filter_id, ipc_frag_refilter_info_t *refilter_info)
+{
+    IpcFragPktGroupInfo *pkt_grp_info;
+    IpcFragPktMetaInfo *new_meta = NULL, *next_meta, *priv_meta, *free_meta;
+    qbm_gpd *next_gpd, *priv_gpd, *free_gpd, *reasm_gpd;
+    IpcFragIpv4L3Key v4_key;
+    kal_uint8 frag_flag;
+    kal_uint32 frag_offset, frag_end;
+    kal_int32 shrink_len;
+    IpcFragIpv4L3KeyWithTStamp key_with_time;
+    kal_bool need_insert_cb = KAL_FALSE;
+    void *buff;
+    kal_uint16 buff_len;
+
+    if (!new_gpd || !packet_info || !refilter_info)
+    {
+        goto ipc_frag_v4_queue_err;
+    }
+
+    v4_key.src_addr = packet_info->src_addr[0];
+    v4_key.dst_addr = packet_info->dst_addr[0];
+    v4_key.ip_id = packet_info->ip_id;
+    v4_key.protocol = packet_info->protocol;
+    v4_key.reserved = 0;
+    if (ipc_fragment_mp_getMN(&v4_key, KAL_TRUE))
+    {
+        pkt_grp_info = ipc_fragment_mp_addMN(&v4_key, KAL_TRUE);
+    }
+    else
+    {
+        pkt_grp_info = ipc_fragment_mp_addMN(&v4_key, KAL_TRUE);
+        ipc_fragment_pktg_init(pkt_grp_info);
+    }
+
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_V4_KEY_INFO, v4_key.src_addr, v4_key.dst_addr, v4_key.ip_id, v4_key.protocol);
+
+    if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_COMPLETE) || (pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_DROPPED))
+    {
+        goto ipc_frag_v4_queue_err;
+    }
+
+    new_meta = (IpcFragPktMetaInfo *)ipc_fragment_mem_alloc(sizeof(IpcFragPktMetaInfo));
+    if (!new_meta)
+    {
+        if (ipc_fragment_queuing_recycle_meta_in_insufficient_space(KAL_TRUE) || ipc_fragment_queuing_recycle_meta_in_insufficient_space(KAL_FALSE))
+        {
+            new_meta = (IpcFragPktMetaInfo *)ipc_fragment_mem_alloc(sizeof(IpcFragPktMetaInfo));
+        }
+        else
+        {
+            ASSERT(0);
+        }
+
+        if (pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_DROPPED)
+        {
+            goto ipc_frag_v4_queue_err;
+        }
+    }
+    frag_offset = new_meta->offset = new_meta->orig_offset = packet_info->frag_payload_offset;
+    new_meta->pkt_len = new_meta->orig_pkt_len = packet_info->frag_payload_len;
+    new_meta->gpd_payload_offset = packet_info->frag_buffer_payload_offset;
+    frag_end = new_meta->offset + new_meta->pkt_len;
+    frag_flag = packet_info->frag_flag;
+
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_FRAG_INFO, frag_offset, new_meta->pkt_len, frag_flag, frag_end);
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_GRP_INFO, pkt_grp_info->info_mask, pkt_grp_info->accumulate_len, pkt_grp_info->total_len, pkt_grp_info->head_gpd);
+
+    // Dump the GPD packet in ELT, assume the input GPD must be followed with one BD
+    buff_len = QBM_DES_GET_DATALEN(new_gpd);
+    buff = QBM_DES_GET_DATAPTR(QBM_DES_GET_DATAPTR(new_gpd));
+    IPC_FRAGMENT_DL_PKT_DUMP(buff, buff_len);
+
+    if (pkt_grp_info->head_gpd == NULL)
+    {
+        memcpy(&(pkt_grp_info->first_packet_refilter_info), refilter_info, sizeof(ipc_frag_refilter_info_t));
+        need_insert_cb = KAL_TRUE;
+    }
+
+    if ((frag_flag & IPC_FRAG_FLAG_MF) == 0)
+    {
+        if ((frag_end < pkt_grp_info->accumulate_len) || ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_LAST_PKT) && (frag_end != pkt_grp_info->total_len)))
+        {
+            goto ipc_frag_v4_queue_err;
+        }
+
+        pkt_grp_info->info_mask |= IPC_FRAG_INFO_RECEIVE_LAST_PKT;
+        pkt_grp_info->total_len = frag_end;
+
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_LAST_FRAG);
+    }
+    else
+    {
+        if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_LAST_PKT) && (frag_end > pkt_grp_info->total_len))
+        {
+            goto ipc_frag_v4_queue_err;
+        }
+    }
+
+    if (new_meta->pkt_len == 0)
+    {
+        goto ipc_frag_v4_queue_err;
+    }
+
+    priv_meta = pkt_grp_info->tail_meta;
+    priv_gpd = pkt_grp_info->tail_gpd;
+    if (!priv_gpd || priv_meta->offset < frag_offset)
+    {
+        next_gpd = NULL;
+        next_meta = NULL;
+    }
+    else
+    {
+        priv_meta = NULL;
+        priv_gpd = NULL;
+        next_gpd = pkt_grp_info->head_gpd;
+        next_meta = pkt_grp_info->head_meta;
+
+        while (next_gpd)
+        {
+            if (next_meta->offset >= frag_offset)
+            {
+                break;
+            }
+            else
+            {
+                priv_gpd = next_gpd;
+                priv_meta = next_meta;
+                next_gpd = QBM_DES_GET_NEXT(next_gpd);
+                next_meta = next_meta->next;
+            }
+        }
+    }
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_FIND_POS, priv_gpd, priv_meta, next_gpd, next_meta);
+
+    if (priv_gpd)
+    {
+        shrink_len = (kal_int32)priv_meta->offset + priv_meta->pkt_len - frag_offset;
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_OVERLAP_PRIV, priv_meta->offset, priv_meta->pkt_len, shrink_len);
+
+        if (shrink_len > 0)
+        {
+            frag_offset += shrink_len;
+            if (frag_offset < frag_end)
+            {
+                new_meta->offset = frag_offset;
+                new_meta->pkt_len -= shrink_len;
+            }
+            else
+            {
+                goto ipc_frag_v4_queue_err;
+            }
+        }
+    }
+
+    while (next_gpd && next_meta->offset < frag_end)
+    {
+        shrink_len = (kal_int32)frag_end - next_meta->offset;
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_OVERLAP_NXT, next_meta->offset, next_meta->pkt_len, shrink_len);
+
+        if (shrink_len < next_meta->pkt_len)
+        {
+            if (shrink_len > 0)
+            {
+                next_meta->offset += shrink_len;
+                pkt_grp_info->accumulate_len -= shrink_len;
+            }
+            break;
+        }
+        else
+        {
+            free_gpd = next_gpd;
+            free_meta = next_meta;
+            next_gpd = QBM_DES_GET_NEXT(next_gpd);
+            next_meta = next_meta->next;
+
+            if (priv_gpd)
+            {
+                QBM_DES_SET_NEXT(priv_gpd, next_gpd);
+                priv_meta->next = next_meta;
+            }
+            else
+            {
+                pkt_grp_info->head_gpd = next_gpd;
+                pkt_grp_info->head_meta = next_meta;
+            }
+
+            pkt_grp_info->accumulate_len -= free_meta->pkt_len;
+            qbmt_dest_q(free_gpd, free_gpd);
+            ipc_fragment_mem_free(free_meta);
+        }
+    }
+
+    QBM_DES_SET_NEXT(new_gpd, next_gpd);
+    new_meta->next = next_meta;
+
+    if (!next_gpd)
+    {
+        pkt_grp_info->tail_gpd = new_gpd;
+        pkt_grp_info->tail_meta = new_meta;
+    }
+
+    if (priv_gpd)
+    {
+        QBM_DES_SET_NEXT(priv_gpd, new_gpd);
+        priv_meta->next = new_meta;
+    }
+    else
+    {
+        pkt_grp_info->head_gpd = new_gpd;
+        pkt_grp_info->head_meta = new_meta;
+    }
+
+    pkt_grp_info->accumulate_len += new_meta->pkt_len;
+
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_INSERT, new_meta->offset, new_meta->pkt_len, pkt_grp_info->accumulate_len, frag_offset);
+
+    if (frag_offset == 0)
+    {
+        pkt_grp_info->info_mask |= IPC_FRAG_INFO_RECEIVE_FIRST_PKT;
+        pkt_grp_info->filter_id = matched_filter_id;
+        memcpy(&(pkt_grp_info->first_packet_info), packet_info, sizeof(ipc_packet_info_t));
+        memcpy(&(pkt_grp_info->first_packet_refilter_info), refilter_info, sizeof(ipc_frag_refilter_info_t));
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_FIRST_FRAG, pkt_grp_info->filter_id);
+    }
+
+    if (pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_FIRST_PKT && pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_LAST_PKT &&
+        pkt_grp_info->total_len == pkt_grp_info->accumulate_len)
+    {
+
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_COMPLETE);
+
+        // Send collected fragments to IPCORE for refiltering, and IPCORE will help to trigger reassemable if needed
+        (pkt_grp_info->first_packet_refilter_info).packet_info = &(pkt_grp_info->first_packet_info);
+        if (ipc_fragment_defrag_reasm_en)
+        {
+            ipc_fragment_reassemble(KAL_TRUE, &reasm_gpd, pkt_grp_info);
+        }
+        ipc_fragment_refiltering_queued_packets(IPC_IP_TYPE_IPV4, &(pkt_grp_info->first_packet_refilter_info), pkt_grp_info->head_gpd, pkt_grp_info->tail_gpd);
+        pkt_grp_info->head_gpd = pkt_grp_info->tail_gpd = NULL;
+
+        pkt_grp_info->info_mask |= IPC_FRAG_INFO_RECEIVE_COMPLETE;
+        ipc_fragment_mp_erase(&v4_key, KAL_TRUE);
+    }
+
+    if (need_insert_cb == KAL_TRUE)
+    {
+        key_with_time.v4_key = v4_key;
+        key_with_time.tickStamp = kal_get_systicks();
+
+        if (IPCF_Q_EXP_NXTP(ipc_q_exp_pw_v4) == ipc_q_exp_pr_v4)
+        {
+            ipc_fragment_queuing_recycle(KAL_TRUE);
+        }
+
+        if (ipc_q_exp_pw_v4 == ipc_q_exp_pr_v4 && ipc_q_exp_pw_v6 == ipc_q_exp_pr_v6)
+        {
+            ipc_fragment_queuing_set_expire_timer();
+        }
+
+        ipc_q_exp_buff_v4[ipc_q_exp_pw_v4] = key_with_time;
+        ipc_q_exp_pw_v4 = IPCF_Q_EXP_NXTP(ipc_q_exp_pw_v4);
+    }
+
+    return;
+
+ipc_frag_v4_queue_err:
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_ERR, new_gpd, new_meta);
+
+    if (new_meta)
+    {
+        ipc_fragment_mem_free(new_meta);
+    }
+
+    if (new_gpd)
+    {
+        ipc_frag_send_pkt(IPC_IP_TYPE_IPV4, refilter_info, new_gpd, new_gpd);
+    }
+
+    return;
+}
+
+void ipc_fragment_queuing_v6(qbm_gpd *new_gpd, ipc_packet_info_t *packet_info, kal_uint32 matched_filter_id, ipc_frag_refilter_info_t *refilter_info)
+{
+    IpcFragPktGroupInfo *pkt_grp_info;
+    IpcFragPktMetaInfo *new_meta = NULL, *next_meta, *priv_meta;
+    qbm_gpd *next_gpd, *priv_gpd, *reasm_gpd;
+    IpcFragIpv6L3Key v6_key;
+    kal_uint8 frag_flag;
+    kal_uint32 frag_offset, frag_end;
+    kal_uint8 i;
+    IpcFragIpv6L3KeyWithTStamp key_with_time;
+    kal_bool need_insert_cb = KAL_FALSE;
+    void *buff;
+    kal_uint16 buff_len;
+
+    if (!new_gpd || !packet_info || !refilter_info)
+    {
+        goto ipc_frag_v6_queue_err;
+    }
+
+    for (i = 0; i < 4; ++i)
+    {
+        v6_key.src_addr[i] = packet_info->src_addr[i];
+        v6_key.dst_addr[i] = packet_info->dst_addr[i];
+    }
+    v6_key.ip_id = packet_info->ip_id;
+    if (ipc_fragment_mp_getMN(&v6_key, KAL_FALSE))
+    {
+        pkt_grp_info = ipc_fragment_mp_addMN(&v6_key, KAL_FALSE);
+    }
+    else
+    {
+        pkt_grp_info = ipc_fragment_mp_addMN(&v6_key, KAL_FALSE);
+        ipc_fragment_pktg_init(pkt_grp_info);
+    }
+
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_V6_KEY_INFO_SRC, v6_key.src_addr[0], v6_key.src_addr[1], v6_key.src_addr[2], v6_key.src_addr[3]);
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_V6_KEY_INFO_DST, v6_key.dst_addr[0], v6_key.dst_addr[1], v6_key.dst_addr[2], v6_key.dst_addr[3]);
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_V6_KEY_INFO_ID, v6_key.ip_id);
+
+    if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_COMPLETE) || (pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_DROPPED))
+    {
+        goto ipc_frag_v6_queue_err;
+    }
+
+    new_meta = (IpcFragPktMetaInfo *)ipc_fragment_mem_alloc(sizeof(IpcFragPktMetaInfo));
+    if (!new_meta)
+    {
+        if (ipc_fragment_queuing_recycle_meta_in_insufficient_space(KAL_FALSE) || ipc_fragment_queuing_recycle_meta_in_insufficient_space(KAL_TRUE))
+        {
+            new_meta = (IpcFragPktMetaInfo *)ipc_fragment_mem_alloc(sizeof(IpcFragPktMetaInfo));
+        }
+        else
+        {
+            ASSERT(0);
+        }
+
+        if (pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_DROPPED)
+        {
+            goto ipc_frag_v6_queue_err;
+        }
+    }
+    frag_offset = new_meta->offset = new_meta->orig_offset = packet_info->frag_payload_offset;
+    new_meta->pkt_len = new_meta->orig_pkt_len = packet_info->frag_payload_len;
+    new_meta->gpd_payload_offset = packet_info->frag_buffer_payload_offset;
+    frag_end = new_meta->offset + new_meta->pkt_len;
+    frag_flag = packet_info->frag_flag;
+
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_FRAG_INFO, frag_offset, new_meta->pkt_len, frag_flag, frag_end);
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_GRP_INFO, pkt_grp_info->info_mask, pkt_grp_info->accumulate_len, pkt_grp_info->total_len, pkt_grp_info->head_gpd);
+
+    // Dump the GPD packet in ELT, assume the input GPD must be followed with one BD
+    buff_len = QBM_DES_GET_DATALEN(new_gpd);
+    buff = QBM_DES_GET_DATAPTR(QBM_DES_GET_DATAPTR(new_gpd));
+    IPC_FRAGMENT_DL_PKT_DUMP(buff, buff_len);
+
+    if (frag_end > IPC_FRAG_IPV6_MAX_LEN)
+    {
+        // TODO: send ICMP
+        goto ipc_frag_v6_queue_err;
+    }
+
+    if (pkt_grp_info->head_gpd == NULL)
+    {
+        memcpy(&(pkt_grp_info->first_packet_refilter_info), refilter_info, sizeof(ipc_frag_refilter_info_t));
+        need_insert_cb = KAL_TRUE;
+    }
+
+    if ((frag_flag & IPC_FRAG_FLAG_MF) == 0)
+    {
+        if ((frag_end < pkt_grp_info->accumulate_len) || ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_LAST_PKT) && (frag_end != pkt_grp_info->total_len)))
+        {
+            goto ipc_frag_v6_queue_err;
+        }
+
+        pkt_grp_info->info_mask |= IPC_FRAG_INFO_RECEIVE_LAST_PKT;
+        pkt_grp_info->total_len = frag_end;
+
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_LAST_FRAG);
+    }
+    else
+    {
+        if ((pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_LAST_PKT) && (frag_end > pkt_grp_info->total_len))
+        {
+            goto ipc_frag_v6_queue_err;
+        }
+    }
+
+    if (new_meta->pkt_len == 0)
+    {
+        goto ipc_frag_v6_queue_err;
+    }
+
+    priv_meta = pkt_grp_info->tail_meta;
+    priv_gpd = pkt_grp_info->tail_gpd;
+    if (!priv_gpd || priv_meta->offset < frag_offset)
+    {
+        next_gpd = NULL;
+        next_meta = NULL;
+    }
+    else
+    {
+        priv_meta = NULL;
+        priv_gpd = NULL;
+        next_gpd = pkt_grp_info->head_gpd;
+        next_meta = pkt_grp_info->head_meta;
+
+        while (next_gpd)
+        {
+            if (next_meta->offset >= frag_offset)
+            {
+                break;
+            }
+            else
+            {
+                priv_gpd = next_gpd;
+                priv_meta = next_meta;
+                next_gpd = QBM_DES_GET_NEXT(next_gpd);
+                next_meta = next_meta->next;
+            }
+        }
+    }
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_FIND_POS, priv_gpd, priv_meta, next_gpd, next_meta);
+
+    if (priv_gpd && (kal_uint32)priv_meta->offset + priv_meta->pkt_len > frag_offset)
+    {
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_OVERLAP_PRIV, priv_meta->offset, priv_meta->pkt_len, 0);
+        ipc_fragment_mp_erase(&v6_key, KAL_FALSE);
+        goto ipc_frag_v6_queue_err;
+    }
+
+    if (next_gpd && next_meta->offset < frag_end)
+    {
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_OVERLAP_NXT, next_meta->offset, next_meta->pkt_len, 0);
+        ipc_fragment_mp_erase(&v6_key, KAL_FALSE);
+        goto ipc_frag_v6_queue_err;
+    }
+
+    QBM_DES_SET_NEXT(new_gpd, next_gpd);
+    new_meta->next = next_meta;
+
+    if (!next_gpd)
+    {
+        pkt_grp_info->tail_gpd = new_gpd;
+        pkt_grp_info->tail_meta = new_meta;
+    }
+
+    if (priv_gpd)
+    {
+        QBM_DES_SET_NEXT(priv_gpd, new_gpd);
+        priv_meta->next = new_meta;
+    }
+    else
+    {
+        pkt_grp_info->head_gpd = new_gpd;
+        pkt_grp_info->head_meta = new_meta;
+    }
+
+    pkt_grp_info->accumulate_len += new_meta->pkt_len;
+
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_INSERT, new_meta->offset, new_meta->pkt_len, pkt_grp_info->accumulate_len, frag_offset);
+
+    if (frag_offset == 0)
+    {
+        pkt_grp_info->info_mask |= IPC_FRAG_INFO_RECEIVE_FIRST_PKT;
+        pkt_grp_info->filter_id = matched_filter_id;
+        memcpy(&(pkt_grp_info->first_packet_info), packet_info, sizeof(ipc_packet_info_t));
+        memcpy(&(pkt_grp_info->first_packet_refilter_info), refilter_info, sizeof(ipc_frag_refilter_info_t));
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_FIRST_FRAG, pkt_grp_info->filter_id);
+    }
+
+    if (pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_FIRST_PKT && pkt_grp_info->info_mask & IPC_FRAG_INFO_RECEIVE_LAST_PKT &&
+        pkt_grp_info->total_len == pkt_grp_info->accumulate_len)
+    {
+
+        hif_data_trace(MD_TRC_IPC_FRAG_QUE_COMPLETE);
+
+        // Send collected fragments to IPCORE for refiltering, and IPCORE will help to trigger reassemable if needed
+        (pkt_grp_info->first_packet_refilter_info).packet_info = &(pkt_grp_info->first_packet_info);
+        if (ipc_fragment_defrag_reasm_en || pkt_grp_info->first_packet_info.need_reassemble)
+        {
+            ipc_fragment_reassemble(KAL_FALSE, &reasm_gpd, pkt_grp_info);
+            pkt_grp_info->first_packet_refilter_info.is_pkt_info = KAL_FALSE;
+            pkt_grp_info->first_packet_info.need_reassemble = KAL_FALSE;
+        } else {
+            pkt_grp_info->first_packet_refilter_info.is_pkt_info = KAL_TRUE;
+        }
+        ipc_fragment_refiltering_queued_packets(IPC_IP_TYPE_IPV6, &(pkt_grp_info->first_packet_refilter_info), pkt_grp_info->head_gpd, pkt_grp_info->tail_gpd);
+        pkt_grp_info->head_gpd = pkt_grp_info->tail_gpd = NULL;
+
+        pkt_grp_info->info_mask |= IPC_FRAG_INFO_RECEIVE_COMPLETE;
+        ipc_fragment_mp_erase(&v6_key, KAL_FALSE);
+    }
+
+    if (need_insert_cb == KAL_TRUE)
+    {
+        key_with_time.v6_key = v6_key;
+        key_with_time.tickStamp = kal_get_systicks();
+
+        if (IPCF_Q_EXP_NXTP(ipc_q_exp_pw_v6) == ipc_q_exp_pr_v6)
+        {
+            ipc_fragment_queuing_recycle(KAL_FALSE);
+        }
+
+        if (ipc_q_exp_pw_v4 == ipc_q_exp_pr_v4 && ipc_q_exp_pw_v6 == ipc_q_exp_pr_v6)
+        {
+            ipc_fragment_queuing_set_expire_timer();
+        }
+
+        ipc_q_exp_buff_v6[ipc_q_exp_pw_v6] = key_with_time;
+        ipc_q_exp_pw_v6 = IPCF_Q_EXP_NXTP(ipc_q_exp_pw_v6);
+    }
+
+    return;
+
+ipc_frag_v6_queue_err:
+    hif_data_trace(MD_TRC_IPC_FRAG_QUE_ERR, new_gpd, new_meta);
+    if (new_meta)
+    {
+        ipc_fragment_mem_free(new_meta);
+    }
+
+    if (new_gpd)
+    {
+        ipc_frag_send_pkt(IPC_IP_TYPE_IPV6, refilter_info, new_gpd, new_gpd);
+    }
+
+    return;
+}
+
+void ipc_fragment_mp_test()
+{
+    kal_int32 i, j;
+    IpcFragIpv4L3Key v4_key = {0};
+    IpcFragIpv6L3Key v6_key = {0};
+    IpcFragPktMetaInfo *meta_node = NULL;
+    IpcFragPktGroupInfo *p_info = NULL;
+    IpcFragMnd4 *p_ptr= NULL;
+
+    for (i = 0; i < 20; ++i)
+    {
+        for (j = 0; j < 4; ++j)
+        {
+            v4_key.src_addr = i;
+            v4_key.dst_addr = 30000 + i;
+            v4_key.ip_id = 2000 + i;
+            v4_key.protocol = 100 + i;
+
+            meta_node = (IpcFragPktMetaInfo *)ipc_fragment_mem_alloc(sizeof(IpcFragPktMetaInfo));
+            ASSERT(meta_node);
+            meta_node->next = ipc_fragment_mp_addMN(&v4_key, KAL_TRUE)->head_meta;
+            meta_node->offset = j;
+            meta_node->pkt_len = i + j;
+            p_info = ipc_fragment_mp_addMN(&v4_key, KAL_TRUE);
+            if (NULL == p_info) {
+                return;
+            }
+            p_info->head_meta = meta_node;
+
+            p_ptr = ipc_fragment_mp_getMN(&v4_key, KAL_TRUE);
+            if (NULL == p_ptr) {
+                return;
+            }
+
+            ASSERT(ipc_fragment_ipv4_l3eq(&v4_key, &(p_ptr->key)) == KAL_TRUE);
+            v4_key.protocol = i;
+            ASSERT(ipc_fragment_mp_getMN(&v4_key, KAL_TRUE) == NULL);
+        }
+
+        for (j = 0; j < 4; ++j)
+        {
+            v6_key.src_addr[0] = i + 0;
+            v6_key.src_addr[1] = i + 1;
+            v6_key.src_addr[2] = i + 2;
+            v6_key.src_addr[3] = i + 3;
+            v6_key.dst_addr[0] = 30000 + i;
+            v6_key.dst_addr[1] = 30001 + i;
+            v6_key.dst_addr[2] = 30002 + i;
+            v6_key.dst_addr[3] = 30003 + i;
+            v6_key.ip_id = 4000 + i;
+
+            meta_node = (IpcFragPktMetaInfo *)ipc_fragment_mem_alloc(sizeof(IpcFragPktMetaInfo));
+            ASSERT(meta_node);
+            meta_node->next = ipc_fragment_mp_addMN(&v6_key, KAL_FALSE)->head_meta;
+            meta_node->offset = j;
+            meta_node->pkt_len = i + j;
+            ipc_fragment_mp_addMN(&v6_key, KAL_FALSE)->head_meta = meta_node;
+            ASSERT(ipc_fragment_ipv6_l3eq(&v6_key, &(((IpcFragMnd6 *)ipc_fragment_mp_getMN(&v6_key, KAL_FALSE))->key)) == KAL_TRUE);
+            v6_key.ip_id = i;
+            ASSERT(ipc_fragment_mp_getMN(&v6_key, KAL_FALSE) == NULL);
+        }
+    }
+}
+
+void ipc_fragment_efrag_reasm_en_test(kal_bool is_enable)
+{
+    ipc_fragment_defrag_reasm_en = is_enable;
+}
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_export.c b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_export.c
new file mode 100644
index 0000000..d7c5fdf
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_export.c
@@ -0,0 +1,102 @@
+#include "ipc_fragment.h"
+#include "ipc_fragment_frag.h"
+#include "ipc_fragment_utility.h"
+#include "ipc_fragment_export.h"
+
+static inline kal_bool ipc_fragment_init_internal(kal_bool is_reset)
+{
+    ipc_fragment_afm_init();
+    ipc_fragment_mp_init();
+
+    if (KAL_FALSE == is_reset)
+    {
+        ipc_fragment_set_ipc_refilter_func_ptr(ipc_frag_refilter);
+        ipc_fragment_queuing_expire_init(); // event scheduler should be only created at init stage
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_fragment_init()
+{
+    return ipc_fragment_init_internal(KAL_FALSE);
+}
+
+kal_bool ipc_fragment_deinit()
+{
+    ipc_fragment_queuing_expire_deinit();
+    ipc_fragment_mp_deinit();
+    ipc_fragment_afm_deinit();
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_fragment_reset()
+{
+    ipc_fragment_deinit();
+    ipc_fragment_init_internal(KAL_TRUE);
+
+    return KAL_TRUE;
+}
+
+kal_uint32 ipc_fragment_frag(void *buff, kal_uint32 buff_len, qbm_gpd **frag_gpd_head, qbm_gpd **frag_gpd_tail, kal_bool is_v4)
+{
+    kal_uint32 reasm_gpd_num = 0;
+
+    ASSERT(buff);
+    ASSERT(buff_len > 0);
+
+    if (is_v4 == KAL_TRUE)
+    {
+        reasm_gpd_num = ipc_fragment_frag_v4(buff, buff_len, frag_gpd_head, frag_gpd_tail, NULL);
+    }
+    else
+    {
+        reasm_gpd_num = ipc_fragment_frag_v6(buff, buff_len, frag_gpd_head, frag_gpd_tail, NULL);
+    }
+
+    return reasm_gpd_num;
+}
+
+void ipc_fragment_defrag(qbm_gpd *new_gpd, ipc_frag_refilter_info_t *info, kal_bool is_v4)
+{
+    ipc_packet_info_t *packet_info;
+    kal_uint32 matched_filter_id;
+
+    ASSERT(info);
+
+    packet_info = info->packet_info;
+    matched_filter_id = info->filter_id;
+
+    if (is_v4 == KAL_TRUE)
+    {
+        ipc_fragment_queuing_v4(new_gpd, packet_info, matched_filter_id, info);
+    }
+    else
+    {
+        ipc_fragment_queuing_v6(new_gpd, packet_info, matched_filter_id, info);
+    }
+}
+
+void ipc_fragment_on_ilm(ilm_struct *ilm)
+{
+    ipc_fragment_t *p = ipc_fragment_get_inst();
+
+    switch (ilm->msg_id)
+    {
+    case MSG_ID_TIMER_EXPIRY:
+        switch (evshed_get_index(ilm))
+        {
+        case IPC_FRAG_ES_IDX_QUEUE_EXPIRE:
+            evshed_timer_handler(p->ipc_frag_queue_expire_es);
+            break;
+        default:
+            ASSERT(0);
+            break;
+        }
+        break;
+
+    default:
+        break;
+    }
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_frag.c b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_frag.c
new file mode 100644
index 0000000..c5ac2f4
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_frag.c
@@ -0,0 +1,245 @@
+#include "ipc_fragment_frag.h"
+#include "ipc_fragment.h"
+#include "ipc_fragment_struct.h"
+#include "ipc_fragment_utility.h"
+
+#define IPC_FRAGMENT_FRAG_HEADER_BUFF_LEN 128
+
+kal_uint32 ipc_fragment_frag_v4(void *buff, kal_uint32 buff_len, qbm_gpd **frag_gpd_head, qbm_gpd **frag_gpd_tail, ipc_fragment_pkt_info *frag_pkt_info)
+{
+    kal_uint8 header[IPC_FRAGMENT_FRAG_HEADER_BUFF_LEN] = {0};
+    qbm_gpd *gpd = NULL, *priv_gpd = NULL;
+    kal_uint8 *gpd_bd_data_p = NULL;
+    const kal_uint8 *ip_buff = (const kal_uint8 *)buff;
+    kal_uint32 frag_pkt_len = buff_len, header_len, num = 0;
+    kal_uint16 frag_flag, checksum;
+    kal_uint32 frag_dword_align;
+    ipc_packet_info_t info_frag_pkt;
+
+    hif_data_trace(MD_TRC_IPC_FRAG_FRAG_START, 1, buff, buff_len, IPC_NE_GET_2B(ip_buff + 4));
+    IPC_FRAGMENT_UL_PKT_DUMP(buff, buff_len);
+
+    header_len = (IPC_NE_GET_1B(ip_buff) & 0x0f) << 2;
+    ASSERT(IPC_FRAGMENT_FRAG_HEADER_BUFF_LEN > header_len);
+    memcpy(header, ip_buff, header_len);
+    if (frag_pkt_info)
+    {
+        info_frag_pkt.src_addr[0] = IPC_NE_GET_4B(header + 12);
+        info_frag_pkt.dst_addr[0] = IPC_NE_GET_4B(header + 16);
+        info_frag_pkt.ip_id = IPC_NE_GET_2B(header + 4);
+        info_frag_pkt.protocol = IPC_NE_GET_1B(header + 9);
+        info_frag_pkt.fragment = KAL_TRUE;
+    }
+
+    ip_buff += header_len;
+    buff_len -= header_len;
+    frag_flag = (IPC_NE_GET_2B(header + 6) & 0x4000) | 0x2000;
+
+    while (buff_len > 0)
+    {
+        frag_pkt_len = (IPC_FRAG_FRAGMENT_MTU_SIZE - header_len) & (~0x7);
+        frag_pkt_len = (buff_len >= frag_pkt_len) ? frag_pkt_len : buff_len;
+        gpd = (qbm_gpd *)qbm_alloc_one(QBM_TYPE_NET_DL);
+        ASSERT(gpd);
+        ipc_fragment_set_gpd_datalen(gpd, header_len + frag_pkt_len, (void **)&gpd_bd_data_p);
+        memcpy(gpd_bd_data_p, header, header_len);
+        memcpy(gpd_bd_data_p + header_len, ip_buff, frag_pkt_len);
+        IPC_NE_SET_2B(gpd_bd_data_p + 2, frag_pkt_len + header_len);
+        IPC_NE_SET_2B(gpd_bd_data_p + 6, frag_flag);
+        checksum = ipc_fragment_ipv4_cal_header_checksum(gpd_bd_data_p);
+        IPC_NE_SET_2B(gpd_bd_data_p + 10, checksum);
+        if (frag_pkt_info)
+        {
+            info_frag_pkt.frag_payload_len = frag_pkt_len;
+            info_frag_pkt.frag_payload_offset = (frag_flag & 0x1fff) << 3;
+            info_frag_pkt.frag_flag = frag_flag >> 13;
+            info_frag_pkt.frag_buffer_payload_offset = header_len;
+            kal_mem_cpy(&(frag_pkt_info->packet_info[frag_pkt_info->frag_pkt_num++]), &info_frag_pkt, sizeof(ipc_packet_info_t));
+        }
+
+        if (priv_gpd)
+        {
+            QBM_DES_SET_NEXT(priv_gpd, gpd);
+        }
+        else
+        {
+            *frag_gpd_head = gpd;
+        }
+        priv_gpd = gpd;
+        qbm_cal_set_checksum(priv);
+
+        ++num;
+        frag_dword_align = frag_pkt_len & (~0x7);
+        frag_flag += frag_dword_align >> 3;
+        ip_buff += frag_dword_align;
+        buff_len -= (buff_len > frag_pkt_len) ? frag_dword_align : buff_len;
+
+        if (buff_len > 0)
+        {
+            IPC_FRAGMENT_UL_PKT_DUMP(gpd_bd_data_p, header_len + frag_pkt_len);
+        }
+    }
+
+    frag_flag = IPC_NE_GET_2B(gpd_bd_data_p + 6) & 0xdfff;
+    IPC_NE_SET_2B(gpd_bd_data_p + 6, frag_flag);
+    checksum = ipc_fragment_ipv4_cal_header_checksum(gpd_bd_data_p);
+    IPC_NE_SET_2B(gpd_bd_data_p + 10, checksum);
+    if (frag_pkt_info && num - 1 < frag_pkt_info->frag_pkt_num)
+    {
+        frag_pkt_info->packet_info[num - 1].frag_flag &= 0x6;
+    }
+
+    QBM_DES_SET_NEXT(priv_gpd, NULL);
+    qbm_cal_set_checksum(priv_gpd);
+    IPC_FRAGMENT_UL_PKT_DUMP(gpd_bd_data_p, header_len + frag_pkt_len);
+
+    *frag_gpd_tail = priv_gpd;
+
+    hif_data_trace(MD_TRC_IPC_FRAG_FRAG_END, num, *frag_gpd_head, *frag_gpd_tail);
+
+    return num;
+}
+
+kal_uint32 ipc_fragment_frag_v6(void *buff, kal_uint32 buff_len, qbm_gpd **frag_gpd_head, qbm_gpd **frag_gpd_tail, ipc_fragment_pkt_info *frag_pkt_info)
+{
+    static kal_uint32 ip_id = 0;
+    kal_uint8 header[IPC_FRAGMENT_FRAG_HEADER_BUFF_LEN] = {0};
+    kal_uint8 frag_header[IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN] = {0};
+    kal_uint8 *gpd_bd_data_p = NULL;
+    const kal_uint8 *ip_buff = (const kal_uint8 *)buff;
+    kal_uint32 frag_pkt_len = buff_len, header_len, num = 0, priv_header_len;
+    kal_uint8 next_header, priv_next_header;
+    kal_bool find = KAL_FALSE;
+    qbm_gpd *gpd = NULL, *priv_gpd = NULL;
+    kal_uint16 frag_offset;
+    ipc_packet_info_t info_frag_pkt;
+
+    hif_data_trace(MD_TRC_IPC_FRAG_FRAG_START, 0, buff, buff_len, ip_id);
+    IPC_FRAGMENT_UL_PKT_DUMP(buff, buff_len);
+
+    header_len = 40;
+    priv_header_len = 0;
+    next_header = IPC_NE_GET_1B(ip_buff + 6);
+    priv_next_header = IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_NON;
+    while (find == KAL_FALSE)
+    {
+        switch (next_header)
+        {
+        case IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_HOP:
+        case IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_DST:
+        case IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_ROUT:
+            priv_next_header = next_header;
+            next_header = IPC_NE_GET_1B(ip_buff + header_len);
+            priv_header_len = header_len;
+            header_len += 8 + (IPC_NE_GET_1B(ip_buff + header_len + 1) << 3);
+            break;
+
+        default:
+            find = KAL_TRUE;
+            break;
+        }
+    }
+    ASSERT(IPC_FRAGMENT_FRAG_HEADER_BUFF_LEN >= header_len);
+    memcpy(header, ip_buff, header_len);
+    switch (priv_next_header)
+    {
+    case IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_NON:
+        IPC_NE_SET_1B(header + 6, IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_FRAG);
+        break;
+
+    case IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_HOP:
+    case IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_DST:
+    case IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_ROUT:
+        IPC_NE_SET_1B(header + priv_header_len, IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_FRAG);
+        break;
+
+    default:
+        ASSERT(0);
+        break;
+    }
+    if (frag_pkt_info)
+    {
+        info_frag_pkt.src_addr[0] = IPC_NE_GET_4B(header + 8);
+        info_frag_pkt.src_addr[1] = IPC_NE_GET_4B(header + 12);
+        info_frag_pkt.src_addr[2] = IPC_NE_GET_4B(header + 16);
+        info_frag_pkt.src_addr[3] = IPC_NE_GET_4B(header + 20);
+        info_frag_pkt.dst_addr[0] = IPC_NE_GET_4B(header + 24);
+        info_frag_pkt.dst_addr[1] = IPC_NE_GET_4B(header + 28);
+        info_frag_pkt.dst_addr[2] = IPC_NE_GET_4B(header + 32);
+        info_frag_pkt.dst_addr[3] = IPC_NE_GET_4B(header + 36);
+        info_frag_pkt.ip_id = ip_id;
+        info_frag_pkt.fragment = KAL_TRUE;
+    }
+
+    frag_offset = 1;
+    IPC_NE_SET_1B(frag_header, next_header);
+    IPC_NE_SET_2B(frag_header + 2, frag_offset);
+    IPC_NE_SET_4B(frag_header + 4, ip_id);
+
+    ip_buff += header_len;
+    buff_len -= header_len;
+
+    while (buff_len > 0)
+    {
+        frag_pkt_len = (IPC_FRAG_FRAGMENT_MTU_SIZE - header_len - IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN) & (~0x7);
+        frag_pkt_len = (buff_len >= frag_pkt_len) ? frag_pkt_len : buff_len;
+        gpd = (qbm_gpd *)qbm_alloc_one(QBM_TYPE_NET_DL);
+        ASSERT(gpd);
+        ipc_fragment_set_gpd_datalen(gpd, frag_pkt_len + header_len + IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN, (void **)&gpd_bd_data_p);
+        memcpy(gpd_bd_data_p, header, header_len);
+        memcpy(gpd_bd_data_p + header_len, frag_header, IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN);
+        memcpy(gpd_bd_data_p + header_len + IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN, ip_buff, frag_pkt_len);
+        IPC_NE_SET_2B(gpd_bd_data_p + 4, frag_pkt_len + header_len + IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN - 40);
+        if (frag_pkt_info)
+        {
+            info_frag_pkt.frag_payload_len = frag_pkt_len;
+            info_frag_pkt.frag_payload_offset = frag_offset & (~0x7);
+            info_frag_pkt.frag_flag = 0x01;
+            info_frag_pkt.frag_buffer_payload_offset = header_len + IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN;
+            kal_mem_cpy(&(frag_pkt_info->packet_info[frag_pkt_info->frag_pkt_num++]), &info_frag_pkt, sizeof(ipc_packet_info_t));
+        }
+
+        if (priv_gpd)
+        {
+            QBM_DES_SET_NEXT(priv_gpd, gpd);
+        }
+        else
+        {
+            *frag_gpd_head = gpd;
+        }
+        priv_gpd = gpd;
+        qbm_cal_set_checksum(priv);
+
+        ++num;
+        ASSERT(((frag_pkt_len & 0x7) == 0) || (frag_pkt_len == buff_len));
+        frag_offset += frag_pkt_len;
+
+        IPC_NE_SET_2B(frag_header + 2, frag_offset);
+        ip_buff += frag_pkt_len;
+        buff_len -= frag_pkt_len;
+
+        if (buff_len > 0)
+        {
+            IPC_FRAGMENT_UL_PKT_DUMP(gpd_bd_data_p, header_len + IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN + frag_pkt_len);
+        }
+    }
+
+    frag_offset = IPC_NE_GET_2B(gpd_bd_data_p + header_len + 2) & (~0x1);
+    IPC_NE_SET_2B(gpd_bd_data_p + header_len + 2, (frag_offset & (~0x7)));
+
+    if (frag_pkt_info && num - 1 < frag_pkt_info->frag_pkt_num)
+    {
+        frag_pkt_info->packet_info[num - 1].frag_flag &= 0;
+    }
+
+    QBM_DES_SET_NEXT(priv_gpd, NULL);
+    qbm_cal_set_checksum(priv_gpd);
+    IPC_FRAGMENT_UL_PKT_DUMP(gpd_bd_data_p, header_len + IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN + frag_pkt_len);
+
+    *frag_gpd_tail = priv_gpd;
+    ++ip_id;
+
+    hif_data_trace(MD_TRC_IPC_FRAG_FRAG_END, num, *frag_gpd_head, *frag_gpd_tail);
+
+    return num;
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_frag.h b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_frag.h
new file mode 100644
index 0000000..105ee1a
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_frag.h
@@ -0,0 +1,34 @@
+#ifndef _IPC_FRAGMENT_FRAG_INC
+#define _IPC_FRAGMENT_FRAG_INC
+
+#include "ipc_fragment.h"
+#include "ipc_fragment_struct.h"
+
+#define IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_HOP 0
+#define IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_DST 60
+#define IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_ROUT 43
+#define IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_FRAG 44
+#define IPC_FRAGMENT_FRAG_IPV6_EXT_HEADER_NON 59
+
+#define IPC_FRAGMENT_IPV6_FRAG_HEADER_LEN 8
+#define IPC_FRAG_FRAGMENT_MTU_SIZE 1500
+
+#define IPC_FRAG_INVALID_FILTER_ID -1
+#define IPC_FRAG_IPV6_MAX_LEN 65535
+#define IPC_FRAG_FLAG_MF 0x01
+#define IPC_FRAG_INFO_RECEIVE_FIRST_PKT 0x1
+#define IPC_FRAG_INFO_RECEIVE_LAST_PKT 0x2
+#define IPC_FRAG_INFO_RECEIVE_COMPLETE 0x4
+
+#define IPC_FRAG_FRAGMENT_INFO_PKT_NUM_MAX 40
+
+typedef struct _ipc_fragment_pkt_info
+{
+    ipc_packet_info_t packet_info[IPC_FRAG_FRAGMENT_INFO_PKT_NUM_MAX];
+    unsigned frag_pkt_num;
+} ipc_fragment_pkt_info;
+
+kal_uint32 ipc_fragment_frag_v4(void *buff, kal_uint32 buff_len, qbm_gpd **frag_gpd_head, qbm_gpd **frag_gpd_tail, ipc_fragment_pkt_info *frag_pkt_info);
+kal_uint32 ipc_fragment_frag_v6(void *buff, kal_uint32 buff_len, qbm_gpd **frag_gpd_head, qbm_gpd **frag_gpd_tail, ipc_fragment_pkt_info *frag_pkt_info);
+
+#endif /* _IPC_FRAGMENT_FRAG_INC */
\ No newline at end of file
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_reassemble.c b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_reassemble.c
new file mode 100644
index 0000000..f345b7d
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_reassemble.c
@@ -0,0 +1,275 @@
+#include "ipc_fragment.h"
+#include "ipc_fragment_frag.h"
+#include "ipc_fragment_utility.h"
+
+#define IPC_FRAGMENT_EXT_HDR_IPV6 (-1)
+#define IPC_FRAGMENT_TMP_BUFFER_LEN (1024)
+
+inline void ipc_fragment_ipv6_set_next_header(void *new_header_buffer, kal_int16 curr_next_header, kal_int16 next_header, kal_int32 offset)
+{
+    kal_uint8 *p_hdr = (kal_uint8 *)new_header_buffer + offset;
+
+    switch (curr_next_header)
+    {
+    case IPC_FRAGMENT_EXT_HDR_IPV6:
+        IPC_NE_SET_1B(p_hdr + 6, next_header);
+        break;
+
+    case IPC_HDR_PROT_IPV6_HOP:
+    case IPC_HDR_PROT_IPV6_ROUTE:
+    case IPC_HDR_PROT_IPV6_DEST:
+    case IPC_HDR_PROT_AH:
+    case IPC_HDR_PROT_IPV6_FRAG:
+        IPC_NE_SET_1B(p_hdr + 0, next_header);
+        break;
+
+    default:
+        break;
+    }
+
+    return;
+}
+
+kal_int32 ipc_fragment_ipv6_remove_fragment_header(const void *original_ip_hdr, void *out_buffer)
+{
+    kal_int32 ip_header_len;
+    kal_int32 priv_offset;
+    kal_int16 next_header, priv_next_header;
+    const kal_uint8 *original_ip_header = (const kal_uint8 *)original_ip_hdr;
+    kal_uint8 *new_header_buffer = (kal_uint8 *)out_buffer;
+
+    ASSERT(new_header_buffer && new_header_buffer);
+
+    priv_offset = 0;
+    ip_header_len = 40;
+    priv_next_header = IPC_FRAGMENT_EXT_HDR_IPV6; // use -1 to present IPv6 header here
+    next_header = IPC_NE_GET_1B(original_ip_header + 6);
+
+    while (priv_next_header != IPC_HDR_PROT_IPV6_FRAG)
+    {
+
+        switch (next_header)
+        {
+        case IPC_HDR_PROT_IPV6_HOP:
+        case IPC_HDR_PROT_IPV6_ROUTE:
+        case IPC_HDR_PROT_IPV6_DEST:
+            priv_next_header = next_header;
+            next_header = IPC_NE_GET_1B(original_ip_header + ip_header_len + 0);
+            priv_offset = ip_header_len;
+            ip_header_len += (IPC_NE_GET_1B(original_ip_header + ip_header_len + 1) + 1) * 8;
+            break;
+
+        case IPC_HDR_PROT_AH:
+            priv_next_header = next_header;
+            next_header = IPC_NE_GET_1B(original_ip_header + ip_header_len + 0);
+            priv_offset = ip_header_len;
+            ip_header_len += (IPC_NE_GET_1B(original_ip_header + ip_header_len + 1) + 2) * 4;
+            break;
+
+        case IPC_HDR_PROT_IPV6_FRAG:
+            next_header = IPC_NE_GET_1B(original_ip_header + ip_header_len + 0);
+            ASSERT(IPC_FRAGMENT_TMP_BUFFER_LEN >= ip_header_len);
+            memcpy(new_header_buffer, original_ip_header, ip_header_len);
+            ipc_fragment_ipv6_set_next_header(new_header_buffer, priv_next_header, next_header, priv_offset);
+            priv_next_header = IPC_HDR_PROT_IPV6_FRAG;
+            break;
+
+        default:
+            ASSERT(0);
+            break;
+        }
+    }
+
+    return ip_header_len;
+}
+
+void ipc_fragment_dump_packet_from_gpd_with_multi_bd(const qbm_gpd *gpd)
+{
+    static kal_uint8 buff[65600] = {0};
+    kal_int32 buff_len = 0, offset = 0;
+    void *bd = NULL;
+    kal_bool end_of_bd = KAL_FALSE;
+
+    ASSERT(gpd);
+    buff_len = QBM_DES_GET_DATALEN(gpd);
+
+    if (QBM_DES_GET_BDP(gpd))
+    {
+        bd = QBM_DES_GET_DATAPTR(gpd);
+        while (!end_of_bd)
+        {
+            memcpy(buff + offset, QBM_DES_GET_DATAPTR(bd), QBM_DES_GET_DATALEN(bd));
+            offset += QBM_DES_GET_DATALEN(bd);
+            if (!QBM_DES_GET_EOL(bd))
+            {
+                bd = QBM_DES_GET_NEXT(bd);
+            }
+            else
+            {
+                end_of_bd = KAL_TRUE;
+            }
+        }
+    }
+    else
+    {
+        memcpy(buff, QBM_DES_GET_DATAPTR(gpd), QBM_DES_GET_DATALEN(gpd));
+    }
+
+    IPC_FRAGMENT_DL_PKT_DUMP(buff, buff_len);
+}
+
+kal_bool ipc_fragment_reassemble_v4(qbm_gpd **reasm_gpd, IpcFragPktGroupInfo *pkt_grp_info)
+{
+    kal_uint8 *bd_data_addr;
+    kal_uint16 reasm_header_len;
+    kal_uint16 checksum, frag_flag;
+    qbm_gpd *head_gpd, *tail_gpd, *curr_gpd, *next_gpd;
+    IpcFragPktMetaInfo *head_meta, *tail_meta, *curr_meta;
+    kal_uint8 *bd;
+    kal_bool result = KAL_FALSE;
+
+    head_gpd = curr_gpd = pkt_grp_info->head_gpd;
+    tail_gpd = pkt_grp_info->tail_gpd;
+    head_meta = curr_meta = pkt_grp_info->head_meta;
+    tail_meta = pkt_grp_info->tail_meta;
+
+    ASSERT(head_gpd && tail_gpd && head_meta && tail_meta);
+
+    *reasm_gpd = (qbm_gpd *)qbm_alloc_one(QBM_TYPE_TGPD);
+    hif_data_trace(MD_TRC_IPC_FRAG_REASM, 1, *reasm_gpd);
+
+    if (*reasm_gpd)
+    {
+        reasm_header_len = curr_meta->gpd_payload_offset;
+        QBM_DES_SET_BDP(*reasm_gpd);
+        QBM_DES_SET_DATAPTR(*reasm_gpd, curr_gpd);
+        QBM_DES_SET_DATALEN(*reasm_gpd, reasm_header_len + pkt_grp_info->total_len);
+
+        next_gpd = QBM_DES_GET_NEXT(curr_gpd);
+        bd = (kal_uint8 *)QBM_DES_GET_DATAPTR(curr_gpd);
+        bd_data_addr = (kal_uint8 *)QBM_DES_GET_DATAPTR(bd) + curr_meta->offset - curr_meta->orig_offset;
+        QBM_DES_SET_DATAPTR(curr_gpd, bd_data_addr);
+        QBM_DES_SET_DATALEN(curr_gpd, reasm_header_len + curr_meta->pkt_len);
+        QBM_DES_CLR_BDP(curr_gpd);
+        QBM_DES_CLR_EOL(curr_gpd);
+
+        frag_flag = IPC_NE_GET_1B(bd_data_addr + 6);
+        frag_flag &= 0xdf;
+        IPC_NE_SET_1B(bd_data_addr + 6, frag_flag);
+        IPC_NE_SET_2B(bd_data_addr + 2, pkt_grp_info->total_len + reasm_header_len);
+        checksum = ipc_fragment_ipv4_cal_header_checksum(bd_data_addr);
+        IPC_NE_SET_2B(bd_data_addr + 10, checksum);
+        qbm_cal_set_checksum(curr_gpd);
+
+        while (curr_gpd != tail_gpd)
+        {
+            ASSERT(curr_meta != tail_meta);
+
+            curr_gpd = next_gpd;
+            curr_meta = curr_meta->next;
+            next_gpd = QBM_DES_GET_NEXT(next_gpd);
+
+            bd = (kal_uint8 *)QBM_DES_GET_DATAPTR(curr_gpd);
+            bd_data_addr = (kal_uint8 *)QBM_DES_GET_DATAPTR(bd) + curr_meta->gpd_payload_offset + curr_meta->offset - curr_meta->orig_offset;
+            QBM_DES_SET_DATAPTR(curr_gpd, bd_data_addr);
+            QBM_DES_SET_DATALEN(curr_gpd, curr_meta->pkt_len);
+            QBM_DES_CLR_BDP(curr_gpd);
+            QBM_DES_CLR_EOL(curr_gpd);
+            qbm_cal_set_checksum(curr_gpd);
+        }
+        QBM_DES_SET_EOL(curr_gpd);
+        qbm_cal_set_checksum(curr_gpd);
+
+        qbm_cal_set_checksum(*reasm_gpd);
+
+        pkt_grp_info->head_gpd = pkt_grp_info->tail_gpd = *reasm_gpd;
+
+        ipc_fragment_dump_packet_from_gpd_with_multi_bd(*reasm_gpd);
+
+        result = KAL_TRUE;
+    }
+
+    return result;
+}
+
+kal_bool ipc_fragment_reassemble_v6(qbm_gpd **reasm_gpd, IpcFragPktGroupInfo *pkt_grp_info)
+{
+    kal_uint8 *bd_data_addr;
+    kal_uint16 reasm_header_len, cpy_header_len;
+    qbm_gpd *head_gpd, *tail_gpd, *curr_gpd, *next_gpd;
+    IpcFragPktMetaInfo *head_meta, *tail_meta, *curr_meta;
+    kal_uint8 *bd;
+    static kal_uint8 tmp_buffer[IPC_FRAGMENT_TMP_BUFFER_LEN];
+    kal_bool result = KAL_FALSE;
+
+    head_gpd = curr_gpd = pkt_grp_info->head_gpd;
+    tail_gpd = pkt_grp_info->tail_gpd;
+    head_meta = curr_meta = pkt_grp_info->head_meta;
+    tail_meta = pkt_grp_info->tail_meta;
+
+    ASSERT(head_gpd && tail_gpd && head_meta && tail_meta);
+
+    *reasm_gpd = (qbm_gpd *)qbm_alloc_one(QBM_TYPE_TGPD);
+    hif_data_trace(MD_TRC_IPC_FRAG_REASM, 0, *reasm_gpd);
+
+    if (*reasm_gpd)
+    {
+        reasm_header_len = curr_meta->gpd_payload_offset - 8;
+        QBM_DES_SET_BDP(*reasm_gpd);
+        QBM_DES_SET_DATAPTR(*reasm_gpd, curr_gpd);
+        QBM_DES_SET_DATALEN(*reasm_gpd, reasm_header_len + pkt_grp_info->total_len);
+
+        next_gpd = QBM_DES_GET_NEXT(curr_gpd);
+        bd = (kal_uint8 *)QBM_DES_GET_DATAPTR(curr_gpd);
+        bd_data_addr = (kal_uint8 *)QBM_DES_GET_DATAPTR(bd) + curr_meta->offset - curr_meta->orig_offset;
+
+        cpy_header_len = ipc_fragment_ipv6_remove_fragment_header(bd_data_addr, tmp_buffer);
+        ASSERT(cpy_header_len == reasm_header_len);
+        bd_data_addr += 8;
+        memcpy(bd_data_addr, tmp_buffer, reasm_header_len);
+        IPC_NE_SET_2B(bd_data_addr + 4, reasm_header_len + pkt_grp_info->total_len - 40);
+        QBM_CACHE_FLUSH(bd_data_addr, reasm_header_len);
+
+        QBM_DES_SET_DATAPTR(curr_gpd, bd_data_addr);
+        QBM_DES_SET_DATALEN(curr_gpd, reasm_header_len + curr_meta->pkt_len);
+        QBM_DES_CLR_BDP(curr_gpd);
+        QBM_DES_CLR_EOL(curr_gpd);
+        qbm_cal_set_checksum(curr_gpd);
+
+        while (curr_gpd != tail_gpd)
+        {
+            ASSERT(curr_meta != tail_meta);
+
+            curr_gpd = next_gpd;
+            curr_meta = curr_meta->next;
+            next_gpd = QBM_DES_GET_NEXT(next_gpd);
+
+            bd = (kal_uint8 *)QBM_DES_GET_DATAPTR(curr_gpd);
+            bd_data_addr = (kal_uint8 *)QBM_DES_GET_DATAPTR(bd) + curr_meta->gpd_payload_offset + curr_meta->offset - curr_meta->orig_offset;
+            QBM_DES_SET_DATAPTR(curr_gpd, bd_data_addr);
+            QBM_DES_SET_DATALEN(curr_gpd, curr_meta->pkt_len);
+            QBM_DES_CLR_BDP(curr_gpd);
+            QBM_DES_CLR_EOL(curr_gpd);
+            qbm_cal_set_checksum(curr_gpd);
+        }
+        QBM_DES_SET_EOL(curr_gpd);
+        qbm_cal_set_checksum(curr_gpd);
+
+        qbm_cal_set_checksum(*reasm_gpd);
+
+        pkt_grp_info->head_gpd = pkt_grp_info->tail_gpd = *reasm_gpd;
+
+    #ifndef __MTK_TARGET__
+        ipc_fragment_dump_packet_from_gpd_with_multi_bd(*reasm_gpd);
+    #endif 
+
+        result = KAL_TRUE;
+    }
+
+    return result;
+}
+
+kal_bool ipc_fragment_reassemble(kal_bool is_v4, qbm_gpd **reasm_gpd, IpcFragPktGroupInfo *pkt_grp_info)
+{
+    return is_v4 == KAL_TRUE ? ipc_fragment_reassemble_v4(reasm_gpd, pkt_grp_info) : ipc_fragment_reassemble_v6(reasm_gpd, pkt_grp_info);
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_struct.h b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_struct.h
new file mode 100644
index 0000000..ef90b8a
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_struct.h
@@ -0,0 +1,96 @@
+#ifndef _IPC_FRAGMENT_STRUCT_INC
+#define _IPC_FRAGMENT_STRUCT_INC
+
+#include "ipc_fragment.h"
+
+typedef struct _ipc_fragment_t
+{
+    KAL_AFM_ID k_afm_id;
+    kal_uint8 *afm_buffer_p;
+    kal_uint32 *afm_sub_buffer_size_p;
+    kal_uint32 *afm_sub_buffer_num_p;
+    kal_uint32 afm_left_mem_size;
+    event_scheduler *ipc_frag_queue_expire_es;
+    eventid ipc_frag_queue_expire_evt;
+} ipc_fragment_t;
+
+typedef struct _IpcFragIpv4L3Key
+{
+    kal_uint32 src_addr;
+    kal_uint32 dst_addr;
+    kal_uint16 ip_id;
+    kal_uint8 protocol;
+    kal_uint8 reserved;
+} IpcFragIpv4L3Key;
+
+typedef struct _IpcFragIpv6L3Key
+{
+    kal_uint32 src_addr[4];
+    kal_uint32 dst_addr[4];
+    kal_uint32 ip_id;
+} IpcFragIpv6L3Key;
+
+typedef struct _IpcFragPktMetaInfo IpcFragPktMetaInfo;
+struct _IpcFragPktMetaInfo
+{
+    kal_uint16 offset;
+    kal_uint16 pkt_len;
+    kal_uint16 orig_offset;
+    kal_uint16 orig_pkt_len;
+    kal_uint16 gpd_payload_offset;
+    IpcFragPktMetaInfo *next;
+};
+
+typedef struct _IpcFragPktGroupInfo
+{
+    qbm_gpd *head_gpd, *tail_gpd;
+    IpcFragPktMetaInfo *head_meta, *tail_meta;
+    kal_uint32 info_mask;
+    kal_uint16 total_len;
+    kal_uint16 accumulate_len;
+    kal_int32 filter_id;
+    ipc_packet_info_t first_packet_info;
+    ipc_frag_refilter_info_t first_packet_refilter_info;
+} IpcFragPktGroupInfo;
+
+typedef struct _IpcFragIpv4L3KeyWithTStamp
+{
+    IpcFragIpv4L3Key v4_key;
+    kal_uint32 tickStamp;
+} IpcFragIpv4L3KeyWithTStamp;
+
+typedef struct _IpcFragIpv6L3KeyWithTStamp
+{
+    IpcFragIpv6L3Key v6_key;
+    kal_uint32 tickStamp;
+} IpcFragIpv6L3KeyWithTStamp;
+
+typedef struct _IpcFragMnd4 IpcFragMnd4;
+struct _IpcFragMnd4
+{
+    IpcFragIpv4L3Key key;
+    IpcFragPktGroupInfo val;
+    IpcFragMnd4 *next;
+};
+
+typedef struct _IpcFragMnd6 IpcFragMnd6;
+struct _IpcFragMnd6
+{
+    IpcFragIpv6L3Key key;
+    IpcFragPktGroupInfo val;
+    IpcFragMnd6 *next;
+};
+
+typedef struct _IpcFragUM4
+{
+    IpcFragMnd4 **mp;
+    kal_uint32 mp_num;
+} IpcFragUM4;
+
+typedef struct _IpcFragUM6
+{
+    IpcFragMnd6 **mp;
+    kal_uint32 mp_num;
+} IpcFragUM6;
+
+#endif /* _IPC_FRAGMENT_STRUCTINC */
\ No newline at end of file
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_ut.c b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_ut.c
new file mode 100644
index 0000000..c32b51d
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_ut.c
@@ -0,0 +1,270 @@
+#include "ipc_fragment.h"
+#include "ipc_fragment_frag.h"
+#include "ipc_fragment_struct.h"
+#include "ipc_fragment_utility.h"
+#include "ipc_fragment_export.h"
+
+#define IPC_FRAG_TEST_REASM_IPV4_LEN 24
+#define IPC_FRAG_TEST_REASM_IPV6_LEN 56
+#define IPC_FRAG_TEST_REASM_UDP_LEN 8
+#define IPC_FRAG_TEST_REASM_LARGE_DATA_LEN 16214
+
+static qbm_gpd *reasm_pkt_v4_gpd;
+static qbm_gpd *reasm_pkt_v6_gpd;
+
+void ipc_fragment_reassemble_test_send2defrag(kal_bool is_v4, kal_uint32 frag_gpd_num, qbm_gpd *frag_gpd_head, qbm_gpd *frag_gpd_tail, ipc_fragment_pkt_info *frag_pkt_info, kal_bool quening_in_order)
+{
+    ipc_frag_refilter_info_t refilter_info;
+    kal_uint32 idx, idx2;
+    qbm_gpd *curr_gpd;
+    ipc_packet_info_t *p_pkt_info;
+
+    if (is_v4 == KAL_TRUE)
+    {
+        reasm_pkt_v4_gpd = NULL;
+    }
+    else
+    {
+        reasm_pkt_v6_gpd = NULL;
+    }
+
+    refilter_info.uplink = KAL_FALSE;
+    refilter_info.netif_id = 0;
+    refilter_info.pdn_id = 0;
+    refilter_info.filter_id = 1;
+    refilter_info.filter_magic_number = 0xABCDEFFF;
+
+    if (quening_in_order == KAL_TRUE)
+    {
+        for (idx = 0; idx < frag_gpd_num; ++idx)
+        {
+            curr_gpd = frag_gpd_head;
+            ASSERT(curr_gpd);
+            frag_gpd_head = (qbm_gpd *)QBM_DES_GET_NEXT(frag_gpd_head);
+            p_pkt_info = &(frag_pkt_info->packet_info[idx]);
+            refilter_info.packet_info = p_pkt_info;
+            ipc_fragment_defrag(curr_gpd, &refilter_info, is_v4);
+        }
+    }
+    else
+    {
+        for (idx = frag_gpd_num; idx > 0; --idx)
+        {
+            curr_gpd = frag_gpd_head;
+            for (idx2 = 1; idx2 < idx; ++idx2)
+            {
+                curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+            }
+            ASSERT(curr_gpd);
+            p_pkt_info = &(frag_pkt_info->packet_info[idx - 1]);
+            refilter_info.packet_info = p_pkt_info;
+            ipc_fragment_defrag(curr_gpd, &refilter_info, is_v4);
+        }
+    }
+}
+
+kal_uint8 conn_buff[IPC_FRAG_TEST_REASM_LARGE_DATA_LEN];
+kal_bool ipc_fragment_reassemble_test_cmp_reasm_gpd(qbm_gpd *reasm_gpd, const kal_uint8 *large_packet)
+{
+    kal_bool end_of_bd = KAL_FALSE;
+    void *bd = NULL;
+    kal_uint32 offset = 0;
+    kal_int32 cmp;
+
+    ASSERT(reasm_gpd);
+	kal_mem_set(conn_buff, 0, IPC_FRAG_TEST_REASM_LARGE_DATA_LEN);
+
+    if (QBM_DES_GET_BDP(reasm_gpd))
+    {
+        bd = QBM_DES_GET_DATAPTR(reasm_gpd);
+        while (end_of_bd == KAL_FALSE)
+        {
+            memcpy(conn_buff + offset, QBM_DES_GET_DATAPTR(bd), QBM_DES_GET_DATALEN(bd));
+            offset += QBM_DES_GET_DATALEN(bd);
+            if (!QBM_DES_GET_EOL(bd))
+            {
+                bd = QBM_DES_GET_NEXT(bd);
+            }
+            else
+            {
+                end_of_bd = KAL_TRUE;
+            }
+        }
+    }
+    else
+    {
+        memcpy(conn_buff, QBM_DES_GET_DATAPTR(reasm_gpd), QBM_DES_GET_DATALEN(reasm_gpd));
+    }
+    cmp = memcmp(conn_buff, large_packet, IPC_FRAG_TEST_REASM_LARGE_DATA_LEN);
+
+    return (cmp == 0) ? KAL_TRUE : KAL_FALSE;
+}
+
+kal_uint8 header_v4[IPC_FRAG_TEST_REASM_IPV4_LEN] = {0x45, 0x00, 0x00, 0x00, 0x12, 0x34, 0x40, 0x00, 0x40, 0x11, 0xeb, 0x59,
+                                                     0x0a, 0x0b, 0x0c, 0x0d, 0x0d, 0x0c, 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00};
+kal_uint8 header_v6[IPC_FRAG_TEST_REASM_IPV6_LEN] = {0x60, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x20,        //
+                                                     0x0a, 0x0b, 0x0c, 0x0d, 0x1a, 0x1b, 0x1c, 0x1d,  // v6 src
+                                                     0x2a, 0x2b, 0x2c, 0x2d, 0x3a, 0x3b, 0x3c, 0x3d,  //
+                                                     0x3a, 0x3b, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2d,  // v6 dst
+                                                     0x1a, 0x1b, 0x1c, 0x1d, 0x0a, 0x0b, 0x0c, 0x0d,  //
+                                                     0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // hop-by-hop opt
+                                                     0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // destination opt
+kal_uint8 udp_header[IPC_FRAG_TEST_REASM_UDP_LEN] = {0xea, 0xfb, 0x13, 0x8c, 0x00, 0x00, 0x00, 0x00};
+kal_uint8 large_packet[IPC_FRAG_TEST_REASM_LARGE_DATA_LEN];
+ipc_fragment_pkt_info frag_pkt_info;
+void ipc_fragment_reassemble_test_v4(kal_bool quening_in_order)
+{
+    static kal_uint16 ip_id = 0;
+    kal_uint16 pkt_len = 0, header_len;
+    qbm_gpd *frag_gpd_head = NULL, *frag_gpd_tail = NULL;
+    kal_uint32 frag_gpd_num = 0;
+    kal_uint32 checksum;
+    kal_uint8 raw_data;
+    kal_uint32 offset;
+    kal_bool cmp_result;
+
+	kal_mem_set(large_packet, 0, IPC_FRAG_TEST_REASM_LARGE_DATA_LEN);
+    kal_mem_set(&frag_pkt_info, 0, sizeof(ipc_fragment_pkt_info));
+    /* Generate large packet */
+    IPC_NE_SET_2B(header_v4 + 4, ip_id);
+    ++ip_id;
+    header_len = (IPC_NE_GET_1B(header_v4) & 0x0f) << 2;
+    memcpy(large_packet, header_v4, header_len);
+    pkt_len += header_len;
+    memcpy(large_packet + pkt_len, udp_header, IPC_FRAG_TEST_REASM_UDP_LEN);
+    pkt_len += IPC_FRAG_TEST_REASM_UDP_LEN;
+    for (raw_data = 0; pkt_len < IPC_FRAG_TEST_REASM_LARGE_DATA_LEN; ++raw_data)
+    {
+        large_packet[pkt_len++] = raw_data;
+    }
+    // Update IPv4 header and header checksum
+    IPC_NE_SET_2B(large_packet + 2, IPC_FRAG_TEST_REASM_LARGE_DATA_LEN);
+    checksum = ipc_fragment_ipv4_cal_header_checksum(large_packet);
+    IPC_NE_SET_2B(large_packet + 10, checksum);
+    // Update udp_header
+    IPC_NE_SET_2B(large_packet + header_len + 4, IPC_FRAG_TEST_REASM_LARGE_DATA_LEN - header_len);
+    checksum = IPC_NE_GET_2B(header_v4 + 12) + IPC_NE_GET_2B(header_v4 + 14) + IPC_NE_GET_2B(header_v4 + 16) + IPC_NE_GET_2B(header_v4 + 18) + IPC_NE_GET_1B(header_v4 + 9) +
+               IPC_NE_GET_2B(large_packet + header_len + 4);
+    checksum += IPC_NE_GET_2B(udp_header + 0) + IPC_NE_GET_2B(udp_header + 2) + IPC_NE_GET_2B(large_packet + header_len + 4);
+    for (offset = header_len + IPC_FRAG_TEST_REASM_UDP_LEN; offset < IPC_FRAG_TEST_REASM_LARGE_DATA_LEN; offset += 2)
+    {
+        checksum += ((offset + 2) <= IPC_FRAG_TEST_REASM_LARGE_DATA_LEN) ? IPC_NE_GET_2B(large_packet + offset) : (IPC_NE_GET_1B(large_packet + offset) << 8);
+        while (checksum & 0xffff0000)
+        {
+            checksum = (checksum & 0xffff) + ((checksum & 0xffff0000) >> 16);
+        }
+    }
+    checksum = ((checksum == 0xffff) ? checksum : ~checksum) & 0xffff;
+    IPC_NE_SET_2B(large_packet + header_len + 6, checksum);
+
+    /* Large packet fragment */
+    frag_gpd_num = ipc_fragment_frag_v4(large_packet, pkt_len, &frag_gpd_head, &frag_gpd_tail, &frag_pkt_info);
+
+    /* IPv4 defragment */
+    ipc_fragment_reassemble_test_send2defrag(KAL_TRUE, frag_gpd_num, frag_gpd_head, frag_gpd_tail, &frag_pkt_info, quening_in_order);
+
+    /* Compare orignial packet with reassemabled packet */
+    cmp_result = ipc_fragment_reassemble_test_cmp_reasm_gpd(reasm_pkt_v4_gpd, large_packet);
+    ASSERT(cmp_result == KAL_TRUE);
+
+    qbmt_dest_q(reasm_pkt_v4_gpd, reasm_pkt_v4_gpd);
+}
+
+void ipc_fragment_reassemble_test_v6(kal_bool quening_in_order)
+{
+    kal_uint32 large_pkt_len;
+    kal_uint16 pkt_len = 0, header_len;
+    qbm_gpd *frag_gpd_head = NULL, *frag_gpd_tail = NULL;
+    kal_uint32 frag_gpd_num = 0;
+    kal_uint32 checksum;
+    kal_uint8 raw_data;
+    kal_uint32 offset;
+    kal_bool cmp_result;
+
+	kal_mem_set(large_packet, 0, IPC_FRAG_TEST_REASM_LARGE_DATA_LEN);
+    kal_mem_set(&frag_pkt_info, 0, sizeof(ipc_fragment_pkt_info));
+    /* Generate large packet */
+    header_len = IPC_FRAG_TEST_REASM_IPV6_LEN;
+    memcpy(large_packet, header_v6, header_len);
+    pkt_len += header_len;
+    memcpy(large_packet + pkt_len, udp_header, IPC_FRAG_TEST_REASM_UDP_LEN);
+    pkt_len += IPC_FRAG_TEST_REASM_UDP_LEN;
+    large_pkt_len = IPC_FRAG_TEST_REASM_LARGE_DATA_LEN;
+    for (raw_data = 0; pkt_len < large_pkt_len; ++raw_data)
+    {
+        large_packet[pkt_len++] = raw_data;
+    }
+    // Update IPv6 header
+    IPC_NE_SET_2B(large_packet + 4, large_pkt_len - 40);
+    // Update UDP header
+    IPC_NE_SET_2B(large_packet + header_len + 4, large_pkt_len - header_len);
+    checksum = 0x11 + IPC_NE_GET_2B(large_packet + header_len + 4);
+    for (offset = 8; offset < 40; offset += 2)
+    {
+        checksum += IPC_NE_GET_2B(header_v6 + offset);
+    }
+    checksum += IPC_NE_GET_2B(udp_header + 0) + IPC_NE_GET_2B(udp_header + 2) + IPC_NE_GET_2B(large_packet + header_len + 4);
+    for (offset = header_len + IPC_FRAG_TEST_REASM_UDP_LEN; offset < large_pkt_len; offset += 2)
+    {
+        checksum += IPC_NE_GET_2B(large_packet + offset);
+        while (checksum & 0xffff0000)
+        {
+            checksum = (checksum & 0xffff) + ((checksum & 0xffff0000) >> 16);
+        }
+    }
+    checksum = ((checksum == 0xffff) ? checksum : ~checksum) & 0xffff;
+    IPC_NE_SET_2B(large_packet + header_len + 6, checksum);
+
+    /* Large packet fragment */
+    frag_gpd_num = ipc_fragment_frag_v6(large_packet, pkt_len, &frag_gpd_head, &frag_gpd_tail, &frag_pkt_info);
+
+    /* IPv6 defragment */
+    ipc_fragment_reassemble_test_send2defrag(KAL_FALSE, frag_gpd_num, frag_gpd_head, frag_gpd_tail, &frag_pkt_info, quening_in_order);
+
+    /* Compare orignial packet with reassemabled packet */
+    cmp_result = ipc_fragment_reassemble_test_cmp_reasm_gpd(reasm_pkt_v6_gpd, large_packet);
+    ASSERT(cmp_result == KAL_TRUE);
+
+    qbmt_dest_q(reasm_pkt_v6_gpd, reasm_pkt_v6_gpd);
+}
+
+void ipc_fragment_ut_refilter(kal_uint8 ip_type, ipc_frag_refilter_info_t *info, qbm_gpd *p_head, qbm_gpd *p_tail)
+{
+    /* Assign reassembled packet into global variable, and test function will compare original data with reassembled packet */
+    ASSERT(p_head == p_tail);
+    if (ip_type == IPC_IP_TYPE_IPV4)
+    {
+        reasm_pkt_v4_gpd = p_head;
+    }
+    else
+    {
+        reasm_pkt_v6_gpd = p_head;
+    }
+}
+
+extern void ipc_fragment_mp_test();
+extern void ipc_fragment_efrag_reasm_en_test(kal_bool is_enable);
+void ipc_fragment_test()
+{
+    ipc_fragment_set_ipc_refilter_func_ptr(ipc_fragment_ut_refilter);
+    ipc_fragment_efrag_reasm_en_test(KAL_TRUE);
+
+    ipc_fragment_reset();
+    ipc_fragment_mp_test();
+
+    ipc_fragment_reset();
+    ipc_fragment_reassemble_test_v4(KAL_TRUE);
+
+    ipc_fragment_reset();
+    ipc_fragment_reassemble_test_v6(KAL_TRUE);
+
+    ipc_fragment_reset();
+    ipc_fragment_reassemble_test_v4(KAL_FALSE);
+
+    ipc_fragment_reset();
+    ipc_fragment_reassemble_test_v6(KAL_FALSE);
+
+    ipc_fragment_reset();
+    ipc_fragment_efrag_reasm_en_test(KAL_FALSE);
+    ipc_fragment_set_ipc_refilter_func_ptr(ipc_frag_refilter);
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_utility.c b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_utility.c
new file mode 100644
index 0000000..1e940ed
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_utility.c
@@ -0,0 +1,196 @@
+#include "ipc_fragment_utility.h"
+
+static void (*ipc_fragment_refiltering_func)(kal_uint8 ip_type, ipc_frag_refilter_info_t *info, qbm_gpd *p_head, qbm_gpd *p_tail);
+static ipc_fragment_t ipc_fragment_inst;
+
+static kal_uint8 ipc_frag_buffer[IPC_FRAG_AFM_BUFFER_SIZE];
+static kal_uint32 ipc_frag_sub_buffer_size[] = {sizeof(IpcFragPktMetaInfo),                    // Ipv4/v6 framgment pkt_info nodes
+                                                sizeof(IpcFragMnd6),                           // IPv4 and Ipv6 shared hash nodes
+                                                sizeof(void *) * IPC_FRAG_HASH_TABLE_BUCK_NUM, // IPv4/v6 Hash table
+                                                AFM_SUBPOOL_END_PATTERN};
+static kal_uint32 ipc_frag_sub_buffer_num[] = {IPC_FRAG_PKT_META_NODE_NUM, IPC_FRAG_HASH_NODE_NUM, 2, AFM_SUBPOOL_END_PATTERN};
+
+ipc_fragment_t *ipc_fragment_get_inst()
+{
+    return &ipc_fragment_inst;
+}
+
+void *ipc_fragment_mem_alloc(size_t size)
+{
+    return kal_afm_alloc(ipc_fragment_get_inst()->k_afm_id, size);
+}
+
+void ipc_fragment_mem_free(void *p)
+{
+    kal_afm_free(ipc_fragment_get_inst()->k_afm_id, p);
+}
+
+void ipc_fragment_afm_init()
+{
+    ipc_fragment_t *p = ipc_fragment_get_inst();
+
+    p->afm_buffer_p = ipc_frag_buffer;
+    p->afm_sub_buffer_size_p = ipc_frag_sub_buffer_size;
+    p->afm_sub_buffer_num_p = ipc_frag_sub_buffer_num;
+
+    p->k_afm_id = kal_afm_create(p->afm_buffer_p, IPC_FRAG_AFM_BUFFER_SIZE, p->afm_sub_buffer_size_p, p->afm_sub_buffer_num_p, 0x00, &(p->afm_left_mem_size));
+    ASSERT(p->k_afm_id);
+}
+
+void ipc_fragment_afm_deinit()
+{
+    static kal_uint32 ipc_fragment_afm_delete_fail_cnt = 0;
+    ipc_fragment_t *p = ipc_fragment_get_inst();
+
+    if (p->k_afm_id)
+    {
+        ipc_fragment_afm_delete_fail_cnt += kal_afm_delete(p->k_afm_id) == KAL_MEMORY_NOT_RELEASE;
+    }
+}
+
+void ipc_fragment_set_gpd_datalen(void *gpd, kal_uint32 datalen, void **payload_ptr)
+{
+    void *bd;
+
+    if (QBM_DES_GET_BDP(gpd))
+    {
+        bd = QBM_DES_GET_DATAPTR(gpd);
+        *payload_ptr = QBM_DES_GET_DATAPTR(bd);
+        QBM_DES_SET_DATALEN(bd, datalen);
+        qbm_cal_set_checksum(bd);
+    }
+    else
+    {
+        *payload_ptr = QBM_DES_GET_DATAPTR(gpd);
+    }
+
+    QBM_DES_SET_DATALEN(gpd, datalen);
+    qbm_cal_set_checksum(gpd);
+}
+
+kal_uint16 ipc_fragment_ipv4_cal_header_checksum(void *original_ip_header)
+{
+
+    kal_uint32 sum32 = 0;
+    kal_uint32 offset = 0;
+    kal_uint8 *ip_header = (kal_uint8 *)original_ip_header;
+    kal_uint32 ip_header_len;
+
+    ASSERT(original_ip_header);
+
+    ip_header_len = (IPC_NE_GET_1B(ip_header) & 0xf) << 2;
+
+    while (offset < ip_header_len)
+    {
+        sum32 += IPC_NE_GET_2B(ip_header + offset);
+        offset += 2;
+    }
+
+    sum32 -= IPC_NE_GET_2B(ip_header + 10);
+
+    while (sum32 & 0xffff0000)
+    {
+        sum32 = (sum32 & 0xffff) + ((sum32 & 0xffff0000) >> 16);
+    }
+
+    return ~sum32;
+}
+
+void ipc_fragment_refiltering_queued_packets(kal_uint8 ip_type, ipc_frag_refilter_info_t *info, qbm_gpd *p_head, qbm_gpd *p_tail)
+{
+    ipc_fragment_refiltering_func(ip_type, info, p_head, p_tail);
+}
+
+void ipc_fragment_set_ipc_refilter_func_ptr(void (*func)(kal_uint8 ip_type, ipc_frag_refilter_info_t *info, qbm_gpd *p_head, qbm_gpd *p_tail))
+{
+    ipc_fragment_refiltering_func = func;
+}
+
+kal_bool ipc_fragment_icmp4_send(kal_int32 type, kal_int32 code, void *payload)
+{
+    return KAL_TRUE;
+}
+
+kal_bool ipc_fragment_icmp6_send(kal_int32 type, kal_int32 code, void *payload)
+{
+    return KAL_TRUE;
+}
+
+void ipc_fragment_pktg_init(IpcFragPktGroupInfo *gif)
+{
+    gif->head_gpd = gif->tail_gpd = NULL;
+    gif->head_meta = gif->tail_meta = NULL;
+    gif->info_mask = gif->total_len = gif->accumulate_len = 0;
+    gif->filter_id = IPC_FRAG_INVALID_FILTER_ID;
+}
+
+void ipc_fragment_pktg_rel_gpd_list(IpcFragPktGroupInfo *gif)
+{
+    qbm_gpd *curr_gpd, *priv_gpd;
+    curr_gpd = gif->head_gpd;
+    while (curr_gpd)
+    {
+        priv_gpd = curr_gpd;
+        curr_gpd = QBM_DES_GET_NEXT(curr_gpd);
+        qbmt_dest_q(priv_gpd, priv_gpd);
+    }
+    gif->head_gpd = gif->tail_gpd = NULL;
+}
+
+void ipc_fragment_pktg_rel_meta_list(IpcFragPktGroupInfo *gif)
+{
+    IpcFragPktMetaInfo *curr_meta, *priv_meta;
+    curr_meta = gif->head_meta;
+    while (curr_meta)
+    {
+        priv_meta = curr_meta;
+        curr_meta = curr_meta->next;
+        ipc_fragment_mem_free(priv_meta);
+    }
+    gif->head_meta = gif->tail_meta = NULL;
+}
+
+kal_bool ipc_fragment_ipv4_l3eq(IpcFragIpv4L3Key *a, IpcFragIpv4L3Key *b)
+{
+    return a->src_addr == b->src_addr && a->dst_addr == b->dst_addr && a->ip_id == b->ip_id && a->protocol == b->protocol ? KAL_TRUE : KAL_FALSE;
+}
+
+kal_bool ipc_fragment_ipv6_l3eq(IpcFragIpv6L3Key *a, IpcFragIpv6L3Key *b)
+{
+    return a->src_addr[0] == b->src_addr[0] && a->src_addr[1] == b->src_addr[1] && a->src_addr[2] == b->src_addr[2] && a->src_addr[3] == b->src_addr[3] &&
+                   a->dst_addr[0] == b->dst_addr[0] && a->dst_addr[1] == b->dst_addr[1] && a->dst_addr[2] == b->dst_addr[2] && a->dst_addr[3] == b->dst_addr[3] &&
+                   a->ip_id == b->ip_id
+               ? KAL_TRUE
+               : KAL_FALSE;
+}
+
+kal_uint32 ipc_fragment_mf(void *pk, kal_uint32 ks)
+{
+    kal_uint32 a[4] = {0x014589cd, 0x2367abef, 0xf2d4c3e1, ks}, kv = 0;
+    kal_uint32 c[4] = {0, 0, 0, 0};
+    kal_uint32 ls = ks;
+    const kal_uint32 *k = (kal_uint32 *)pk;
+
+    while (ls > 0)
+    {
+        for (kal_uint8 i = 0; i < 4; ++i)
+        {
+            kv = 0;
+            if (ls >= 4)
+            {
+                kv = *k;
+                ls -= 4;
+            }
+            else
+            {
+                kal_mem_cpy(&kv, k, ls);
+                ls -= ls;
+            }
+            c[i] = 0xffffffff - a[i] < kv + c[(i + 3) % 4];
+            a[i] += kv + c[(i + 3) % 4];
+            ++k;
+        }
+    }
+
+    return a[0] ^ a[1] ^ a[2] ^ a[3];
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_utility.h b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_utility.h
new file mode 100644
index 0000000..5117f84
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_fragment/ipc_fragment_utility.h
@@ -0,0 +1,37 @@
+#ifndef _IPC_FRAGMENT_UTILITY_INC
+#define _IPC_FRAGMENT_UTILITY_INC
+
+#include "ipc_api.h"
+#include "ipc_fragment.h"
+#include "ipc_fragment_struct.h"
+
+#define IPC_ICMP4_TYPE_TIME_EXCEEDED 11
+#define IPC_ICMP4_CODE_FRAG_REASM_TIME_EXCEEDED 1
+#define IPC_ICMP6_TYPE_TIME_EXCEEDED 3
+#define IPC_ICMP6_TYPE_PARAMETER_PROBLEM 4
+#define IPC_ICMP6_CODE_FRAG_REASM_TIME_EXCEEDED 1
+#define IPC_ICMP6_CODE_ERR_HDR_FIELD_ENCOUNTERED 0
+
+ipc_fragment_t *ipc_fragment_get_inst();
+void *ipc_fragment_mem_alloc(size_t size);
+void ipc_fragment_mem_free(void *p);
+void ipc_fragment_afm_init();
+void ipc_fragment_afm_deinit();
+
+void ipc_fragment_set_gpd_datalen(void *gpd, kal_uint32 datalen, void **payload_ptr);
+kal_uint16 ipc_fragment_ipv4_cal_header_checksum(void *original_ip_header);
+void ipc_fragment_refiltering_queued_packets(kal_uint8 ip_type, ipc_frag_refilter_info_t *info, qbm_gpd *p_head, qbm_gpd *p_tail);
+void ipc_fragment_set_ipc_refilter_func_ptr(void (*func)(kal_uint8 ip_type, ipc_frag_refilter_info_t *info, qbm_gpd *p_head, qbm_gpd *p_tail));
+kal_bool ipc_fragment_icmp4_send(kal_int32 type, kal_int32 code, void *payload);
+kal_bool ipc_fragment_icmp6_send(kal_int32 type, kal_int32 code, void *payload);
+
+void ipc_fragment_pktg_rel_gpd_list(IpcFragPktGroupInfo *gif);
+void ipc_fragment_pktg_rel_meta_list(IpcFragPktGroupInfo *gif);
+void ipc_fragment_pktg_init(IpcFragPktGroupInfo *gif);
+kal_bool ipc_fragment_ipv4_l3eq(IpcFragIpv4L3Key *a, IpcFragIpv4L3Key *b);
+kal_bool ipc_fragment_ipv6_l3eq(IpcFragIpv6L3Key *a, IpcFragIpv6L3Key *b);
+kal_uint32 ipc_fragment_mf(void *pk, kal_uint32 ks);
+
+kal_bool ipc_fragment_reassemble(kal_bool is_v4, qbm_gpd **reasm_gpd, IpcFragPktGroupInfo *pkt_grp_info);
+
+#endif /* _IPC_FRAGMENT_INC */
\ No newline at end of file
diff --git a/mcu/middleware/hif/ipcore/src/ipc_if.c b/mcu/middleware/hif/ipcore/src/ipc_if.c
new file mode 100644
index 0000000..a1a0a11
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_if.c
@@ -0,0 +1,3875 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_if.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IP Core public interface implementation.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_api.h"
+#include "sysservice_msgid.h"
+#include "em_struct.h"
+#include "em_msgid.h"
+#include "intrCtrl.h"
+#include "mw_sap.h"
+#include "ps_public_enum.h"
+#include "l4_msgid.h"
+#include "l4c_ipcore_struct.h"
+
+#include "upcm.h"
+#include "ipcore_upcm_struct.h"
+#include "upcm_msgid.h"
+#if defined(__LTM_SIMULATION_SUPPORT__)
+    #include "lms_api.h"
+#endif
+#include "qmu_bm.h"
+#include "qmu_bm_size.h"
+#include "qmu_bm_util.h"
+
+#include "nmu.h"
+#include "nmu_util.h"
+#include "hmu.h"
+
+#ifdef __ESL_COSIM_HIF__
+    #include "hif_esl_common.h"
+#endif
+
+#include "tcpip_rsra_proxy_public_apis.h"
+
+#include "ccci_ipc_msgid.h"
+#include "hif_mw_msgid.h"
+#include "dispatcher_msgid.h"
+#include "pfm_api.h"
+
+#include "ipc_dpfm.h"
+#include "ipc_api.h"
+#include "ipc_defs.h"
+#include "ipc_debug.h"
+#include "ipc_utils.h"
+#include "ipc_filter.h"
+#include "ipc_dhcp_adp.h"
+#include "ipc_notify.h"
+#include "ipc_data.h"
+
+#include "rsra_public.h"
+
+#if defined (__HIF_CCCI_SUPPORT__)
+#include "ccci_if.h"
+#endif
+
+#if !defined(__MTK_TARGET__) && defined(_MSC_VER) && (_MSC_VER >= 1500)
+#pragma warning( disable : 4100 )
+#endif
+
+#if defined(__IPF_SUPPORT__)
+#include "ipc_data_ipf.h"
+#endif
+
+#define IPC_IPV4_FORMAT_NUM 4
+#define IPC_IPV6_FORMAT_NUM 16
+#define IPC_IP_MAX_LENGTH   4
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+kal_spinlockid ipc_spinlock_g = NULL;
+kal_spinlockid g_ul_spinlock = NULL;
+static volatile kal_bool ipc_in_reset_s = KAL_FALSE;
+/*------------------------------------------------------------------------------
+ * Private functions.
+ *----------------------------------------------------------------------------*/
+
+void ipc_on_lte_tick_source(kal_bool is_lte_tick)
+{
+    if (is_lte_tick) {
+        hmu_switch_hif_timer(HMU_TIMER_SOURCE_DSP);
+    } else {
+        hmu_switch_hif_timer(HMU_TIMER_SOURCE_SYS);
+    }
+}
+
+static ipc_netif_type_e ipc_get_netif_type_by_apn_type(kal_uint32 apn_type)
+{
+    switch (apn_type) {
+        case DDM_APN_TYPE_DEFAULT:
+            return IPC_NETIF_TYPE_NORMAL;
+        case DDM_APN_TYPE_IMS:
+        case DDM_APN_TYPE_EMERGENCY:
+        case DDM_APN_TYPE_XCAP:
+            return IPC_NETIF_TYPE_LATENCY_CONCERN;
+        default:
+            return IPC_NETIF_TYPE_NORMAL;
+    }
+}
+
+static void ipc_config_pdn_info_ipv4(ipc_session_t *session,
+                                     kal_uint32 session_ip_id,
+                                     ip_addr_struct *ip_addr,
+                                     dns_struct *dns,
+                                     kal_uint32 netif_id,
+                                     kal_uint32 netif_features,
+                                     kal_bool *trigger_linkup)
+{
+    kal_uint32 input_dns_idx;
+    kal_uint32 total_dns_cnt;
+    kal_char dns_ip_v4[IPC_IPV4_FORMAT_NUM][IPC_IP_MAX_LENGTH] = {0}; /*< used for save ip string */
+    kal_char ip_v4[IPC_IPV4_FORMAT_NUM][IPC_IP_MAX_LENGTH] = {0};     /*< used for save ip string */
+    kal_uint8 i = 0;
+
+    /* Configure IPv4 address */
+    IPC_ASSERT((IPV4_ADDR_TYPE == ip_addr->ip_addr_type) || (IPV4V6_ADDR_TYPE == ip_addr->ip_addr_type));
+
+    /* Set IPv4 information into nmu */
+    total_dns_cnt = 0;
+    for (input_dns_idx = 0; input_dns_idx < NUM_OF_DNS_ADDR; input_dns_idx++) {
+        if (KAL_TRUE == dns->v4[input_dns_idx].is_dnsv4_present) {
+            for (i = 0; i < IPC_IPV4_FORMAT_NUM; i++) {
+                /* ex: "192.168.1.1" save as 4 string "ip_v4[0], ip_v4[1], ip_v4[2], ip_v4[3]" */
+                if (0 > kal_snprintf(dns_ip_v4[i], IPC_IP_MAX_LENGTH, "%d", dns->v4[input_dns_idx].dnsv4[i])) {
+                    /* no log */
+                }
+            }
+
+            hif_trace_debug(IPC_TR_SESSION_BINDING_CFG_IPV4_DNS_USIR, session_ip_id, total_dns_cnt, dns_ip_v4[0], dns_ip_v4[1], dns_ip_v4[2], dns_ip_v4[3]);
+            nmu_set_ip4_dns(session_ip_id, total_dns_cnt, dns->v4[input_dns_idx].dnsv4);
+            total_dns_cnt++;
+        }
+    }
+    hif_trace_info(IPC_TR_SESSION_BINDING_CFG_IPV4_DNS_NUM, total_dns_cnt, session_ip_id);
+    nmu_set_ip4_dns_num(session_ip_id, total_dns_cnt);
+
+    for (i = 0; i < IPC_IPV4_FORMAT_NUM; i++) {
+        if (0 > kal_snprintf(ip_v4[i], IPC_IP_MAX_LENGTH, "%d", ip_addr->ipv4[i])) {
+            /* no log */
+        }
+    }
+    hif_trace_debug(IPC_TR_SESSION_BINDING_CFG_IPV4_ADDR_USIR, session_ip_id, ip_v4[0], ip_v4[1], ip_v4[2], ip_v4[3]);
+    nmu_set_ip4_ip(session_ip_id, ip_addr->ipv4);
+
+    hif_trace_debug(IPC_TR_SESSION_BINDING_CFG_IPV4_FAKE_INFO_USIR, session_ip_id, ip_v4[0], ip_v4[1], ip_v4[2], ip_v4[3]);
+    nmu_set_ip4_fake_mask_and_gateway(session_ip_id, ip_addr->ipv4);
+
+    if (IPC_IS_V4_UNSPECIFIED_ADDR(ip_addr->ipv4)) { /* IPv4 information is not complete in control path */
+
+        /* set IPv4 down */
+        hif_trace_info(IPC_TR_SESSION_BINDING_CFG_IPV4_DOWN, session_ip_id);
+        nmu_set_ip4_down(session_ip_id);
+
+        /* Trigger DHCPv4 client if needed */
+        if (netif_features & IPC_F_DHCP4C) { /* enable DHCPv4 if necessary */
+            hif_trace_info(IPC_TR_SESSION_BINDING_DHCP4C, netif_id, netif_features);
+            ipc_enable_dhcp4c(session);
+
+            /* Stop triggering link up if DHCPv4 client is enabled */
+            *trigger_linkup = KAL_FALSE;
+        }
+    } else { /* IPv4 information is complete, set IPv4 up */
+        hif_trace_info(IPC_TR_SESSION_BINDING_CFG_IPV4_UP, session_ip_id);
+        nmu_set_ip4_up(session_ip_id);
+    }
+}
+
+static void ipc_config_pdn_info_ipv6(kal_uint32 session_ip_id,
+                                     ip_addr_struct *ip_addr,
+                                     dns_struct *dns)
+{
+    kal_uint32 input_dns_idx = 0;
+    kal_uint32 total_dns_cnt = 0;
+    kal_char dns_ip_v6[IPC_IPV6_FORMAT_NUM][IPC_IP_MAX_LENGTH] = {0}; /*< used for save ip string */
+    kal_char ip_v6[IPC_IPV6_FORMAT_NUM][IPC_IP_MAX_LENGTH] = {0};     /*< used for save ip string */
+    kal_uint8 i = 0;
+
+    /*
+     * Configure IPv6 address
+     * Always only configure network interface identifier /64
+     */
+    IPC_ASSERT((IPV6_ADDR_TYPE == ip_addr->ip_addr_type) || (IPV4V6_ADDR_TYPE == ip_addr->ip_addr_type));
+
+    /* Set IPv6 information into nmu */
+    total_dns_cnt = 0;
+    for (input_dns_idx = 0; input_dns_idx < NUM_OF_DNS_ADDR; input_dns_idx++) {
+        if (KAL_TRUE == dns->v6[input_dns_idx].is_dnsv6_present) {
+            for (i = 0; i < IPC_IPV6_FORMAT_NUM; i++) {
+                /* ex: "fe80:..." save as 16 string "ip_v6[0], ip_v6[1], ip_v6[2], ip_v6[3]..." */
+                if (0 > kal_snprintf(dns_ip_v6[i], IPC_IP_MAX_LENGTH, "%d", dns->v6[input_dns_idx].dnsv6[i])) {
+                    /* no log */
+                }
+            }
+            hif_trace_debug(IPC_TR_SESSION_BINDING_CFG_IPV6_DNS_USIR, session_ip_id, total_dns_cnt, dns_ip_v6[0], dns_ip_v6[1], dns_ip_v6[2], dns_ip_v6[3],
+                                                                                                    dns_ip_v6[4], dns_ip_v6[5], dns_ip_v6[6], dns_ip_v6[7],
+                                                                                                    dns_ip_v6[8], dns_ip_v6[9], dns_ip_v6[10], dns_ip_v6[11],
+                                                                                                    dns_ip_v6[12], dns_ip_v6[13], dns_ip_v6[14], dns_ip_v6[15]);
+            nmu_set_ip6_dns(session_ip_id, total_dns_cnt, dns->v6[input_dns_idx].dnsv6);
+            total_dns_cnt++;
+        }
+    }
+    hif_trace_info(IPC_TR_SESSION_BINDING_CFG_IPV6_DNS_NUM, total_dns_cnt, session_ip_id);
+    nmu_set_ip6_dns_num(session_ip_id, total_dns_cnt);
+
+    if (IPC_IS_V6_UNSPECIFIED_ADDR(ip_addr->ipv6)) {
+        hif_trace_info(IPC_TR_SESSION_BINDING_CFG_IPV6_ZERO_IID_LEN, session_ip_id);
+        nmu_set_ip6_iid_len(session_ip_id, 0);
+
+        hif_trace_info(IPC_TR_SESSION_BINDING_CFG_IPV6_DOWN, session_ip_id);
+        nmu_set_ip6_down(session_ip_id);
+    } else {
+        for (i = 0; i < IPC_IPV6_FORMAT_NUM; i++) {
+            if (0 > kal_snprintf(ip_v6[i], IPC_IP_MAX_LENGTH, "%d", ip_addr->ipv6[i])) {
+                /* no log */
+            }
+        }
+        hif_trace_debug(IPC_TR_SESSION_BINDING_CFG_IPV6_IID_USIR, session_ip_id, IPV6_VALID_IID_BITS, ip_v6[0], ip_v6[1], ip_v6[2], ip_v6[3],
+                                                                                                      ip_v6[4], ip_v6[5], ip_v6[6], ip_v6[7],
+                                                                                                      ip_v6[8], ip_v6[9], ip_v6[10], ip_v6[11],
+                                                                                                      ip_v6[12], ip_v6[13], ip_v6[14], ip_v6[15]);
+        nmu_set_ip6_iid(session_ip_id, ip_addr->ipv6);
+        nmu_set_ip6_iid_len(session_ip_id, IPV6_VALID_IID_BITS);
+
+        hif_trace_info(IPC_TR_SESSION_BINDING_CFG_IPV6_UP, session_ip_id);
+        nmu_set_ip6_up(session_ip_id);
+    }
+}
+
+void ipc_on_pdn_bind_bot(module_type src_mod_id,
+                         kal_uint32 netif_features,
+                         local_para_struct *local_para_ptr,
+                         ps_cause_enum result)
+{
+    ipcore_upcm_pdn_bind_ind_struct *param = (ipcore_upcm_pdn_bind_ind_struct *) local_para_ptr;
+    ipc_session_t *session;
+    kal_uint32 session_ip_id;
+    kal_uint8 ip_type = IPC_IP_TYPE_INVALID;
+    kal_bool trigger_linkup;
+    module_type dst_mod_id = src_mod_id;
+    msg_type msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_RSP;
+
+    if (HIF_IPC_OK == result) {
+        session = ipc_find_session_by_context(param->pdn_id);
+        if (session) {
+            session_ip_id = session->ip_id;
+            ip_type = session->type;
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+            ipc_update_session_state(session, IPC_SESSION_STATE_BIND);
+
+            hif_trace_info(IPC_TR_SESSION_BINDING_CFG_IP_INFO, param->network_interface_id, param->pdn_id, param->ip_addr.ip_addr_type, session_ip_id);
+
+            trigger_linkup = KAL_TRUE;
+
+            /*
+             *  Configure IPv6 address
+             *  Always only configure network interface identifier /64
+             */
+            if (IPC_IP_TYPE_IPV6 == ip_type || IPC_IP_TYPE_MIXED == ip_type) {
+                ipc_config_pdn_info_ipv6(session_ip_id, &(param->ip_addr), &(param->dns));
+            }
+
+            /*
+             *  Configure IPv4 address
+             */
+            if (IPC_IP_TYPE_IPV4 == ip_type || IPC_IP_TYPE_MIXED == ip_type) {
+                ipc_config_pdn_info_ipv4(session, session_ip_id, &(param->ip_addr), &(param->dns), param->network_interface_id, netif_features, &trigger_linkup);
+            }
+
+            if (KAL_TRUE == trigger_linkup) {
+                ipc_update_session_state(session, IPC_SESSION_STATE_PRE_LINKUP);
+            }
+        } else {
+            hif_trace_error(IPC_TR_SESSION_BIND_SESSION_RLOCK_FAIL, param->network_interface_id, param->pdn_id);
+            result = HIF_IPC_PDN_BIND_RSP_SESSION_RLOCK_FAIL;
+        }
+    }else{
+        if(HIF_IPC_PDN_BIND_RSP_INVALID_NETIF == result){
+            session = ipc_find_session_by_context(param->pdn_id);
+            if(session){
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                ipc_update_session_state(session, IPC_SESSION_STATE_UNBIND);
+                ipc_del_session(session);
+                hif_trace_error(IPC_TR_SESSION_BIND_DYNAMIC_Q_ERROR, param->network_interface_id, param->pdn_id);
+            }
+        }
+    }
+
+    hif_trace_info(IPC_TR_SESSION_BINDING_RESULT, result);
+    if (MOD_NIL != src_mod_id) {
+        ipcore_upcm_pdn_bind_rsp_struct *rsp_msg_p;
+
+        rsp_msg_p = (ipcore_upcm_pdn_bind_rsp_struct *) construct_local_para(sizeof(ipcore_upcm_pdn_bind_rsp_struct), TD_RESET);
+        IPC_ASSERT(rsp_msg_p);
+
+        /* Sync to HW */
+#if defined(__IPF_SUPPORT__)
+        if (HIF_IPC_OK == result) {
+            ipc_update_pn_match_setting(param->pdn_id, param->network_interface_id, ip_type, IPC_IPF_PN_MATCH_BIND);
+        }
+#endif
+        /* Fill response from indication structure */
+        if (param) {
+            hif_trace_info(IPC_TR_SESSION_BINDING_RSP_PARAM_GEN, param->network_interface_id, param->pdn_id, sizeof(ip_addr_struct), sizeof(dns_struct), sizeof(upcm_ipcore_back_info_t));
+
+            rsp_msg_p->network_interface_id = param->network_interface_id;
+            /*
+             * 2016/4/28 Peter.Hsu
+             * The MSB of pdn id is used as sim idx in IPCore internal design for Multiple PS feature.
+             * Therefore, we mask out the MSB before sent the pdn id information to other module.
+             */
+            rsp_msg_p->pdn_id = IPC_UNMASK_PROTOID_FROM_PDNID(param->pdn_id);
+            kal_mem_cpy(&(rsp_msg_p->ip_addr), &(param->ip_addr), sizeof(ip_addr_struct));
+            kal_mem_cpy(&(rsp_msg_p->dns), &(param->dns), sizeof(dns_struct));
+            kal_mem_cpy(&(rsp_msg_p->back_info), &(param->back_info), sizeof(upcm_ipcore_back_info_t));
+        }
+
+        /* Fill result */
+        rsp_msg_p->result = result;
+        hif_trace_info(IPC_TR_SESSION_BINDING_RSP, result, src_mod_id);
+
+#ifdef ATEST_SYS_IPCORE
+        ipc_ut_msg_send6(MOD_IPCORE,
+                         src_mod_id,
+                         IPCORE_SAP,
+                         MSG_ID_IPCORE_UPCM_PDN_BIND_RSP,
+                         (local_para_struct*)rsp_msg_p,
+                         NULL);
+#else
+
+#ifdef __LTM_SIMULATION_SUPPORT__
+        dst_mod_id = MOD_LTM_SIM;
+#endif
+
+#ifdef __DISPATCHER_SUPPORT__
+        if ((src_mod_id >= MOD_DISPATCHER) && (src_mod_id <= MOD_DISPATCHER + MAX_SIM_NUM)) {
+            /* DISPATCHER */
+            msg_id = MSG_ID_IPCORE_DISPATCHER_PDN_BIND_RSP;
+        }
+#endif
+
+        msg_send6(MOD_IPCORE, dst_mod_id, IPCORE_SAP, msg_id, (local_para_struct*)rsp_msg_p, NULL);
+#endif
+    }
+}
+
+void ipc_on_pdn_bind_top(module_type src_mod_id,
+                         local_para_struct *local_para_ptr)
+{
+    ipcore_upcm_pdn_bind_ind_struct *param = (ipcore_upcm_pdn_bind_ind_struct *) local_para_ptr;
+    ipc_netif_t *netif;
+    ipc_session_t *session;
+    kal_uint32 features = 0;
+    void *netif_cbk_context;
+    module_type netif_module_id;
+    ipc_netif_type_e netif_type = IPC_NETIF_TYPE_NORMAL;
+    kal_uint8 ip_type;
+    ps_cause_enum result;
+    ilm_struct ilm = {0};
+
+    result = HIF_IPC_OK;
+
+    hif_trace_info(IPC_TR_SESSION_BINDING_START);
+
+    if (param) {
+        IPC_ASSERT(local_para_ptr->msg_len == sizeof(ipcore_upcm_pdn_bind_ind_struct));
+        hif_trace_info(IPC_TR_SESSION_BINDING_INFO, param->network_interface_id, param->pdn_id, param->ip_addr.ip_addr_type);
+
+        switch (param->ip_addr.ip_addr_type) {
+            case IPV4_ADDR_TYPE:
+                ip_type = IPC_IP_TYPE_IPV4;
+                break;
+            case IPV6_ADDR_TYPE:
+                ip_type = IPC_IP_TYPE_IPV6;
+                break;
+            case IPV4V6_ADDR_TYPE:
+                ip_type = IPC_IP_TYPE_MIXED;
+                break;
+            default:
+                hif_trace_error(IPC_TR_SESSION_BIND_UNSUPPORTED_IP_ADDR_TYPE, param->ip_addr.ip_addr_type, param->pdn_id);
+                result = HIF_IPC_PDN_BIND_RSP_UNSUPPORTED_IP_ADDR_TYPE;
+                goto rsp;
+        }
+
+        netif = ipc_find_netif(param->network_interface_id);
+        if (netif) {
+            session = ipc_new_session(netif, param->pdn_id, ip_type, IPC_SESSION_STATE_PRE_BIND);
+            features = netif->config.features;
+            netif_cbk_context = netif->config.callback_context;
+            netif_module_id = netif->config.module_id;
+            if (session) {
+                netif_type = ipc_get_netif_type_by_apn_type(param->apn_type_info.apn_type_activate);
+                if (IPC_NETIF_TYPE_LATENCY_CONCERN == netif_type) {
+                    IPC_R_TO_W_LOCK_OBJECT(netif, ipc_spinlock_g);
+                    netif->config.features |= IPC_F_LATENCY_CONCERN;
+                    IPC_W_TO_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+                }
+            }
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+            if (session) {
+                /*
+                 * Send netif type to LHIF for dynamic queue mapping.
+                 */
+                if (features & IPC_F_DYNAMIC_Q_MAPPING) {
+                    ipc_lhifcore_q_mapping_msg_t *req_msg_p;
+
+                    req_msg_p = (ipc_lhifcore_q_mapping_msg_t *) construct_local_para(sizeof(ipc_lhifcore_q_mapping_msg_t), TD_RESET);
+                    IPC_ASSERT(req_msg_p);
+
+                    /* Fill request from indication structure */
+                    kal_mem_cpy(&(req_msg_p->bind_ind), param, sizeof(ipcore_upcm_pdn_bind_ind_struct));
+
+                    req_msg_p->netif_features = features;
+                    req_msg_p->callback_context = netif_cbk_context;
+                    req_msg_p->bind_src_mod_id = src_mod_id;
+                    req_msg_p->netif_type = netif_type;
+
+                    ilm.src_mod_id = MOD_IPCORE;
+                    ilm.dest_mod_id = netif_module_id;
+                    ilm.sap_id = IPCORE_SAP;
+                    ilm.msg_id = MSG_ID_IPCORE_LHIFCORE_QUEUE_MAPPING_REQ;
+                    ilm.local_para_ptr = (local_para_struct *)req_msg_p;
+                    ilm.peer_buff_ptr = NULL;
+
+                    msg_send_ext_queue(&ilm);
+                    return;
+                }
+            } else {
+                hif_trace_error(IPC_TR_SESSION_BIND_NEW_SESSION_FAIL, param->network_interface_id, param->pdn_id, ip_type);
+                result = HIF_IPC_PDN_BIND_RSP_NEW_SESSION_FAIL;
+            }
+        } else {
+            hif_trace_error(IPC_TR_SESSION_BIND_INVALID_NETIF, param->network_interface_id);
+            result = HIF_IPC_PDN_BIND_RSP_INVALID_NETIF;
+        }
+    } else {
+        hif_trace_error(IPC_TR_SESSION_BIND_NULL_PARAM);
+        result = HIF_IPC_PDN_BIND_RSP_NULL_PARAM;
+    }
+
+    rsp : ipc_on_pdn_bind_bot(src_mod_id, features, local_para_ptr, result);
+}
+
+void ipc_on_pdn_unbind(local_para_struct *local_para_ptr)
+{
+    ipcore_upcm_pdn_unbind_ind_struct *param = (ipcore_upcm_pdn_unbind_ind_struct *) local_para_ptr;
+    ipc_session_t *session;
+    kal_uint32 session_ip_id;
+    kal_uint8 session_type;
+
+    if (param) {
+        IPC_ASSERT(local_para_ptr->msg_len == sizeof(ipcore_upcm_pdn_unbind_ind_struct));
+        hif_trace_info(IPC_TR_SESSION_DEACTIVATING, param->pdn_id);
+
+        session = ipc_find_session_by_context(param->pdn_id);
+        if (session) {
+            session_ip_id = session->ip_id;
+            session_type = session->type;
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+            if (IPC_IP_TYPE_IPV6 == session_type || IPC_IP_TYPE_MIXED == session_type) {
+                nmu_set_ip6_dns_num(session_ip_id, 0);
+                nmu_set_ip6_down(session_ip_id);
+            }
+            if (IPC_IP_TYPE_IPV4 == session_type || IPC_IP_TYPE_MIXED == session_type) {
+                nmu_set_ip4_dns_num(session_ip_id, 0);
+                nmu_set_ip4_down(session_ip_id);
+            }
+
+            ipc_disable_dhcp4c(session); /* disable DHCPv4 it's been enabled */
+            ipc_update_session_state(session, IPC_SESSION_STATE_UNBIND);
+            ipc_del_session(session);
+
+            /* Sync to HW */
+#if defined(__IPF_SUPPORT__)
+            ipc_update_pn_match_setting(param->pdn_id, IPC_INVALID_NETIF_ID, session_type, IPC_IPF_PN_MATCH_UNBIND);
+#endif
+
+#if (CUR_GEN >= MD_GEN95)
+            /* Discard Packets which are already in IPCore's internal queue */
+            ipc_data_drop_ul_meta_by_pdn(param->pdn_id);
+#endif
+        /* Reset data usage of pdn_id on Unbind */
+        ipc_reset_data_usage_by_pdn_sim_id(param->pdn_id);
+
+        } else {
+            hif_trace_error(IPC_TR_SESSION_DEACTIVATE_NO_SESSION_FOUND, param->pdn_id);
+            ipc_ut_set_error(IPC_UT_SESSION_DEACTIVATE_NO_SESSION_FOUND);
+        }
+    } else {
+        hif_trace_error(IPC_TR_SESSION_DEACTIVATE_NULL_PARAM);
+    }
+}
+
+static void ipc_on_pdn_rebind(module_type src_mod_id,
+                              local_para_struct *local_para_ptr)
+{
+    ipcore_upcm_pdn_rebind_ind_struct *param = (ipcore_upcm_pdn_rebind_ind_struct *) local_para_ptr;
+    ipc_session_t *session;
+    ipc_netif_t *netif;
+    kal_uint32 session_ip_id;
+    kal_uint8 old_session_type;
+    kal_uint8 old_ipv4_addr[4];
+    kal_uint8 old_ipv6_addr[16];
+    kal_uint8 new_session_type = IPC_IP_TYPE_INVALID;
+    kal_uint32 netif_features;
+    kal_bool trigger_linkup = KAL_TRUE;
+    ps_cause_enum result = HIF_IPC_OK;
+
+    if (param) {
+        IPC_ASSERT(local_para_ptr->msg_len == sizeof(ipcore_upcm_pdn_rebind_ind_struct));
+        hif_trace_info(IPC_TR_SESSION_REBINDING_INFO, param->network_interface_id, param->old_pdn_id, param->new_pdn_id, param->ip_addr.ip_addr_type);
+
+        switch (param->ip_addr.ip_addr_type) {
+            case IPV4_ADDR_TYPE:
+                new_session_type = IPC_IP_TYPE_IPV4;
+                break;
+            case IPV6_ADDR_TYPE:
+                new_session_type = IPC_IP_TYPE_IPV6;
+                break;
+            case IPV4V6_ADDR_TYPE:
+                new_session_type = IPC_IP_TYPE_MIXED;
+                break;
+            default:
+                hif_trace_error(IPC_TR_SESSION_REBIND_UNSUPPORTED_IP_ADDR_TYPE, param->ip_addr.ip_addr_type, param->new_pdn_id);
+                result = HIF_IPC_PDN_BIND_RSP_UNSUPPORTED_IP_ADDR_TYPE;
+                goto rsp;
+        }
+
+        netif = ipc_find_netif(param->network_interface_id);
+        if (netif) {
+            netif_features = netif->config.features;
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+            session = ipc_find_session_by_context((kal_uint8)(param->old_pdn_id));
+            if (session) {
+                session_ip_id = session->ip_id;
+                old_session_type = session->type;
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+                session = ipc_replace_session(netif, session, param->new_pdn_id, new_session_type, IPC_SESSION_STATE_LINKUP);
+                if (session) {
+                    if (IPC_IP_TYPE_IPV6 == old_session_type || IPC_IP_TYPE_MIXED == old_session_type) {
+                        if (IPC_IP_TYPE_IPV6 == new_session_type || IPC_IP_TYPE_MIXED == new_session_type) {
+                            nmu_get_ip6_iid(session_ip_id, &old_ipv6_addr);
+                            if (0 != kal_mem_cmp(param->ip_addr.ipv6, &old_ipv6_addr, sizeof(old_ipv6_addr))) {
+                                /*
+                                 * IPv6 addr has been changed.
+                                 * Update addr/dns to nmu.
+                                 */
+                                /* Delete old info */
+                                nmu_set_ip6_dns_num(session_ip_id, 0);
+                                nmu_set_ip6_down(session_ip_id);
+
+                                ipc_update_session_state(session, IPC_SESSION_STATE_IP_REVOKE);
+
+                                /* Update new info */
+                                ipc_config_pdn_info_ipv6(session_ip_id, &(param->ip_addr), &(param->dns));
+
+                                ipc_update_session_state(session, IPC_SESSION_STATE_LINKUP);
+                            }
+                        } else {
+                            /* Delete old info */
+                            nmu_set_ip6_dns_num(session_ip_id, 0);
+                            nmu_set_ip6_down(session_ip_id);
+                        }
+                    }
+
+                    if (IPC_IP_TYPE_IPV4 == old_session_type || IPC_IP_TYPE_MIXED == old_session_type) {
+                        if (IPC_IP_TYPE_IPV4 == new_session_type || IPC_IP_TYPE_MIXED == new_session_type) {
+                            nmu_get_ip4_ip(session_ip_id, &old_ipv4_addr);
+                            if (0 != kal_mem_cmp(param->ip_addr.ipv4, &old_ipv4_addr, sizeof(old_ipv4_addr))) {
+                                /*
+                                 * IPv4 addr has been changed.
+                                 * Update addr/dns to nmu.
+                                 */
+                                /* Delete old info */
+                                nmu_set_ip4_dns_num(session_ip_id, 0);
+                                nmu_set_ip4_down(session_ip_id);
+                                ipc_disable_dhcp4c(session); /* disable DHCPv4 it's been enabled */
+
+                                ipc_update_session_state(session, IPC_SESSION_STATE_IP_REVOKE);
+
+                                /* Update new info */
+                                ipc_config_pdn_info_ipv4(session, session_ip_id, &(param->ip_addr), &(param->dns), param->network_interface_id, netif_features, &trigger_linkup);
+
+                                ipc_update_session_state(session, IPC_SESSION_STATE_LINKUP);
+                            }
+                        } else {
+                            /* Delete old info */
+                            nmu_set_ip4_dns_num(session_ip_id, 0);
+                            nmu_set_ip4_down(session_ip_id);
+                            ipc_disable_dhcp4c(session); /* disable DHCPv4 it's been enabled */
+                        }
+                    }
+                } else {
+                    hif_trace_error(IPC_TR_SESSION_REBIND_REPLACE_SESSION_FAIL, param->network_interface_id, param->old_pdn_id, param->new_pdn_id);
+                    result = HIF_IPC_PDN_BIND_RSP_NEW_SESSION_FAIL;
+                }
+            } else {
+                hif_trace_error(IPC_TR_SESSION_REBIND_SESSION_RLOCK_FAIL, param->network_interface_id, param->old_pdn_id);
+                result = HIF_IPC_PDN_BIND_RSP_SESSION_RLOCK_FAIL;
+            }
+        } else {
+            hif_trace_error(IPC_TR_SESSION_REBIND_INVALID_NETIF, param->network_interface_id);
+            result = HIF_IPC_PDN_BIND_RSP_INVALID_NETIF;
+        }
+    } else {
+        hif_trace_error(IPC_TR_SESSION_DEACTIVATE_NULL_PARAM);
+        result = HIF_IPC_PDN_BIND_RSP_NULL_PARAM;
+    }
+
+rsp :
+    hif_trace_info(IPC_TR_SESSION_REBINDING_RESULT, result);
+    if (MOD_NIL != src_mod_id) {
+        ipcore_upcm_pdn_rebind_rsp_struct *rsp_msg_p = NULL;
+
+        rsp_msg_p = (ipcore_upcm_pdn_rebind_rsp_struct *) construct_local_para(sizeof(ipcore_upcm_pdn_rebind_rsp_struct), TD_RESET);
+        IPC_ASSERT(rsp_msg_p);
+
+        /* Sync to HW */
+#if defined(__IPF_SUPPORT__)
+        if (HIF_IPC_OK == result) {
+            /* Clear old pn_match_setting */
+            ipc_update_pn_match_setting(param->old_pdn_id, IPC_INVALID_NETIF_ID, old_session_type, IPC_IPF_PN_MATCH_UNBIND);
+            /* Update new pn_match_setting */
+            ipc_update_pn_match_setting(param->new_pdn_id, param->network_interface_id, new_session_type, IPC_IPF_PN_MATCH_BIND);
+        }
+#endif
+
+        /* Reset data usage of old pdn_id on PDN Rebind */
+        if (HIF_IPC_OK == result) {
+            ipc_reset_data_usage_by_pdn_sim_id(param->old_pdn_id);
+        }
+
+        /* Fill response from indication structure */
+        if (param) {
+            hif_trace_info(IPC_TR_SESSION_REBINDING_RSP_PARAM_GEN, param->network_interface_id, param->old_pdn_id, param->new_pdn_id, sizeof(ip_addr_struct), sizeof(dns_struct), sizeof(upcm_ipcore_back_info_t));
+
+            rsp_msg_p->network_interface_id = param->network_interface_id;
+            rsp_msg_p->old_pdn_id = IPC_UNMASK_PROTOID_FROM_PDNID(param->old_pdn_id);
+            rsp_msg_p->new_pdn_id = IPC_UNMASK_PROTOID_FROM_PDNID(param->new_pdn_id);
+            kal_mem_cpy(&(rsp_msg_p->ip_addr), &(param->ip_addr), sizeof(ip_addr_struct));
+            kal_mem_cpy(&(rsp_msg_p->dns), &(param->dns), sizeof(dns_struct));
+        }
+
+        /* Fill result */
+        rsp_msg_p->result = result;
+
+        hif_trace_info(IPC_TR_SESSION_REBINDING_RSP, result, src_mod_id);
+        msg_send6(IPCORE_SRC_MOD, REBIND_DST_MOD, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_REBIND_RSP, (local_para_struct*)rsp_msg_p, NULL);
+    }
+}
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+void ipc_bind_lan_netif(kal_uint32 netif_id_1, kal_uint32 netif_id_2)
+{
+    ipc_netif_t                 *netif_1, *netif_2;
+    kal_uint32                   features_1, features_2;
+    ipc_link_req_t              *link_req;
+    void                        *context_1, *context_2;
+    module_type                  module_id_1, module_id_2;
+
+    netif_1 = ipc_find_netif(netif_id_1);
+    netif_2 = ipc_find_netif(netif_id_2);
+    IPC_R_TO_W_LOCK_OBJECT(netif_1, ipc_spinlock_g);
+    hif_data_trace(MD_TRC_IPC_BIND_LAN_NETIF, 0, netif_1, netif_id_1, netif_2, netif_id_2);
+
+    /* Setup LAN netif 1 */
+    if (netif_1 && netif_2) {
+        features_1 = netif_1->config.features;
+
+        IPC_ASSERT(features_1 & IPC_F_LAN);
+        IPC_ASSERT(!netif_1->lan_netif && !netif_2->lan_netif);
+
+        /* Bind to one another netif */
+        netif_1->lan_netif = netif_2;
+
+        context_1 = netif_1->config.callback_context;
+        module_id_1 = netif_1->config.module_id;
+    } else {
+        hif_trace_error(IPC_TR_LAN_NETIF_BIND_INVALID_NETIF, netif_1, netif_id_1, netif_2, netif_id_2);
+        if (netif_1) {
+            IPC_W_UNLOCK_OBJECT(netif_1, ipc_spinlock_g);
+        }
+        if (netif_2) {
+            IPC_R_UNLOCK_OBJECT(netif_2, ipc_spinlock_g);
+        }
+        IPC_ASSERT(KAL_FALSE);
+    }
+
+    IPC_W_TO_R_LOCK_OBJECT(netif_1, ipc_spinlock_g);
+    IPC_R_TO_W_LOCK_OBJECT(netif_2, ipc_spinlock_g);
+
+    /* Setup LAN netif 2 */
+    if (netif_2) {
+        features_2 = netif_2->config.features;
+
+        IPC_ASSERT(features_2 & IPC_F_LAN);
+        IPC_ASSERT(!netif_2->lan_netif);
+
+        /* Bind to one another netif */
+        netif_2->lan_netif = netif_1;
+
+        context_2 = netif_2->config.callback_context;
+        module_id_2 = netif_2->config.module_id;
+    } else {
+        hif_trace_error(IPC_TR_LAN_NETIF_BIND_INVALID_NETIF, netif_1, netif_id_1, netif_2, netif_id_2);
+        if (netif_2) {
+            IPC_W_UNLOCK_OBJECT(netif_2, ipc_spinlock_g);
+        }
+        IPC_R_UNLOCK_OBJECT(netif_1, ipc_spinlock_g);
+        IPC_ASSERT(KAL_FALSE);
+    }
+
+    IPC_W_UNLOCK_OBJECT(netif_2, ipc_spinlock_g);
+    IPC_R_UNLOCK_OBJECT(netif_1, ipc_spinlock_g);
+
+    /* Link up LAN netif 1 */
+    link_req = (ipc_link_req_t *)construct_local_para(sizeof(ipc_link_req_t), TD_RESET);
+    IPC_ASSERT(link_req);
+
+    link_req->callback_context = context_1;
+    link_req->ip_type = IPC_IP_TYPE_MIXED;
+    link_req->req_type = IPC_LINK_REQ_TYPE_DPFM;
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              module_id_1, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_IPCORE_LINK_UP_REQ, /* msg_id */
+              (struct local_para_struct *)link_req, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+
+    /* Link up LAN netif 2 */
+    link_req = (ipc_link_req_t *)construct_local_para(sizeof(ipc_link_req_t), TD_RESET);
+    IPC_ASSERT(link_req);
+
+    link_req->callback_context = context_2;
+    link_req->ip_type = IPC_IP_TYPE_MIXED;
+    link_req->req_type = IPC_LINK_REQ_TYPE_DPFM;
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              module_id_2, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_IPCORE_LINK_UP_REQ, /* msg_id */
+              (struct local_para_struct *)link_req, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+}
+
+void ipc_unbind_lan_netif(kal_uint32 netif_id_1, kal_uint32 netif_id_2)
+{
+    ipc_netif_t                 *netif_1, *netif_2;
+    kal_uint32                   features_1, features_2;
+    ipc_link_req_t              *link_req;
+    void                        *context_1, *context_2;
+    module_type                  module_id_1, module_id_2;
+
+    netif_1 = ipc_find_netif(netif_id_1);
+    netif_2 = ipc_find_netif(netif_id_2);
+    IPC_R_TO_W_LOCK_OBJECT(netif_1, ipc_spinlock_g);
+    hif_data_trace(MD_TRC_IPC_UNBIND_LAN_NETIF, 0, netif_1, netif_id_1, netif_2, netif_id_2);
+
+    /* Setup LAN netif 1 */
+    if (netif_1 && netif_2) {
+        features_1 = netif_1->config.features;
+
+        IPC_ASSERT(features_1 & IPC_F_LAN);
+        IPC_ASSERT(netif_1->lan_netif && netif_2->lan_netif);
+
+        /* Unbind netif */
+        netif_1->lan_netif = NULL;
+
+        context_1 = netif_1->config.callback_context;
+        module_id_1 = netif_1->config.module_id;
+    } else {
+        hif_trace_error(IPC_TR_LAN_NETIF_UNBIND_INVALID_NETIF, netif_1, netif_id_1, netif_2, netif_id_2);
+        if (netif_1) {
+            IPC_W_UNLOCK_OBJECT(netif_1, ipc_spinlock_g);
+        }
+        if (netif_2) {
+            IPC_R_UNLOCK_OBJECT(netif_2, ipc_spinlock_g);
+        }
+        IPC_ASSERT(KAL_FALSE);
+    }
+
+    IPC_W_TO_R_LOCK_OBJECT(netif_1, ipc_spinlock_g);
+    IPC_R_TO_W_LOCK_OBJECT(netif_2, ipc_spinlock_g);
+
+    /* Setup LAN netif 2 */
+    if (netif_2) {
+        features_2 = netif_2->config.features;
+
+        IPC_ASSERT(features_2 & IPC_F_LAN);
+        IPC_ASSERT(netif_2->lan_netif);
+
+        /* Unbind netif */
+        netif_2->lan_netif = NULL;
+
+        context_2 = netif_2->config.callback_context;
+        module_id_2 = netif_2->config.module_id;
+    } else {
+        hif_trace_error(IPC_TR_LAN_NETIF_UNBIND_INVALID_NETIF, netif_1, netif_id_1, netif_2, netif_id_2);
+        if (netif_2) {
+            IPC_W_UNLOCK_OBJECT(netif_2, ipc_spinlock_g);
+        }
+        IPC_R_UNLOCK_OBJECT(netif_1, ipc_spinlock_g);
+        IPC_ASSERT(KAL_FALSE);
+    }
+
+    IPC_W_UNLOCK_OBJECT(netif_2, ipc_spinlock_g);
+    IPC_R_UNLOCK_OBJECT(netif_1, ipc_spinlock_g);
+
+    /* Link down LAN netif 1 */
+    link_req = (ipc_link_req_t *)construct_local_para(sizeof(ipc_link_req_t), TD_RESET);
+    IPC_ASSERT(link_req);
+
+    link_req->callback_context = context_1;
+    link_req->ip_type = IPC_IP_TYPE_MIXED;
+    link_req->req_type = IPC_LINK_REQ_TYPE_DPFM;
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+            module_id_1, /* dest_mod_id */
+            IPCORE_SAP, /* sap_id */
+            MSG_ID_IPCORE_LINK_DOWN_REQ, /* msg_id */
+            (struct local_para_struct *)link_req, /* local_para_ptr */
+            NULL); /* peer_buff_ptr */
+
+    /* Link down LAN netif 2 */
+    link_req = (ipc_link_req_t *)construct_local_para(sizeof(ipc_link_req_t), TD_RESET);
+    IPC_ASSERT(link_req);
+
+    link_req->callback_context = context_2;
+    link_req->ip_type = IPC_IP_TYPE_MIXED;
+    link_req->req_type = IPC_LINK_REQ_TYPE_DPFM;
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+            module_id_2, /* dest_mod_id */
+            IPCORE_SAP, /* sap_id */
+            MSG_ID_IPCORE_LINK_DOWN_REQ, /* msg_id */
+            (struct local_para_struct *)link_req, /* local_para_ptr */
+            NULL); /* peer_buff_ptr */
+}
+#endif
+
+void ipc_on_query_info(module_type src_mod_id, local_para_struct *local_para_ptr)
+{
+    ipc_netif_list_t netif_list_info;
+
+    hif_trace_info(IPC_TR_QUERY_INFO_START, src_mod_id, local_para_ptr);
+
+    /* Initiate information for response */
+    kal_mem_set(&netif_list_info, 0, sizeof(ipc_netif_list_t));
+
+    /* Collect information */
+    ipc_query_netif_list(&netif_list_info);
+
+    /* Response */
+    if (MOD_NIL != src_mod_id) {
+        ipc_query_info_t *cnf_msg_p;
+
+        cnf_msg_p = (ipc_query_info_t *) construct_local_para(sizeof(ipc_query_info_t), TD_RESET);
+        IPC_ASSERT(cnf_msg_p);
+
+        /* Fill response from indication structure */
+        kal_mem_cpy(&(cnf_msg_p->netif), &netif_list_info, sizeof(ipc_netif_list_t));
+
+        hif_trace_info(IPC_TR_QUERY_INFO_CNF, src_mod_id);
+
+        msg_send6(IPCORE_SRC_MOD,
+                  QUERY_DST_MOD,
+                  IPCORE_SAP,
+                  MSG_ID_IPCORE_QUERY_INFO_CNF,
+                  (local_para_struct*)cnf_msg_p,
+                  NULL);
+    } else {
+        hif_trace_error(IPC_TR_QUERY_INFO_NO_MOD_ID_FOR_CFN, src_mod_id, MOD_NIL);
+    }
+
+    hif_trace_info(IPC_TR_QUERY_INFO_END);
+}
+
+static void ipc_reg_callbacks(void)
+{
+    /* Register the callback functions with UPCM. */
+    IPC_REG_CBK_DLVR_DL_SDU(ipc_on_did_downlink_multiple_ps); /* LTE downlink callback. */
+    IPC_REG_CBK_NOTIFY_LTE_TICK_SOURCE(ipc_on_lte_tick_source); /* LTE change polling source */
+}
+
+static void ipc_get_qbm_datahead(void* gpd, kal_uint32 *datalen_ptr, void **payload_ptr)
+{
+    IPC_ASSERT(gpd && datalen_ptr && payload_ptr);
+
+    /* Get total data length */
+    *datalen_ptr = QBM_DES_GET_DATALEN(gpd);
+
+    /* Get first data pointer */
+    if (QBM_DES_GET_BDP(gpd))
+    {
+        if (*datalen_ptr) {
+            /* GPD with data : get 1st BD with-data for payload head */
+            qbm_gpd* bd = NULL;
+
+            /* get bd data ptr */
+            bd = QBM_DES_GET_DATAPTR(gpd);
+
+            /* Loop to trace 1st DL BD with data buffer */
+            while (bd && (QBM_DES_GET_DATALEN(bd) == 0)) {
+                bd = (QBM_DES_GET_EOL(bd)) ? (NULL) : ((qbm_gpd*) QBM_DES_GET_NEXT(bd));
+            }
+
+            if (bd) {
+                *payload_ptr = (kal_uint8 *) QBM_DES_GET_DATAPTR(bd);
+            } else {
+                hif_trace_error(IPC_TR_GET_QBM_DATAHEAD_ZERO_LENGTH_BD, gpd, QBM_DES_GET_DATALEN(gpd));
+                *payload_ptr = NULL;
+            }
+        } else {
+            /* GPD without data : get 1st BD */
+            void* bd = NULL;
+
+            /* get bd data ptr */
+            bd = QBM_DES_GET_DATAPTR(gpd);
+
+            *payload_ptr = (kal_uint8 *)QBM_DES_GET_DATAPTR(bd);
+        }
+    } else {
+        *payload_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(gpd);
+    }
+}
+
+static void ipc_push_qbm_datahead(void* gpd, kal_uint32 offset, kal_uint32 *datalen_ptr, void **payload_ptr)
+{
+    kal_uint8* data_ptr = NULL;
+    kal_uint32 data_len = 0;
+
+    IPC_ASSERT(gpd && datalen_ptr && payload_ptr);
+
+    if (QBM_DES_GET_BDP(gpd)) {
+        void* bd;
+
+        /* set bd data ptr */
+        bd = QBM_DES_GET_DATAPTR(gpd);
+
+        data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(bd);
+        QBM_DES_SET_DATAPTR(bd, data_ptr-offset);
+
+        /* set bd data len */
+        data_len = QBM_DES_GET_DATALEN(bd);
+        QBM_DES_SET_DATALEN(bd, data_len+offset);
+
+        /* set bd checksum */
+        qbm_cal_set_checksum(bd);
+    } else {
+        data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(gpd);
+        QBM_DES_SET_DATAPTR(gpd, data_ptr-offset);
+    }
+
+    /* set gpd data len */
+    data_len = QBM_DES_GET_DATALEN(gpd);
+    QBM_DES_SET_DATALEN(gpd, data_len+offset);
+
+    /* set gpd checksum */
+    qbm_cal_set_checksum(gpd);
+
+    *datalen_ptr = data_len + offset;
+    *payload_ptr = (void*)(data_ptr - offset);
+}
+
+#ifdef __ESL_COSIM_HIF__
+void ipc_on_esl_netif_attach_done(local_para_struct *local_para_ptr)
+{
+    hif_esl_netif_parm *in_parm = (hif_esl_netif_parm *)local_para_ptr;
+    hif_esl_netif_parm *out_parm;
+
+    out_parm = (hif_esl_netif_parm *)construct_local_para(sizeof(hif_esl_netif_parm), TD_RESET);
+    out_parm->netif_id = in_parm->netif_id;
+
+    /* In ESL environment, IPCore needs to send ILM to UPCM to request binding if network interface sent the ILM MSG_ID_HIF_IPCORE_ESL_ATTACH_DONE_IND */
+    msg_send6(MOD_IPCORE, /* src_mod_id */
+              MOD_UPCM, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_IPCORE_UPCM_ESL_PDN_BIND_REQ, /* msg_id */
+              (local_para_struct *)out_parm, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+}
+#endif
+
+static void ipc_em_update_req_hdlr(local_para_struct *local_para_ptr)
+{
+    l4cps_em_update_req_struct *p_req = (l4cps_em_update_req_struct *)local_para_ptr;
+
+    /*
+     * only process Tool source,
+     * Ignore AP.
+     * AP EM needed to be discussed.
+     */
+    if (p_req->em_src == EM_FROM_ELT) {
+        switch (p_req->info_request[IPC_EM_UL_THROTTLE_STATUS]) {
+            case EM_ON:
+                ipc_em_on_s = 1;
+                break;
+
+            case EM_OFF:
+                ipc_em_on_s = 0;
+                break;
+
+            case EM_NC:
+                /* no change */
+                break;
+
+            default:
+                /*can't reach here*/
+                IPC_ASSERT(KAL_FALSE);
+        }
+
+        /* For EM ELT update info*/
+        ipc_em_send_ul_throttle_status();
+    }
+}
+
+static void ipc_plmn_list_ind_handler(local_para_struct *local_para_ptr)
+{
+    l4c_ipcore_ul_throttle_req_struct *p_ind = (l4c_ipcore_ul_throttle_req_struct *)local_para_ptr;
+    kal_bool to_send_msg = KAL_FALSE;
+
+    switch (p_ind->ul_throttle_action) {
+        case UL_THROTTLE_NO_ACTION:
+
+            /* IPCORE need to process ul queue if ul pending queue is not empty */
+            IPC_SPIN_LOCK(g_ul_spinlock);
+            to_send_msg = ((!ipc_ul_enable_g) && (!ipc_ul_processing_s) && (!ipc_are_ul_queues_empty()));
+            if (to_send_msg) {
+                ipc_ul_processing_s = KAL_TRUE;
+            }
+            ipc_ul_enable_g = KAL_TRUE;
+            IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+            /* Switch to IPCORE context. */
+            if (to_send_msg) {
+                msg_send6(MOD_NIL,    /* src_mod_id */
+                          MOD_IPCORE, /* dest_mod_id */
+                          IPCORE_DATAPATH_SAP, /* sap_id */
+                          MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ, /* msg_id */
+                          NULL,  /* local_para_ptr */
+                          NULL); /* peer_buff_ptr */
+            }
+            break;
+        case UL_THROTTLE_ONGOING:
+            ipc_ul_enable_g = KAL_FALSE;
+            break;
+        case UL_THROTTLE_ABORTING:
+        default:
+            break;
+    }
+}
+
+static void ipc_query_ccci_runtime_data()
+{
+#if defined(__HIF_CCCI_SUPPORT__)
+    kal_uint32 mtu = 0;
+    kal_uint32 ccci_fast_runtime = 0;
+    CCCI_RUNTIME_FEATURE_SUPPORT_T result;
+
+    /* MTU */
+    result = ccci_runtime_data_query(AP_CCCI_RUNTIME_NETWORK_MTU_SIZE, &mtu, 4);
+    if (CCCI_RUNTIME_FEATURE_MUST_SUPPORT == result.support_mask) {
+        ipc_dl_valid_packet_len_s = mtu;
+    } else {
+        ipc_dl_valid_packet_len_s = IPC_DL_INVALID_LEN_DEFAULT;
+    }
+
+#if defined(__FAST_CCCI_HEADER__)
+    /* CCCI Fast Header */
+    result = ccci_runtime_data_query(AP_CCCI_RUNTIME_CCCI_FAST_HEADER, &ccci_fast_runtime, 4);
+    if (CCCI_RUNTIME_FEATURE_MUST_SUPPORT == result.support_mask) {
+        ipc_is_support_ccci_fast_header_s = KAL_TRUE;
+    } else {
+        ipc_is_support_ccci_fast_header_s = KAL_FALSE;
+    }
+#endif // __FAST_CCCI_HEADER__
+#else
+    /* MTU */
+    ipc_dl_valid_packet_len_s = IPC_DL_INVALID_LEN_DEFAULT;
+
+#if defined(__FAST_CCCI_HEADER__)
+    /* CCCI Fast Header */
+    ipc_is_support_ccci_fast_header_s = KAL_FALSE;
+#endif // __FAST_CCCI_HEADER__
+#endif
+}
+
+static void ipc_spinlock_init()
+{
+    IPC_ASSERT(!ipc_spinlock_g);
+    ipc_spinlock_g = kal_create_spinlock(IPC_LOCK_NAME);
+
+    /** used for UL operation */
+    IPC_ASSERT(!g_ul_spinlock);
+    g_ul_spinlock = kal_create_spinlock(IPC_UL_LOCK_NAME);
+}
+
+static void ipc_test_loopback_ind_handler(ilm_struct *ilm)
+{
+    ipcore_upcm_testloop_ind_struct    *ind = (ipcore_upcm_testloop_ind_struct *)(ilm->local_para_ptr);
+    ipcore_upcm_testloop_rsp_struct    *rsp;
+
+    switch (ind->cmd) {
+        case TESTLOOP_CMD_MODE_A_ACTIVATE:
+            IPC_ASSERT(ipc_test_loopback_mode_s != IPC_TEST_LOOPBACK_MODE_B);
+            ipc_test_loopback_mode_s = IPC_TEST_LOOPBACK_MODE_A;
+            IPC_REG_CBK_DLVR_DL_SDU(ipc_on_did_downlink_test_mode);
+            break;
+        case TESTLOOP_CMD_MODE_A_DEACTIVATE:
+            IPC_ASSERT(ipc_test_loopback_mode_s == IPC_TEST_LOOPBACK_MODE_A);
+            ipc_test_loopback_mode_s = IPC_TEST_LOOPBACK_MODE_OFF;
+            IPC_REG_CBK_DLVR_DL_SDU(ipc_on_did_downlink_multiple_ps);
+            break;
+        case TESTLOOP_CMD_MODE_B_ACTIVATE:
+            IPC_ASSERT(ipc_test_loopback_mode_s != IPC_TEST_LOOPBACK_MODE_A);
+            ipc_test_loopback_mode_s = IPC_TEST_LOOPBACK_MODE_B;
+            IPC_REG_CBK_DLVR_DL_SDU(ipc_on_did_downlink_test_mode);
+            break;
+        case TESTLOOP_CMD_MODE_B_DEACTIVATE:
+            IPC_ASSERT(ipc_test_loopback_mode_s == IPC_TEST_LOOPBACK_MODE_B);
+            ipc_test_loopback_mode_s = IPC_TEST_LOOPBACK_MODE_OFF;
+            IPC_REG_CBK_DLVR_DL_SDU(ipc_on_did_downlink_multiple_ps);
+            break;
+        default:
+            /*can't reach here*/
+            IPC_ASSERT(KAL_FALSE);
+    }
+
+    rsp = (ipcore_upcm_testloop_rsp_struct *)construct_local_para(sizeof(ipcore_upcm_testloop_rsp_struct), TD_RESET);
+    IPC_ASSERT(rsp);
+
+    /* Fill result */
+    rsp->is_success = KAL_TRUE;
+
+    msg_send6(MOD_IPCORE, /* src_mod_id */
+              ilm->src_mod_id, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_IPCORE_UPCM_TESTLOOP_RSP, /* msg_id */
+              (struct local_para_struct *)rsp, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+}
+
+static void ipc_on_ipcore_link_up_ind(void *link_handshake_msg_ind_ptr)
+{
+    ipc_link_handshake_msg_t *link_handshake_msg_ind_p = (ipc_link_handshake_msg_t *)link_handshake_msg_ind_ptr;
+    ipc_link_handshake_msg_t *link_handshake_msg_rsp_p = NULL;
+
+    hif_trace_info(IPC_TR_IPCORE_LINK_UP_IND_START, link_handshake_msg_ind_p->netif_id, link_handshake_msg_ind_p->ip_id, link_handshake_msg_ind_p->ip_type);
+
+    /* Always response the indication with same handshake message */
+    link_handshake_msg_rsp_p = (ipc_link_handshake_msg_t *) construct_local_para(sizeof(ipc_link_handshake_msg_t), TD_RESET);
+    IPC_ASSERT(link_handshake_msg_rsp_p);
+
+    kal_mem_cpy(link_handshake_msg_rsp_p, link_handshake_msg_ind_p, sizeof(ipc_link_handshake_msg_t));
+
+    hif_trace_info(IPC_TR_IPCORE_LINK_UP_IND_SEND_LINK_UP_RSP, link_handshake_msg_ind_p->netif_id, link_handshake_msg_ind_p->ip_id, link_handshake_msg_ind_p->ip_type);
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_IPCORE_LINK_UP_RSP, /* msg_id */
+              (struct local_para_struct *) link_handshake_msg_rsp_p, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+
+    hif_trace_info(IPC_TR_IPCORE_LINK_UP_IND_END, link_handshake_msg_ind_p->netif_id, link_handshake_msg_ind_p->ip_id, link_handshake_msg_ind_p->ip_type);
+}
+
+static void ipc_on_ipcore_ip_up_ind(void *link_handshake_msg_ind_ptr)
+{
+    ipc_link_handshake_msg_t *link_handshake_msg_ind_p = (ipc_link_handshake_msg_t *)link_handshake_msg_ind_ptr;
+    ipc_link_handshake_msg_t *link_handshake_msg_rsp_p = NULL;
+
+    hif_trace_info(IPC_TR_IPCORE_IP_UP_IND_START, link_handshake_msg_ind_p->netif_id, link_handshake_msg_ind_p->ip_id, link_handshake_msg_ind_p->ip_type);
+
+    /* Always response the indication with same handshake message */
+    link_handshake_msg_rsp_p = (ipc_link_handshake_msg_t *) construct_local_para(sizeof(ipc_link_handshake_msg_t), TD_RESET);
+    IPC_ASSERT(link_handshake_msg_rsp_p);
+
+    kal_mem_cpy(link_handshake_msg_rsp_p, link_handshake_msg_ind_p, sizeof(ipc_link_handshake_msg_t));
+
+    hif_trace_info(IPC_TR_IPCORE_IP_UP_IND_SEND_IP_UP_RSP, link_handshake_msg_ind_p->netif_id, link_handshake_msg_ind_p->ip_id, link_handshake_msg_ind_p->ip_type);
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_IPCORE_IP_UP_RSP, /* msg_id */
+              (struct local_para_struct *) link_handshake_msg_rsp_p, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+
+    hif_trace_info(IPC_TR_IPCORE_IP_UP_IND_END, link_handshake_msg_ind_p->netif_id, link_handshake_msg_ind_p->ip_id, link_handshake_msg_ind_p->ip_type);
+}
+
+#if (IPC_IPV6_RA_WORKAROUND != 1)
+static void ipc_send_ra_pkt(kal_uint32 netif_id)
+{
+    qbm_gpd *p_ra_gpd = NULL;
+    kal_int32 pdn_id = 0;
+
+    if (KAL_FALSE == ipc_query_pdn_by_netif(netif_id, IPC_IP_TYPE_IPV6, &pdn_id)) {
+        hif_trace_error(IPC_TR_GET_PDN_ID_FAILED, __FUNCTION__);
+        return;
+    }
+
+    /* Forward previous IPv6 RA to AP here */
+    p_ra_gpd = ipc_data_ipv6_ra_pool_pop(pdn_id);
+    if(p_ra_gpd) {
+
+        hif_trace_info(IPC_TR_SEND_RA_GPD_NETIF, __FUNCTION__, p_ra_gpd, netif_id);
+        IPC_SEND_RA_DL(p_ra_gpd, netif_id);
+    }
+
+    return;
+}
+#else
+static void ipc_send_ra_pkt_from_ilm(ilm_struct *p_ilm)
+{
+    qbm_gpd *p_ra_gpd = NULL;
+    d2cm_ipcore_info_ind_struct *p_ind = NULL;
+    kal_int32 pdn_id = 0;
+    kal_uint32 netif_id = 0;
+    kal_bool keep_store = KAL_FALSE;
+    ipc_session_t *session = NULL;
+
+    p_ind = (d2cm_ipcore_info_ind_struct *)p_ilm->local_para_ptr;
+    netif_id = IPC_NETIF_ID_LHIF_BEGIN | p_ind->netif_id;
+    if (KAL_FALSE == ipc_query_pdn_by_netif(netif_id, IPC_IP_TYPE_IPV6, &pdn_id)) {
+        hif_trace_error(IPC_TR_GET_PDN_ID_FAILED, __FUNCTION__);
+        return;
+    }
+    keep_store = p_ind->keep_ra;
+
+    /* get previous IPv6 RA here */
+    p_ra_gpd = ipc_data_ipv6_ra_pool_pop(pdn_id);
+
+    if(p_ra_gpd) {
+        session = ipc_find_session_by_context(pdn_id);
+        if (session == NULL || IPC_SESSION_STATE_PRE_LINKUP == session->state) {
+            if(session) {
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                d2cm_ipcore_info_ind_struct *retry_ind = (d2cm_ipcore_info_ind_struct *)construct_local_para(sizeof(d2cm_ipcore_info_ind_struct), TD_RESET);
+                retry_ind->netif_id = p_ind->netif_id;
+                retry_ind->keep_ra= p_ind->keep_ra;
+                msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_D2CM_IPCORE_INFO_IND, (local_para_struct *)retry_ind, NULL);
+            } else {
+                hif_trace_error(IPC_TR_IPCORE_SESSION_NOT_FOUND, __FUNCTION__, pdn_id);
+            }
+            ipc_data_ipv6_ra_pool_push(pdn_id, p_ra_gpd);
+            return;
+        }
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        if (KAL_TRUE == keep_store) {
+            kal_uint8      *p_packet = NULL;
+            qbm_gpd        *bd = NULL;
+            kal_uint32      packet_len = 0;
+            qbm_gpd         *p_copy_ra_gpd = NULL;
+
+            /* copy p_ra_gpd to p_copy_ra_gpd */
+            if (!QBM_DES_GET_BDP(p_ra_gpd)) {
+                p_packet = QBM_DES_GET_DATAPTR(p_ra_gpd);
+                packet_len = QBM_DES_GET_DATALEN(p_ra_gpd);
+            } else {
+                /* get 1st bd data ptr */
+                bd = QBM_DES_GET_DATAPTR(p_ra_gpd);
+                /* Loop to trace 1st DL BD with data buffer */
+                while (bd && (QBM_DES_GET_DATALEN(bd) == 0)) {
+                    bd = (QBM_DES_GET_EOL(bd))?(NULL):((qbm_gpd*)QBM_DES_GET_NEXT(bd));
+                }
+                /* No any BD have data */
+                if (NULL == bd) {
+                    /* zero length gpd */
+                    qbmt_dest_q(p_ra_gpd, p_ra_gpd);
+                    return;
+                }
+                p_packet = QBM_DES_GET_DATAPTR(bd);
+                packet_len = QBM_DES_GET_DATALEN(p_ra_gpd);
+            }
+            p_copy_ra_gpd = QBM_ALLOC_ONE(QBM_TYPE_NET_DL);
+            if (p_copy_ra_gpd != NULL) {
+                bd = QBM_DES_GET_DATAPTR(p_copy_ra_gpd);
+                kal_mem_cpy(QBM_DES_GET_DATAPTR(bd), p_packet, packet_len);
+                QBM_CACHE_FLUSH(QBM_DES_GET_DATAPTR(bd), packet_len);
+                QBM_DES_SET_DATALEN(bd, packet_len);
+                qbm_cal_set_checksum(bd);
+                QBM_DES_SET_DATALEN(p_copy_ra_gpd, packet_len);
+                qbm_cal_set_checksum(p_copy_ra_gpd);
+                /* for DTAG operator keep RA for future */
+                ipc_data_ipv6_ra_pool_push(pdn_id, p_copy_ra_gpd);
+                hif_trace_info(IPC_TR_SEND_RA_GPD_PUSH_BY_PDN, __FUNCTION__, p_copy_ra_gpd, pdn_id);
+            }
+        }
+
+        hif_trace_info(IPC_TR_SEND_RA_GPD_NETIF, __FUNCTION__, p_ra_gpd, netif_id);
+        IPC_SEND_RA_DL(p_ra_gpd, netif_id);
+    }
+}
+#endif
+
+static void ipc_on_ipcore_up_rsp(void *link_handshake_msg_rsp_ptr) {
+    ipc_link_handshake_msg_t *link_handshake_msg_rsp_p = (ipc_link_handshake_msg_t *) link_handshake_msg_rsp_ptr;
+    ipc_netif_t *netif = NULL;
+    ipc_session_t *session = NULL;
+
+    hif_trace_info(IPC_TR_IPCORE_UP_RSP_START, link_handshake_msg_rsp_p->netif_id, link_handshake_msg_rsp_p->ip_id, link_handshake_msg_rsp_p->ip_type);
+
+    netif = ipc_find_netif(link_handshake_msg_rsp_p->netif_id);
+    if (netif) {
+        session = ipc_find_session_by_netif(netif, link_handshake_msg_rsp_p->ip_type);
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+        if (session) {
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            hif_trace_info(IPC_TR_IPCORE_UP_RSP_UPDATE_SESSION_STATE_TO_LINKUP, session);
+            ipc_update_session_state(session, IPC_SESSION_STATE_LINKUP);
+
+          #if (IPC_IPV6_RA_WORKAROUND != 1)
+            /* flush RA when netif linkup */
+            ipc_send_ra_pkt(link_handshake_msg_rsp_p->netif_id);
+          #endif
+        } else {
+            hif_trace_error(IPC_TR_IPCORE_UP_RSP_SESSION_NOT_FOUND, netif, link_handshake_msg_rsp_p->netif_id, link_handshake_msg_rsp_p->ip_id, link_handshake_msg_rsp_p->ip_type);
+        }
+    } else {
+        hif_trace_error(IPC_TR_IPCORE_UP_RSP_NETIF_NOT_FOUND, link_handshake_msg_rsp_p->netif_id, link_handshake_msg_rsp_p->ip_id, link_handshake_msg_rsp_p->ip_type);
+    }
+
+    hif_trace_info(IPC_TR_IPCORE_UP_RSP_END, link_handshake_msg_rsp_p->netif_id, link_handshake_msg_rsp_p->ip_id, link_handshake_msg_rsp_p->ip_type);
+}
+
+kal_uint16 ipc_calc_tcp_checksum(kal_bool is_ipv4,
+                                 kal_uint8 *src_addr,
+                                 kal_uint8 *dst_addr,
+                                 kal_uint8 *tcp_header,
+                                 kal_uint32 tcp_len)
+{
+    return ipc_utils_calc_tcp_checksum(is_ipv4, src_addr, dst_addr, tcp_header, tcp_len);
+}
+
+kal_uint16 ipc_calc_udp_checksum(kal_bool is_ipv4,
+                                 kal_uint8 *src_addr,
+                                 kal_uint8 *dst_addr,
+                                 kal_uint8 *udp_header,
+                                 kal_uint32 udp_len)
+{
+    return ipc_utils_calc_udp_checksum(is_ipv4, src_addr, dst_addr, udp_header, udp_len);
+}
+
+kal_uint16 ipc_calc_ipv4_checksum(kal_uint8  *ip_header)
+{
+    return ipc_utils_calc_ipv4_checksum(ip_header);
+}
+
+static void ipc_restore_netif_hdlr(local_para_struct *p_param)
+{
+    IPC_ASSERT(NULL != p_param);
+
+    ipc_restore_netif_struct_t *p_restore_info = (ipc_restore_netif_struct_t *)p_param;
+    ipc_netif_t *p_netif = NULL;
+
+    p_netif = ipc_find_netif(p_restore_info->netif_id);
+    if (p_netif) {
+        ipc_notify_netif_link_change(p_netif,
+                                     p_restore_info->ip_type,
+                                     p_restore_info->is_link_update,
+                                     p_restore_info->is_up);
+        IPC_R_UNLOCK_OBJECT(p_netif, ipc_spinlock_g);
+    }
+
+    return;
+}
+
+static void ipc_inject_msg_hdlr(tst_inject_string_struct *p_inject_cmd)
+{
+    ASSERT(NULL != p_inject_cmd);
+
+    if (0 == p_inject_cmd->index) {
+        msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_IPCORE_UDP_IGMP_DEREG_FILTER_REQ, NULL, NULL);
+    } else if (1 == p_inject_cmd->index) {
+        msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_IPCORE_UDP_IGMP_REG_FILTER_REQ, NULL, NULL);
+    } else if (4 == p_inject_cmd->index) {
+    	  // AT+EGCMD=481,1,"10" cancel discarding all uplink packets
+        msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_UL_DISABLE_ALL_PACKETS_DEREG_FILTER_REQ, NULL, NULL);
+    } else if (5 == p_inject_cmd->index) {
+    	  // AT+EGCMD=481,1,"11" discarding all uplink packets for test purpose 
+        msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_UL_DISABLE_ALL_PACKETS_REG_FILTER_REQ, NULL, NULL);
+    } else if (6 == p_inject_cmd->index) {
+    	  // AT+EGCMD=481,1,"20" cancel discarding all uplink packets except ping & RS
+        msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_UL_ICMP_PING_WHITELIST_DEREG_FILTER_REQ, NULL, NULL);
+    } else if (7 == p_inject_cmd->index) {
+    	  // AT+EGCMD=481,1,"21" discarding all uplink packets except ping & RS
+        msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_UL_ICMP_PING_WHITELIST_REG_FILTER_REQ, NULL, NULL);
+    }
+
+    return;
+}
+
+static void ipc_pdn_info_notify(module_type src_mod_id, local_para_struct *local_para_ptr)
+{
+    ipcore_upcm_pdn_info_ind_struct *p_param = (ipcore_upcm_pdn_info_ind_struct*)local_para_ptr;
+    kal_uint32 pdn_id = p_param->pdn_id;
+    kal_uint32 proto_idx = 0;
+
+    IPC_GET_PROTOID_FROM_MODID(src_mod_id, proto_idx);
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, proto_idx);
+
+    switch(p_param->pdn_info) {
+        case UPCM_PDN_ACT:
+            break;
+
+        case UPCM_PDN_DEACT:
+            IPC_ASSERT(IPC_PROXY_IPV6_RA_POOL_SIZE > pdn_id);
+            /* Reset RA pool when PDN is deactivated */
+            ipc_data_ipv6_ra_pool_push(pdn_id, NULL);
+            break;
+
+        default:
+            IPC_ASSERT(KAL_FALSE);
+            break;
+    }
+
+    return;
+}
+
+/*------------------------------------------------------------------------------
+ * Public functions.
+ *----------------------------------------------------------------------------*/
+kal_bool ipc_init(void)
+{
+    nmu_init();
+    hmu_boot_init();
+
+    ipc_spinlock_init();
+    ipc_object_init();
+    ipc_filter_init();
+    ipc_ntfy_init();
+    ipc_queue_init();
+    ipc_reg_callbacks();
+    ipc_timer_init();
+    ipc_query_ccci_runtime_data();
+
+    pfm_init();
+
+#if defined(__IPF_SUPPORT__)
+    IPC_ENABLE_IPF_DL_FILTER();
+#endif
+
+    return KAL_TRUE;
+}
+
+void ipc_on_ilm(ilm_struct *ilm)
+{
+    switch (ilm->msg_id) {
+        case MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ:
+            ipc_on_process_ul_queue();
+            break;
+
+        case MSG_ID_IPCORE_PROCESS_DL_QUEUE_REQ:
+
+            /* Clear processing flag */
+            ipc_data_clear_dl_ilm_flag();
+
+            ipc_data_qbm_downlink_dequeue();
+
+#if defined(__IPF_SUPPORT__)
+            ipc_meta_downlink_dequeue();
+#endif
+            ipc_did_downlink_dequeue();
+            break;
+
+        case MSG_ID_IPCORE_RETRY_UL_RELOAD_REQ:
+            ipc_on_retry_ul_reload();
+            break;
+        case MSG_ID_IPCORE_DISPATCHER_PDN_BIND_IND:
+        case MSG_ID_IPCORE_UPCM_PDN_BIND_IND: {
+            ipcore_upcm_pdn_bind_ind_struct *param = (ipcore_upcm_pdn_bind_ind_struct *)ilm->local_para_ptr;
+            kal_uint8 proto_idx;
+
+            IPC_GET_PROTOID_FROM_MODID(ilm->src_mod_id, proto_idx);
+            IPC_MASK_PROTOID_ON_PDNID(param->pdn_id, proto_idx);
+        }
+            ipc_on_pdn_bind_top(ilm->src_mod_id, ilm->local_para_ptr);
+            break;
+        case MSG_ID_IPCORE_DISPATCHER_PDN_UNBIND_IND:
+        case MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND: {
+            ipcore_upcm_pdn_unbind_ind_struct *param = (ipcore_upcm_pdn_unbind_ind_struct *)ilm->local_para_ptr;
+            kal_uint8 proto_idx;
+
+            IPC_GET_PROTOID_FROM_MODID(ilm->src_mod_id, proto_idx);
+            IPC_MASK_PROTOID_ON_PDNID(param->pdn_id, proto_idx);
+        }
+            ipc_on_pdn_unbind(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_UPCM_PDN_REBIND_IND: {
+            ipcore_upcm_pdn_rebind_ind_struct *param = (ipcore_upcm_pdn_rebind_ind_struct *)ilm->local_para_ptr;
+            kal_uint8 proto_idx;
+
+            IPC_GET_PROTOID_FROM_MODID(ilm->src_mod_id, proto_idx);
+            IPC_MASK_PROTOID_ON_PDNID(param->old_pdn_id, proto_idx);
+            IPC_MASK_PROTOID_ON_PDNID(param->new_pdn_id, proto_idx);
+        }
+            ipc_on_pdn_rebind(ilm->src_mod_id, ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_LHIFCORE_QUEUE_MAPPING_RSP: {
+            ipc_lhifcore_q_mapping_msg_t *msg = (ipc_lhifcore_q_mapping_msg_t *) ilm->local_para_ptr;
+            if(KAL_FALSE == msg->result){
+                ipc_on_pdn_bind_bot(msg->bind_src_mod_id, msg->netif_features, (local_para_struct *)&(msg->bind_ind), HIF_IPC_PDN_BIND_RSP_INVALID_NETIF);
+            }else{
+                ipc_on_pdn_bind_bot(msg->bind_src_mod_id, msg->netif_features, (local_para_struct *)&(msg->bind_ind), HIF_IPC_OK);
+            }
+            break;
+        }
+
+        case MSG_ID_DHCP4C_ACTIVATE_RSP:
+            ipc_on_dhcp4c_activate_rsp(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_DHCP4C_DEACTIVATE_RSP:
+            ipc_on_dhcp4c_deactivate_rsp(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_DHCP4C_IP_UP_IND:
+            ipc_on_dhcp4c_ip_up_ind(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_DHCP4C_IP_DOWN_IND:
+            ipc_on_dhcp4c_ip_down_ind(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_DHCP4C_PACKET_IND:
+            ipc_on_dhcp4c_packet_ind(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_LINK_UP_IND:
+            ipc_on_ipcore_link_up_ind(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_IP_UP_IND:
+            ipc_on_ipcore_ip_up_ind(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_LINK_UP_RSP:
+            ipc_on_ipcore_up_rsp(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_IP_UP_RSP:
+            ipc_on_ipcore_up_rsp(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_QUERY_INFO_REQ:
+            ipc_on_query_info(ilm->src_mod_id, ilm->local_para_ptr);
+            break;
+
+#ifdef __ESL_COSIM_HIF__
+            case MSG_ID_HIF_IPCORE_ESL_ATTACH_DONE_IND:
+            ipc_on_esl_netif_attach_done(ilm->local_para_ptr);
+            break;
+#endif
+
+        case MSG_ID_IPCORE_SET_UL_THROTTLE:
+            ipc_set_ul_throttle(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_VDM_IMS_EMERGENCY_CALL_IND:
+            ipc_ims_emergency_call_ind_handler(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_REGISTER_FILTER_REQ:
+            ipc_filter_reg_handler(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_DEREGISTER_FILTER_REQ:
+            ipc_filter_dereg_handler(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_TIMER_EXPIRY: {
+#ifndef ATEST_SYS_IPCORE
+            switch (evshed_get_index(ilm)) {
+                case IPC_ES_INDEX_UL_THROTTLE:
+                    evshed_timer_handler(ipc_es_ul_throttle_s);
+                    break;
+                default:
+                    IPC_ASSERT(0);
+                    break;
+            }
+#else
+            ipc_ul_throttle_timeout(NULL);
+#endif
+            break;
+        }
+
+        case MSG_ID_L4CPS_EM_UPDATE_REQ:
+            ipc_em_update_req_hdlr(ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_L4C_IPCORE_UL_THROTTLE_REQ:
+#ifndef __NOT_BLOCK_TX_WHEN_PLMN_LIST__
+            ipc_plmn_list_ind_handler(ilm->local_para_ptr);
+#endif
+            break;
+
+        case MSG_ID_IPCORE_RESTORE_NETIF_IND:
+            ipc_restore_netif_hdlr(ilm->local_para_ptr);
+            break;
+
+            /* MSG for Test loopback mode */
+        case MSG_ID_IPCORE_UPCM_TESTLOOP_IND:
+            ipc_test_loopback_ind_handler(ilm);
+            break;
+
+            /* MSG to PFM (Packet Filter Manager) */
+        case MSG_ID_PFM_REGISTER_FILTER_REQ:
+        case MSG_ID_PFM_DEREGISTER_FILTER_REQ:
+        case MSG_ID_AP_STATUS_IND:
+        case MSG_ID_IPCORE_UDP_IGMP_REG_FILTER_REQ:
+        case MSG_ID_IPCORE_UDP_IGMP_DEREG_FILTER_REQ:
+        case MSG_ID_PFM_ICMP_PING_REG_FILTER_REQ:
+        case MSG_ID_PFM_ICMP_PING_DEREG_FILTER_REQ:
+        case MSG_ID_PFM_UL_DISABLE_ALL_PACKETS_REG_FILTER_REQ:
+        case MSG_ID_PFM_UL_DISABLE_ALL_PACKETS_DEREG_FILTER_REQ:
+        case MSG_ID_PFM_UL_ICMP_PING_WHITELIST_REG_FILTER_REQ:
+        case MSG_ID_PFM_UL_ICMP_PING_WHITELIST_DEREG_FILTER_REQ:
+        case MSG_ID_PFM_PCIE_STATE_CHANGE_IND:
+            pfm_on_ilm(ilm);
+            break;
+
+        case MSG_ID_TST_INJECT_STRING:
+            ipc_inject_msg_hdlr((tst_inject_string_struct *)ilm->local_para_ptr);
+            break;
+
+        case MSG_ID_IPCORE_UPCM_PDN_INFO_IND:
+            ipc_pdn_info_notify(ilm->src_mod_id, ilm->local_para_ptr);
+            break;
+
+/* Received ILM sent by IPCore */
+#ifdef ATEST_SYS_IPCORE
+        case MSG_ID_IPCORE_UL_PACKET_FILTERED_REQ:
+        case MSG_ID_IPCORE_DL_PACKET_FILTERED_REQ:
+        case MSG_ID_IPCORE_UL_PACKET_FILTERED_WITH_INFO_REQ:
+        case MSG_ID_IPCORE_DL_PACKET_FILTERED_WITH_INFO_REQ:
+        case MSG_ID_IPCORE_NAS_RQ_INFO_IND:
+        case MSG_ID_IPCORE_UPCM_PDN_REBIND_RSP:
+        case MSG_ID_IPCORE_QUERY_INFO_CNF:
+        case MSG_ID_IPCORE_LHIFCORE_QUEUE_MAPPING_REQ:
+            IPC_ASSERT(ipc_ut_on_ilm(ilm));
+            break;
+#endif
+
+#if (IPC_IPV6_RA_WORKAROUND == 1)
+        case MSG_ID_D2CM_IPCORE_INFO_IND:
+            ipc_send_ra_pkt_from_ilm(ilm);
+            break;
+#endif
+        default:
+            hif_trace_error(IPC_TR_UNKNOWN_ILM, ilm->msg_id);
+            break;
+    }
+}
+
+void ipc_clean_private_data(void)
+{
+    ipc_filter_init();
+    pfm_reset();
+}
+
+kal_bool ipc_reset(void)
+{
+    kal_uint64      idx = 0;
+    ipc_session_t  *session = NULL;
+    kal_uint32      session_ip_id = 0;
+    kal_uint8       session_type = 0;
+
+    hif_trace_info(IPC_TR_RESET_START);
+
+    ipc_in_reset_s = KAL_TRUE;
+
+    /*
+     * 2012/07/24, per moja.hsu MoDIS unit test requirement,
+     * deactivate all sessions and register callback functions with UPCM at reset.
+     */
+    for (idx = 0; idx < IPC_MAX_SESSION_CNT; idx++) {
+        session = ipc_find_session_by_context((kal_uint32)idx);
+
+        hif_trace_info(IPC_TR_DEL_SESSION, session, idx);
+
+        if (session) {
+            session_ip_id = session->ip_id;
+            session_type = session->type;
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+            hif_trace_info(IPC_TR_DEL_SESSION_INFO, session_type, session->ip_id, idx);
+
+            if (IPC_IP_TYPE_IPV6 == session_type || IPC_IP_TYPE_MIXED == session_type) {
+                nmu_set_ip6_dns_num(session_ip_id, 0);
+                nmu_set_ip6_down(session_ip_id);
+            }
+            if (IPC_IP_TYPE_IPV4 == session_type || IPC_IP_TYPE_MIXED == session_type) {
+                nmu_set_ip4_dns_num(session_ip_id, 0);
+                nmu_set_ip4_down(session_ip_id);
+            }
+
+            ipc_disable_dhcp4c(session); /* disable DHCPv4 it's been enabled */
+            ipc_update_session_state(session, IPC_SESSION_STATE_UNBIND);
+            ipc_del_session(session);
+        }
+    }
+
+    /* Remove all attached network interface during reset */
+    for (idx = 0; idx < IPC_MAX_NETIF_CNT; idx++) {
+        ipc_netif_t *netif;
+
+        netif = ipc_find_netif_by_bit_id(1ULL << idx);
+        hif_trace_info(IPC_TR_DEL_NETIF, netif, idx);
+
+        if (netif) {
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+            ipc_del_netif(netif);
+        }
+    }
+
+    ipc_filter_init();
+    ipc_ntfy_init();
+
+    ipc_queue_init();
+    ipc_reg_callbacks();
+
+    pfm_reset();
+
+    ipc_in_reset_s = KAL_FALSE;
+
+    hif_trace_info(IPC_TR_RESET_END);
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_is_in_reset(void)
+{
+    return ipc_in_reset_s;
+}
+
+kal_bool ipc_attach(ipc_conf_t *config, ipc_handle_t *handle)
+{
+    ipc_netif_t *netif = NULL;
+    kal_uint32 netif_id = 0;
+    kal_uint8 ip_type = 0;
+    kal_bool is_send = KAL_FALSE;
+
+    *handle = IPC_INVALID_HANDLE;
+
+    if (NULL == config) {
+        IPC_ASSERT(KAL_FALSE);
+        return KAL_FALSE;
+    }
+    hif_trace_info(IPC_TR_NETIF_ATTACHING, config->module_id, config->netif_id, config->callback_context, config->features);
+
+    netif = ipc_new_netif(config);
+    if (netif) {
+        /*
+         * For Test loopback mode.
+         * IPCore will save the ID of the netif which set the IPC_F_TEST_LOOPBACK_X flag.
+         */
+        if (config->features & IPC_F_TEST_LOOPBACK_A) {
+            ipc_test_loopback_a_netif_id_s = config->netif_id;
+        } else if (config->features & IPC_F_TEST_LOOPBACK_B) {
+            ipc_test_loopback_b_netif_id_s = config->netif_id;
+        }
+
+        *handle = (ipc_handle_t) netif;
+
+        /* Notify for attach event */
+        ipc_ntfy_do_event_cbk(netif, IPC_NTFY_TYPE_ATTACH);
+
+        /* Restore saved netif info */
+        IPC_W_LOCK_OBJECT(netif, ipc_spinlock_g);
+        if (netif->config.features & IPC_F_KEEP_PDN_MAPPING) {
+            is_send = ipc_session_restore_netif_map(netif, &ip_type);
+            netif_id = netif->config.netif_id;
+        }
+        IPC_W_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+        if (is_send) {
+            ipc_session_send_restore_netif_ind(netif_id, ip_type, KAL_TRUE, KAL_TRUE);
+        }
+
+        return KAL_TRUE;
+    } else {
+        return KAL_FALSE;
+    }
+}
+
+kal_bool ipc_detach(ipc_handle_t handle)
+{
+    hif_trace_info(IPC_TR_NETIF_DETACHING, handle);
+
+    /* Notify for detach event "before" actually detach network interface */
+    ipc_ntfy_do_event_cbk((ipc_netif_t *) handle, IPC_NTFY_TYPE_DETACH);
+
+    return ipc_del_netif((ipc_netif_t *) handle);
+}
+
+kal_bool ipc_uplink(ipc_handle_t handle, ipc_io_request_t *ior)
+{
+    ipc_io_request_t         *curr_ior = NULL;
+    ipc_io_request_t         *tail_ior = NULL;
+    kal_uint32                ior_cnt = 0;
+    kal_bool                  to_send_msg = KAL_FALSE;
+    ipc_netif_t              *netif = (ipc_netif_t *)handle;
+    kal_uint32                netif_features = 0;
+    ipc_ul_queue_priority_e   q_priority = IPC_UL_QUEUE_PRIORITY_HIGH;
+
+    HIF_SWLA_START("IU0");
+
+    /*
+     * Note that, since we reload UL buffers in IPCORE context (ipc_on_process_ul_queue()),
+     * all exception cases reuquired for dropping UL packets discard will be done there
+     * for simplicity. So, netif lock is not required here.
+     */
+
+    if (ior) {
+        /* Enqueue the IOR list and keep the information about the corresponding netif. */
+        curr_ior = ior;
+        ior_cnt = 0;
+        do {
+            ((ipc_internal_ior_t *) curr_ior)->netif = netif;
+            tail_ior = curr_ior;
+            ior_cnt++;
+            curr_ior = curr_ior->next_request;
+        } while (curr_ior);
+
+        netif_features = netif->config.features;
+        hif_data_trace(MD_TRC_IPC_UL_UPLINK_CALLBACK, 0, ior, netif, netif_features);
+
+        if (!(netif_features & IPC_F_LATENCY_CONCERN)) {
+            /* IOR from normal Netif should be low-priority */
+            q_priority = IPC_UL_QUEUE_PRIORITY_LOW;
+        } else {
+            /* IOR from LATENCY-CONCERN Netif should be high-priority */
+            q_priority = IPC_UL_QUEUE_PRIORITY_HIGH;
+        }
+        ipc_push_ior_list_to_ior_queue(ior, tail_ior, ior_cnt, q_priority);
+
+        IPC_SPIN_LOCK(g_ul_spinlock);
+        to_send_msg = (!ipc_ul_processing_s);
+        ipc_ul_processing_s = KAL_TRUE;
+        IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+        /* Switch to IPCORE context. */
+        if (to_send_msg) {
+            msg_send6(MOD_NIL,    /* src_mod_id */
+                      MOD_IPCORE, /* dest_mod_id */
+                      IPCORE_DATAPATH_SAP, /* sap_id */
+                      MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ, /* msg_id */
+                      NULL,  /* local_para_ptr */
+                      NULL); /* peer_buff_ptr */
+        }
+
+        HIF_SWLA_STOP("IU0");
+        return KAL_TRUE;
+    } else {
+        hif_trace_error(IPC_TR_UL_INVALID_PARAM, handle, ior);
+        HIF_SWLA_STOP("IU0");
+        return KAL_FALSE;
+    }
+}
+
+kal_int32 ipc_get_ip_id(ipc_handle_t handle)
+{
+    ipc_netif_t *netif = (ipc_netif_t *)handle;
+    kal_int32 ip_id;
+
+    IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+    if (netif) {
+        ip_id = ipc_map_netif_to_ip_id(netif);
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+    } else {
+        ip_id = -1;
+    }
+
+    return ip_id;
+}
+
+void ipc_need_ul_reload(ipc_handle_t handle)
+{
+    ipc_netif_t *netif = (ipc_netif_t *)handle;
+
+    IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+    if (netif) {
+        ipc_set_netif_ul_reload_retry(netif, KAL_TRUE);
+        ipc_set_netif_ul_set_need_reload(netif, KAL_TRUE);
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+    }
+}
+
+void ipc_check_ul_reload_retry(void)
+{
+    kal_uint64 netif_ul_reload_retry;
+    kal_bool to_send_msg;
+
+    netif_ul_reload_retry = ipc_get_all_netif_ul_reload_retry();
+
+    if (0 != netif_ul_reload_retry) {
+        hif_data_trace(MD_TRC_IPC_UL_CHECK_UL_RELOAD_RETRY, 0, netif_ul_reload_retry);
+
+        IPC_SPIN_LOCK(ipc_spinlock_g);
+        to_send_msg = (!ipc_ul_reload_retrying_s);
+        ipc_ul_reload_retrying_s = KAL_TRUE;
+        IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+        if (to_send_msg) {
+            msg_send6(MOD_NIL, /* src_mod_id */
+                      MOD_IPCORE, /* dest_mod_id */
+                      IPCORE_DATAPATH_SAP, /* sap_id */
+                      MSG_ID_IPCORE_RETRY_UL_RELOAD_REQ, /* msg_id */
+                      NULL, /* local_para_ptr */
+                      NULL); /* peer_buff_ptr */
+        }
+        hmu_hifeg_start(HIF_DRV_EG_HIF_RELOAD_EVNET);
+    } else {
+        hmu_hifeg_stop(HIF_DRV_EG_HIF_RELOAD_EVNET);
+    }
+}
+
+void ipc_notify_link_change(kal_uint32 netif_id, kal_uint8 ip_type, kal_bool link_update, kal_bool is_up)
+{
+    ipc_netif_t *netif;
+
+    hif_trace_info(IPC_TR_NOTIFY_LINK_CHANGE_BEGIN, netif_id, ip_type, link_update, is_up);
+
+    netif = ipc_find_netif(netif_id);
+    if (netif)
+    {
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+        hif_trace_info(IPC_TR_NOTIFY_LINK_CHANGE_FOR_NETIF_BEGIN, netif, netif_id);
+        ipc_notify_netif_link_change(netif, ip_type, link_update, is_up);
+        hif_trace_info(IPC_TR_NOTIFY_LINK_CHANGE_FOR_NETIF_END, netif, netif_id);
+    } else
+    {
+        hif_trace_info(IPC_TR_NOTIFY_LINK_CHANGE_UNKNOWN_NETIF, netif_id);
+    }
+
+    hif_trace_info(IPC_TR_NOTIFY_LINK_CHANGE_END, netif_id, ip_type, link_update, is_up);
+}
+
+kal_int32 ipc_register_ul_filter_cbk(ipc_filter_rules_t *rules,
+                                     ipc_filter_callback_t callback_func,
+                                     void *callback_context)
+{
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    ntfy_ctxt.ntfy_mod.cbk_func = callback_func;
+    ntfy_ctxt.ntfy_mod.cbk_mod = MOD_NIL;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+    ntfy_ctxt.p_ntfy_args = callback_context;
+
+    hif_trace_info(IPC_TR_REG_UL_FILTER_CBK_BEGIN, rules, callback_func, callback_context);
+    return ipc_filter_reg_filter_by_ilm(UL_DIRECT, rules, &ntfy_ctxt);
+}
+
+kal_int32 ipc_register_dl_filter_cbk(ipc_filter_rules_t *rules,
+                                     ipc_filter_callback_t callback_func,
+                                     void *callback_context)
+{
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    ntfy_ctxt.ntfy_mod.cbk_func = callback_func;
+    ntfy_ctxt.ntfy_mod.cbk_mod = MOD_NIL;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+    ntfy_ctxt.p_ntfy_args = callback_context;
+
+    hif_trace_info(IPC_TR_REG_DL_FILTER_CBK_BEGIN, rules, callback_func, callback_context);
+    return ipc_filter_reg_filter_by_ilm(DL_DIRECT, rules, &ntfy_ctxt);
+}
+
+kal_int32 ipc_register_ul_filter_msg(ipc_filter_rules_t *rules,
+                                     module_type callback_module,
+                                     void *callback_context)
+{
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_filter_fwd_ul_pkt_by_msg;
+    ntfy_ctxt.ntfy_mod.cbk_mod = callback_module;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM;
+    ntfy_ctxt.p_ntfy_args = callback_context;
+
+    hif_trace_info(IPC_TR_REG_UL_FILTER_MSG_BEGIN, rules, callback_module, callback_context);
+    return ipc_filter_reg_filter_by_ilm(UL_DIRECT, rules, &ntfy_ctxt);
+}
+
+kal_int32 ipc_register_dl_filter_msg(ipc_filter_rules_t *rules,
+                                     module_type callback_module,
+                                     void *callback_context)
+{
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_filter_fwd_ul_pkt_by_msg;
+    ntfy_ctxt.ntfy_mod.cbk_mod = callback_module;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM;
+    ntfy_ctxt.p_ntfy_args = callback_context;
+
+    hif_trace_info(IPC_TR_REG_DL_FILTER_MSG_BEGIN, rules, callback_module, callback_context);
+    return ipc_filter_reg_filter_by_ilm(DL_DIRECT, rules, &ntfy_ctxt);
+}
+
+kal_int32 ipc_register_ul_filter_with_info_cbk(ipc_filter_rules_t *rules,
+                                               ipc_filter_with_info_callback_t callback_func,
+                                               void *callback_context)
+{
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    ntfy_ctxt.ntfy_mod.with_info_cbk_func = callback_func;
+    ntfy_ctxt.ntfy_mod.cbk_mod = MOD_NIL;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+    ntfy_ctxt.p_ntfy_args = callback_context;
+
+    hif_trace_info(IPC_TR_REG_UL_FILTER_WITH_INFO_CBK_BEGIN, rules, callback_func, callback_context);
+    return ipc_filter_reg_filter_by_ilm(UL_DIRECT, rules, &ntfy_ctxt);
+}
+
+kal_int32 ipc_register_dl_filter_with_info_cbk(ipc_filter_rules_t *rules,
+                                               ipc_filter_with_info_callback_t callback_func,
+                                               void *callback_context)
+{
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    ntfy_ctxt.ntfy_mod.with_info_cbk_func = callback_func;
+    ntfy_ctxt.ntfy_mod.cbk_mod = MOD_NIL;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+    ntfy_ctxt.p_ntfy_args = callback_context;
+
+    hif_trace_info(IPC_TR_REG_DL_FILTER_WITH_INFO_CBK_BEGIN, rules, callback_func, callback_context);
+    return ipc_filter_reg_filter_by_ilm(DL_DIRECT, rules, &ntfy_ctxt);
+}
+
+kal_int32 ipc_register_ul_filter_with_info_msg(ipc_filter_rules_t *rules,
+                                               module_type callback_module,
+                                               void *callback_context)
+{
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_filter_fwd_ul_pkt_with_info_by_msg;
+    ntfy_ctxt.ntfy_mod.cbk_mod = callback_module;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO;
+    ntfy_ctxt.p_ntfy_args = callback_context;
+
+    hif_trace_info(IPC_TR_REG_UL_FILTER_WITH_INFO_MSG_BEGIN, rules, callback_module, callback_context);
+    return ipc_filter_reg_filter_by_ilm(UL_DIRECT, rules, &ntfy_ctxt);
+}
+
+kal_int32 ipc_register_dl_filter_with_info_msg(ipc_filter_rules_t *rules,
+                                               module_type callback_module,
+                                               void *callback_context)
+{
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_filter_fwd_ul_pkt_with_info_by_msg;
+    ntfy_ctxt.ntfy_mod.cbk_mod = callback_module;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO;
+    ntfy_ctxt.p_ntfy_args = callback_context;
+
+    hif_trace_info(IPC_TR_REG_DL_FILTER_WITH_INFO_MSG_BEGIN, rules, callback_module, callback_context);
+    return ipc_filter_reg_filter_by_ilm(DL_DIRECT, rules, &ntfy_ctxt);
+}
+
+void ipc_deregister_ul_filter(kal_int32 filter_id)
+{
+    hif_trace_info(IPC_TR_DEREG_UL_FILTER_BEGIN, filter_id);
+    ipc_filter_dereg_filter_by_ilm(filter_id);
+}
+
+void ipc_deregister_dl_filter(kal_int32 filter_id)
+{
+    hif_trace_info(IPC_TR_DEREG_DL_FILTER_BEGIN, filter_id);
+    ipc_filter_dereg_filter_by_ilm(filter_id);
+}
+
+kal_bool ipc_gpd_copy(kal_uint8 *dst_buffer,
+                      kal_uint32 dst_max_len,
+                      kal_uint32 *dst_len_copied,
+                      qbm_gpd *src_head_gpd,
+                      qbm_gpd *src_tail_gpd)
+{
+    kal_bool retval;
+
+    IPC_ASSERT(dst_buffer);
+    IPC_ASSERT(dst_len_copied);
+    IPC_ASSERT(src_head_gpd);
+    IPC_ASSERT(src_tail_gpd);
+
+    hif_trace_info(IPC_TR_GPD_COPY_BEGIN, dst_buffer, dst_max_len, dst_len_copied, src_head_gpd, src_tail_gpd);
+    retval = ipc_utils_gpd_copy(dst_buffer, dst_max_len, dst_len_copied, src_head_gpd, src_tail_gpd);
+    hif_trace_info(IPC_TR_GPD_COPY_END, retval, dst_max_len, *dst_len_copied);
+
+    return retval;
+}
+
+static INLINE kal_bool ipc_pack_pkt(kal_bool uplink,
+                                    ipc_pkt_t *pkt,
+                                    ipc_hdr_t *hdr,
+                                    qbm_gpd **head_gpd,
+                                    qbm_gpd **tail_gpd)
+{
+    kal_bool fill_in_headroom = KAL_FALSE;
+
+    IPC_ASSERT(pkt);
+    IPC_ASSERT(head_gpd);
+    IPC_ASSERT(tail_gpd);
+
+    if (NULL == pkt) {
+        return KAL_FALSE;
+    }
+
+    if (KAL_TRUE == pkt->isGPD) {
+
+        hif_data_trace(MD_TRC_IPC_GE_HANDLE_GPD, 0, pkt->head, pkt->tail);
+
+        /* For GPD TX : Set GPD pointer */
+        *head_gpd = pkt->head;
+        *tail_gpd = pkt->tail;
+
+        /* Per-discussion with user (IMS), caller does NOT reserve IP/UDP header fields in GPD, and IP Core needs to fill them using headroom */
+        fill_in_headroom = KAL_TRUE;
+    } else {
+        /* For Buffer TX : Allocate single GPD and execute memory copy */
+        kal_uint32 ip_header_len = 0;
+        kal_uint32 udp_header_len = 0;
+        kal_uint32 total_len = 0;
+        kal_uint8 *ip_header = NULL;
+
+        /* Check total packet length */
+        if (hdr) {
+            /* Reserve for IP/UDP header fields if needed */
+            ip_header_len = ((IPC_IP_TYPE_IPV4 == hdr->ip_type) ? IPC_HDR_V4_HEADER_SIZE : IPC_HDR_V6_HEADER_SIZE);
+            udp_header_len = IPC_HDR_UDP_HEADER_SIZE;
+        } else {
+            ip_header_len = 0;
+            udp_header_len = 0;
+        }
+
+        total_len = ip_header_len + udp_header_len + pkt->data_len;
+        hif_data_trace(MD_TRC_IPC_GE_SET_ALLOC_DATA, pkt->data_len, pkt->data, ip_header_len, udp_header_len);
+
+        if (total_len > ((KAL_TRUE == uplink) ? ((kal_uint32) QBM_SIZE_NET_UL_SHRD) : ((kal_uint32) QBM_SIZE_NET_DL))) {
+            hif_trace_error(IPC_TR_PACK_PKT_UDP_SIZE_NG, uplink, ip_header_len, udp_header_len, pkt->data_len,
+                            ((KAL_TRUE == uplink) ? QBM_SIZE_NET_UL_SHRD : QBM_SIZE_NET_DL));
+            return KAL_FALSE;
+        }
+
+        /* Allocate single GPD */
+        if (1 != qbmt_alloc_q_no_tail((KAL_TRUE == uplink) ? QBM_TYPE_NET_UL/*UL*/: QBM_TYPE_NET_DL/*DL*/,
+                                      1,
+                                      (void**) head_gpd,
+                                      (void**) tail_gpd)) {
+            hif_trace_error(IPC_TR_PACK_PKT_ALLOC_GPD_NG, total_len);
+            return KAL_FALSE;
+        }
+
+        ipc_utils_set_gpd_datalen(*head_gpd, total_len, (void**) &ip_header);
+
+        /* IP/UDP header has reserved in payload field, no more headroom is needed in following header fill */
+        fill_in_headroom = KAL_FALSE;
+
+        /* Memory copy from data buffer to GPD */
+        kal_mem_cpy(ip_header + (ip_header_len + udp_header_len), pkt->data, pkt->data_len);
+        QBM_CACHE_FLUSH(ip_header + (ip_header_len + udp_header_len), pkt->data_len);
+
+    }
+
+    /* Fill header */
+    if (hdr) {
+        qbm_gpd *curr_gpd = NULL;
+        kal_bool end_of_gpd_list = KAL_FALSE;
+
+        /* Trace GPD list to configure UDP/IP headers one-by-one */
+        for (curr_gpd = *head_gpd; curr_gpd && (KAL_FALSE == end_of_gpd_list);
+                curr_gpd = (qbm_gpd *) QBM_DES_GET_NEXT(curr_gpd)) {
+
+            /* Fill IP/UDP header */
+            static kal_uint32 ip_v4_local_id_s = 0;
+            kal_uint16 sum16;
+            kal_uint32 ip_header_len;
+            kal_uint32 udp_header_len;
+            kal_uint32 total_len;
+            kal_uint8 *ip_header;
+            kal_uint8 *udp_header;
+
+            ip_header_len = (
+                    (IPC_IP_TYPE_IPV4 == hdr->ip_type) ? IPC_HDR_V4_HEADER_SIZE : IPC_HDR_V6_HEADER_SIZE);
+            udp_header_len = IPC_HDR_UDP_HEADER_SIZE;
+
+            /* Push and get IP/UDP header pointers */
+            if (KAL_TRUE == fill_in_headroom) {
+                ipc_push_qbm_datahead(curr_gpd, ip_header_len + udp_header_len, &total_len, (void**) &ip_header);
+            } else {
+                ipc_get_qbm_datahead(curr_gpd, &total_len, (void**) &ip_header);
+            }
+
+            if (ip_header) {
+                udp_header = ip_header + ip_header_len;
+
+                hif_data_trace(MD_TRC_IPC_GE_FILL_HEADER, total_len, curr_gpd, ip_header_len, udp_header_len);
+                IPC_ASSERT(total_len >= (ip_header_len + udp_header_len));
+
+                /* Fill UDP header */
+                IPC_HDR_UDP_SET_SRC_PORT(udp_header, hdr->src_port);
+                IPC_HDR_UDP_SET_DST_PORT(udp_header, hdr->dst_port);
+                IPC_HDR_UDP_SET_LENGTH(udp_header, total_len - ip_header_len/* UDP length */);
+                IPC_HDR_UDP_SET_CHECKSUM(udp_header, 0);
+                sum16 = ipc_calc_udp_checksum(
+                        (IPC_IP_TYPE_IPV4 == hdr->ip_type) ? KAL_TRUE : KAL_FALSE, hdr->src_addr, hdr->dst_addr, udp_header, total_len - ip_header_len/* UDP length */);
+                IPC_HDR_UDP_SET_CHECKSUM(udp_header, sum16);
+
+                if (IPC_IP_TYPE_IPV4 == hdr->ip_type) {
+                    IPC_HDR_V4_RESET_VER_IHL_DSCP_ECN(ip_header);
+                    IPC_HDR_V4_SET_DSCP(ip_header, hdr->dscp_tc);
+                    IPC_HDR_V4_SET_TOTAL_LENGTH(ip_header, total_len);
+                    IPC_HDR_V4_SET_IDENTITY(ip_header, ip_v4_local_id_s);
+                    ip_v4_local_id_s++;
+                    IPC_HDR_V4_SET_FLAGS(ip_header, 0);
+                    IPC_HDR_V4_SET_FRAG_OFFSET(ip_header, 0);
+                    IPC_HDR_V4_SET_TTL(ip_header, IPC_DEF_TTL);
+                    IPC_HDR_V4_SET_PROTOCOL(ip_header, IPC_HDR_PROT_UDP);
+                    IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, 0);
+                    IPC_HDR_V4_SET_SRC_ADDR(ip_header, hdr->src_addr);
+                    IPC_HDR_V4_SET_DST_ADDR(ip_header, hdr->dst_addr);
+                    sum16 = ipc_calc_ipv4_checksum(ip_header);
+                    IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, sum16);
+                } else {
+                    IPC_HDR_V6_RESET_VER_TC_FL(ip_header);
+                    IPC_HDR_V6_SET_TC(ip_header, hdr->dscp_tc);
+                    IPC_HDR_V6_SET_LENGTH(ip_header, total_len - ip_header_len/* UDP length */);
+                    IPC_HDR_V6_SET_NH_TYPE(ip_header, IPC_HDR_PROT_UDP);
+                    IPC_HDR_V6_SET_HOP_LIMIT(ip_header, IPC_DEF_TTL);
+                    IPC_HDR_V6_SET_SRC_ADDR(ip_header, hdr->src_addr);
+                    IPC_HDR_V6_SET_DST_ADDR(ip_header, hdr->dst_addr);
+                }
+
+                QBM_CACHE_FLUSH(ip_header, total_len);
+            } else {
+                hif_trace_error(IPC_TR_PACK_PKT_SKIP_INVALID_GPD, curr_gpd, QBM_DES_GET_DATALEN(curr_gpd));
+            }
+
+            /* Check if current GPD is last one or not */
+            end_of_gpd_list = (curr_gpd == (*tail_gpd)) ? KAL_TRUE : KAL_FALSE;
+        }
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_pack_pkt_public(kal_bool uplink,
+                             ipc_pkt_t *pkt,
+                             ipc_hdr_t *hdr,
+                             qbm_gpd **head_gpd,
+                             qbm_gpd **tail_gpd)
+{
+    hif_data_trace(MD_TRC_IPC_GE_PACK_PACKET_PUBLIC, 0);
+
+    if (KAL_FALSE == ipc_pack_pkt(uplink, pkt, hdr, head_gpd, tail_gpd)) {
+        hif_trace_error(IPC_TR_PACK_PKT_PUBLIC_FAILED, pkt->isGPD, hdr);
+        return KAL_FALSE;
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_send_ul_pkt(ipc_pkt_t *pkt, ipc_hdr_t *hdr, kal_uint32 ebi)
+{
+    qbm_gpd *head_gpd = NULL;
+    qbm_gpd *tail_gpd = NULL;
+    ipc_internal_ior_t *ior = NULL;
+    kal_bool to_send_msg = KAL_FALSE;
+
+    if (NULL == pkt) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    if (KAL_FALSE == ipc_pack_pkt(KAL_TRUE, pkt, hdr, &head_gpd, &tail_gpd)) {
+        hif_trace_error(IPC_TR_UL_PKT_PKT_PACK_FAILED, pkt->isGPD, hdr);
+        return KAL_FALSE;
+    }
+
+    /*
+     * New throttling level needs to block latency-concern packets as well.
+     * Queue packets till throttling policy changes.
+     */
+    hif_data_trace(MD_TRC_IPC_UL_SEND_PKT, ebi, head_gpd, tail_gpd);
+
+    ior = (ipc_internal_ior_t *)QBM_DES_GET_SW_CTRL_FIELD(head_gpd);
+    kal_mem_set(ior, 0, sizeof(ipc_internal_ior_t));
+    ior->io_req.next_request = NULL;
+    ior->io_req.first_gpd = head_gpd;
+    ior->io_req.last_gpd = tail_gpd;
+    ior->io_req.ip_type = 0xFF; //to distinquish from ipc_send_ul_pkt_by_pdn()
+    ior->io_req.data_path_type = IPC_INTERNAL_DATA_PATH; /*< to distinquish from normal data path */
+    ior->ebi = ebi;
+
+    ipc_push_ior_list_to_ior_queue((ipc_io_request_t *)ior, (ipc_io_request_t *)ior, 1, IPC_UL_QUEUE_PRIORITY_HIGH);
+
+    IPC_SPIN_LOCK(g_ul_spinlock);
+    to_send_msg = (!ipc_ul_processing_s);
+    ipc_ul_processing_s = KAL_TRUE;
+    IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+    /* Switch to IPCORE context. */
+    if (to_send_msg) {
+        msg_send6(MOD_NIL,    /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_DATAPATH_SAP, /* sap_id */
+                  MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ, /* msg_id */
+                  NULL,  /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_send_ul_pkt_path_by_pdn(ipc_pkt_t *pkt,
+                                       ipc_hdr_t *hdr,
+                                       kal_uint32 pdn,
+                                       kal_uint8 ip_type,
+                                       ipc_io_req_data_path_e data_path)
+{
+    qbm_gpd *head_gpd = NULL;
+    qbm_gpd *tail_gpd = NULL;
+    ipc_internal_ior_t *ior = NULL;
+    kal_bool to_send_msg = KAL_FALSE;
+    ipc_session_t              *session;
+    ipc_netif_t    *netif;
+
+    if (NULL == pkt || !((IPC_IP_TYPE_IPV4 == ip_type) || (IPC_IP_TYPE_IPV6 == ip_type))) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    if (KAL_FALSE == ipc_pack_pkt(KAL_TRUE, pkt, hdr, &head_gpd, &tail_gpd)) {
+        hif_trace_error(IPC_TR_UL_PKT_PKT_PACK_FAILED, pkt->isGPD, hdr);
+        return KAL_FALSE;
+    }
+
+    /*
+     * New throttling level needs to block latency-concern packets as well.
+     * Queue packets till throttling policy changes.
+     */
+    hif_data_trace(MD_TRC_IPC_UL_SEND_PKT_BY_PDN, pdn, ip_type, head_gpd, tail_gpd, head_gpd->data_len);
+
+    ior = (ipc_internal_ior_t *)QBM_DES_GET_SW_CTRL_FIELD(head_gpd);
+    kal_mem_set(ior, 0, sizeof(ipc_internal_ior_t));
+    ior->io_req.next_request = NULL;
+    ior->io_req.first_gpd = head_gpd;
+    ior->io_req.last_gpd = tail_gpd;
+    ior->io_req.ip_type = ip_type;
+    if (data_path == IPC_INTERNAL_DATA_PATH) {
+        ior->io_req.data_path_type = IPC_INTERNAL_DATA_PATH; /*< to distinquish from normal data path */
+        ior->pdn = pdn;
+    } else {
+        session = ipc_find_session_by_context(pdn);
+        if (session) {
+            netif = session->netif;
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            ior->netif = netif;
+        } else {
+            /* Error case should not happen, bypass normal path filtering to drop directly */
+            ior->io_req.data_path_type = IPC_INTERNAL_DATA_PATH; /*< to distinquish from normal data path */
+            ior->pdn = pdn;
+        }
+    }
+
+    ipc_push_ior_list_to_ior_queue((ipc_io_request_t *)ior, (ipc_io_request_t *)ior, 1, IPC_UL_QUEUE_PRIORITY_HIGH);
+
+    IPC_SPIN_LOCK(g_ul_spinlock);
+    to_send_msg = (!ipc_ul_processing_s);
+    ipc_ul_processing_s = KAL_TRUE;
+    IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+    /* Switch to IPCORE context. */
+    if (to_send_msg) {
+        msg_send6(MOD_NIL,    /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_DATAPATH_SAP, /* sap_id */
+                  MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ, /* msg_id */
+                  NULL, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_send_ul_pkt_by_pdn(ipc_pkt_t *pkt,
+                                ipc_hdr_t *hdr,
+                                kal_uint32 pdn,
+                                kal_uint8 ip_type)
+{
+    return ipc_send_ul_pkt_path_by_pdn(pkt, hdr, pdn, ip_type, IPC_INTERNAL_DATA_PATH);
+}
+
+kal_bool ipc_send_ul_pkt_by_netif_id(ipc_pkt_t *pkt,
+                                     ipc_hdr_t *hdr,
+                                     kal_uint32 netif_id,
+                                     kal_uint8 ip_type)
+{
+    qbm_gpd              *head_gpd = NULL;
+    qbm_gpd              *tail_gpd = NULL;
+    ipc_netif_t          *netif = NULL;
+    ipc_session_t        *session = NULL;
+    ipc_internal_ior_t   *ior = NULL;
+    kal_bool              to_send_msg = KAL_FALSE;
+
+    if (NULL == pkt || !((IPC_IP_TYPE_IPV4 == ip_type) || (IPC_IP_TYPE_IPV6 == ip_type) || (IPC_IP_TYPE_MIXED == ip_type))) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    if (KAL_FALSE == ipc_pack_pkt(KAL_TRUE, pkt, hdr, &head_gpd, &tail_gpd)) {
+        hif_trace_error(IPC_TR_UL_PKT_BY_NETIF_ID_PKT_PACK_FAILED, pkt->isGPD, hdr);
+        return KAL_FALSE;
+    }
+
+    /*
+     * New throttling level needs to block latency-concern packets as well.
+     * Queue packets till throttling policy changes.
+     */
+
+    netif = ipc_find_netif(netif_id);
+    if (netif) {
+        session = ipc_find_session_by_netif(netif, ip_type);
+        if (session) {
+            hif_data_trace(MD_TRC_IPC_UL_SEND_PKT_BY_NETIF_ID, netif_id, ip_type, head_gpd, tail_gpd, head_gpd->data_len);
+
+            ior = (ipc_internal_ior_t *)QBM_DES_GET_SW_CTRL_FIELD(head_gpd);
+            kal_mem_set(ior, 0, sizeof(ipc_internal_ior_t));
+            ior->io_req.next_request = NULL;
+            ior->io_req.first_gpd = head_gpd;
+            ior->io_req.last_gpd = tail_gpd;
+            ior->io_req.ip_type = ip_type;
+            ior->io_req.data_path_type = IPC_INTERNAL_DATA_PATH; /*< to distinquish from normal data path */
+            ior->pdn = session->context;
+
+            ipc_push_ior_list_to_ior_queue((ipc_io_request_t *)ior, (ipc_io_request_t *)ior, 1, IPC_UL_QUEUE_PRIORITY_HIGH);
+
+            IPC_SPIN_LOCK(g_ul_spinlock);
+            to_send_msg = (!ipc_ul_processing_s);
+            ipc_ul_processing_s = KAL_TRUE;
+            IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+            /* Switch to IPCORE context. */
+            if (to_send_msg) {
+                msg_send6(MOD_NIL,    /* src_mod_id */
+                          MOD_IPCORE, /* dest_mod_id */
+                          IPCORE_DATAPATH_SAP, /* sap_id */
+                          MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ, /* msg_id */
+                          NULL,  /* local_para_ptr */
+                          NULL); /* peer_buff_ptr */
+            }
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+        } else {
+            hif_trace_error(IPC_TR_UL_PKT_BY_NETIF_ID_SESSION_NOT_FOUND, netif_id, ip_type);
+            qbmt_dest_q(head_gpd, tail_gpd);
+        }
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+    } else {
+        hif_trace_error(IPC_TR_UL_PKT_BY_NETIF_ID_NETIF_NOT_FOUND, netif_id);
+        qbmt_dest_q(head_gpd, tail_gpd);
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_send_ul_pkt_multiple_ps(ipc_pkt_t *pkt,
+                                     ipc_hdr_t *hdr,
+                                     kal_uint32 ebi,
+                                     kal_uint8 proto_idx)
+{
+    hif_data_trace(MD_TRC_IPC_UL_SEND_PKT_MULTI_PS, ebi, proto_idx);
+
+    if (NULL == pkt) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    if ((0 != IPC_CHECK_EBI(ebi)) ||
+        (0 != IPC_CHECK_PROTOID(proto_idx))) {
+        hif_trace_error(IPC_TR_INVALID_PDN_PROTO_IDX, __FUNCTION__, ebi, proto_idx);
+        return KAL_FALSE;
+    }
+
+    IPC_MASK_PROTOID_ON_PDNID(ebi, proto_idx);
+
+    return ipc_send_ul_pkt(pkt, hdr, ebi);
+}
+
+kal_bool ipc_send_ul_pkt_on_normal_path_by_pdn_multiple_ps(ipc_pkt_t *pkt,
+                                                 ipc_hdr_t *hdr,
+                                                 kal_uint32 pdn,
+                                                 kal_uint8 ip_type,
+                                                 kal_uint8 proto_idx)
+{
+    hif_data_trace(MD_TRC_IPC_UL_SEND_PKT_BY_PDN_MULTI_PS, pdn, proto_idx);
+
+    if (NULL == pkt) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    if ((0 != IPC_CHECK_PDNID(pdn)) ||
+        (0 != IPC_CHECK_PROTOID(proto_idx))) {
+        hif_trace_error(IPC_TR_INVALID_PDN_PROTO_IDX, __FUNCTION__, pdn, proto_idx);
+        return KAL_FALSE;
+    }
+
+    IPC_MASK_PROTOID_ON_PDNID(pdn, proto_idx);
+
+    return ipc_send_ul_pkt_path_by_pdn(pkt, hdr, pdn, ip_type, IPC_NORMAL_DATA_PATH);
+}
+
+kal_bool ipc_send_ul_pkt_by_pdn_multiple_ps(ipc_pkt_t *pkt,
+                                            ipc_hdr_t *hdr,
+                                            kal_uint32 pdn,
+                                            kal_uint8 ip_type,
+                                            kal_uint8 proto_idx)
+{
+    hif_data_trace(MD_TRC_IPC_UL_SEND_PKT_BY_PDN_MULTI_PS, pdn, proto_idx);
+
+    if (NULL == pkt) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    if ((0 != IPC_CHECK_PDNID(pdn)) ||
+        (0 != IPC_CHECK_PROTOID(proto_idx))) {
+        hif_trace_error(IPC_TR_INVALID_PDN_PROTO_IDX, __FUNCTION__, pdn, proto_idx);
+        return KAL_FALSE;
+    }
+
+    IPC_MASK_PROTOID_ON_PDNID(pdn, proto_idx);
+
+    return ipc_send_ul_pkt_by_pdn(pkt, hdr, pdn, ip_type);
+}
+
+kal_bool ipc_send_dl_pkt_enqueue(qbm_gpd *pkt, kal_uint32 netif_id, kal_uint32 session_type)
+{
+    ipc_dlq_ior_t *ior = NULL;
+
+    if (pkt == NULL) {
+        return KAL_FALSE;
+    }
+    ior = (ipc_dlq_ior_t*)QBM_DES_GET_SW_CTRL_FIELD(pkt);
+    memset(ior, 0, sizeof(ipc_dlq_ior_t));
+    ior->session_type = session_type;
+
+    if (session_type >= IPC_IP_TYPE_INVALID) {
+        return KAL_FALSE;
+    }
+
+    if (0 != (netif_id & 0xFFFF0000)) {
+        hif_trace_error(IPC_TR_INVALID_NETIF, __FUNCTION__, netif_id);
+        return KAL_FALSE;
+    }
+    ior->netif_id = netif_id;
+
+    ipc_on_downlink_qbm_enqueue(pkt, pkt);
+    return KAL_TRUE;
+}
+
+kal_bool ipc_send_dl_pkt(ipc_pkt_t *pkt, ipc_hdr_t *hdr, kal_uint32 netif_id)
+{
+    ipc_netif_t *netif = NULL;
+    qbm_gpd *head_gpd = NULL;
+    qbm_gpd *tail_gpd = NULL;
+    qbm_gpd *ipv4_first_gpd = NULL;
+    qbm_gpd *ipv4_last_gpd = NULL;
+    qbm_gpd *ipv6_first_gpd = NULL;
+    qbm_gpd *ipv6_last_gpd = NULL;
+
+    if (NULL == pkt) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    /* Packet and Clarify IPv4/IPv6 GPDs */
+    if (KAL_FALSE == ipc_pack_pkt(KAL_FALSE, pkt, hdr, &head_gpd, &tail_gpd)) {
+        hif_trace_error(IPC_TR_DL_PKT_PKT_PACK_FAILED, pkt->isGPD, hdr);
+
+        if (KAL_TRUE == pkt->isGPD) {
+            qbmt_dest_q(pkt->head, pkt->tail);
+        }
+
+        return KAL_FALSE;
+    }
+
+    ipc_utils_clarify_gpd(head_gpd, tail_gpd, &ipv4_first_gpd, &ipv4_last_gpd, &ipv6_first_gpd, &ipv6_last_gpd);
+
+    netif = ipc_find_netif(netif_id);
+    if (netif) {
+        ipc_io_request_t *ior;
+
+        hif_data_trace(MD_TRC_IPC_DL_SEND_IPV4_PKT, 0, netif->config.netif_id, ipv4_first_gpd, ipv4_last_gpd);
+
+        /* Sent to corresponding network interface */
+        if (ipv4_first_gpd) {
+            ior = (ipc_io_request_t *) QBM_DES_GET_SW_CTRL_FIELD(ipv4_first_gpd);
+            ior->next_request = NULL;
+            ior->first_gpd = ipv4_first_gpd;
+            ior->last_gpd = ipv4_last_gpd;
+            ior->ip_type = IPC_IP_TYPE_IPV4;
+            ior->qos_priority = 0;
+
+            netif->config.ipc_dlink_callback_t(netif->config.callback_context, ior);
+        }
+
+        hif_data_trace(MD_TRC_IPC_DL_SEND_IPV6_PKT, 0, netif->config.netif_id, ipv6_first_gpd, ipv6_last_gpd);
+
+        if (ipv6_first_gpd) {
+            ior = (ipc_io_request_t *) QBM_DES_GET_SW_CTRL_FIELD(ipv6_first_gpd);
+            ior->next_request = NULL;
+            ior->first_gpd = ipv6_first_gpd;
+            ior->last_gpd = ipv6_last_gpd;
+            ior->ip_type = IPC_IP_TYPE_IPV6;
+            ior->qos_priority = 0;
+
+            netif->config.ipc_dlink_callback_t(netif->config.callback_context, ior);
+        }
+
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+        return KAL_TRUE;
+    }
+
+    hif_trace_error(IPC_TR_DL_PKT_NETIF_NOT_FOUND, netif_id);
+    IPC_UT_ASSERT(KAL_FALSE, IPC_UT_DL_PKT_NETIF_NOT_FOUND);
+
+    if (ipv4_first_gpd) {
+        qbmt_dest_q(ipv4_first_gpd, ipv4_last_gpd);
+    }
+    if (ipv6_first_gpd) {
+        qbmt_dest_q(ipv6_first_gpd, ipv6_last_gpd);
+    }
+
+    /* Network interface is not found */
+    return KAL_FALSE;
+}
+
+kal_int32 ipc_register_ntfy(ipc_ntfy_callback_t callback_func,
+                            void *callback_context)
+{
+    kal_int32 ntfy_id = 0;
+
+    hif_trace_info(IPC_TR_REG_NTFY_BEGIN, callback_func, callback_context);
+    ntfy_id = ipc_ntfy_new_cbk(callback_func, callback_context);
+    hif_trace_info(IPC_TR_REG_NTFY_END, ntfy_id);
+
+    return ntfy_id;
+}
+
+void ipc_deregister_ntfy(kal_int32 ntfy_id)
+{
+    hif_trace_info(IPC_TR_DEREG_NTFY_BEGIN, ntfy_id);
+    ipc_ntfy_del_cbk(ntfy_id);
+    hif_trace_info(IPC_TR_DEREG_NTFY_END, ntfy_id);
+}
+
+kal_bool ipc_register_link_up_ind_handler(module_type module_id)
+{
+    hif_trace_info(IPC_TR_REG_LINK_UP_IND_HDLR_BEGIN, module_id);
+    ipc_update_link_up_ind_handler(module_id);
+    hif_trace_info(IPC_TR_REG_LINK_UP_IND_HDLR_END, module_id);
+    return KAL_TRUE;
+}
+
+void ipc_deregister_link_up_ind_handler(void)
+{
+    hif_trace_info(IPC_TR_DEREG_LINK_UP_IND_HDLR_BEGIN);
+    ipc_update_link_up_ind_handler(MOD_IPCORE);
+    hif_trace_info(IPC_TR_DEREG_LINK_UP_IND_HDLR_END);
+}
+
+kal_bool ipc_register_ip_up_ind_handler(module_type module_id)
+{
+    hif_trace_info(IPC_TR_REG_IP_UP_IND_HDLR_BEGIN, module_id);
+    ipc_update_ip_up_ind_handler(module_id);
+    hif_trace_info(IPC_TR_REG_IP_UP_IND_HDLR_END, module_id);
+    return KAL_TRUE;
+}
+
+void ipc_deregister_ip_up_ind_handler(void)
+{
+    hif_trace_info(IPC_TR_DEREG_IP_UP_IND_HDLR_BEGIN);
+    ipc_update_ip_up_ind_handler(MOD_IPCORE);
+    hif_trace_info(IPC_TR_DEREG_IP_UP_IND_HDLR_END);
+}
+
+/*------------------------------------------------------------------------------
+ * Public functions. (Gen93)
+ *----------------------------------------------------------------------------*/
+kal_bool ipc_meta_uplink(kal_uint16 start_idx, kal_uint16 end_idx, LHIF_QUEUE_TYPE queue_type)
+{
+    kal_bool to_send_msg = KAL_FALSE;
+
+    HIF_SWLA_START("IU1");
+    hif_data_trace(MD_TRC_IPC_UL_META_UPLINK_CALLBACK, start_idx, end_idx, queue_type);
+
+    ipc_push_meta_list_to_meta_queue(start_idx, end_idx, queue_type);
+
+    IPC_SPIN_LOCK(g_ul_spinlock);
+    to_send_msg = (!ipc_ul_processing_s);
+    ipc_ul_processing_s = KAL_TRUE;
+    IPC_SPIN_UNLOCK(g_ul_spinlock);
+
+    /* Switch to IPCORE context. */
+    if (to_send_msg) {
+        msg_send6(MOD_NIL,    /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_DATAPATH_SAP, /* sap_id */
+                  MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ, /* msg_id */
+                  NULL,  /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+    }
+
+    HIF_SWLA_STOP("IU1");
+    return KAL_TRUE;
+}
+
+kal_bool ipc_find_pdn_id_by_netif_id(kal_uint32 netif_id, kal_uint8 ip_type, kal_uint32 *p_pdn_id, kal_uint8 *p_proto_idx)
+{
+    ipc_netif_t    *netif;
+    ipc_session_t  *session;
+    kal_bool        ret = KAL_FALSE;
+
+    if ((NULL == p_pdn_id) || (NULL == p_proto_idx)) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    netif = ipc_find_netif(netif_id);
+    if (netif) {
+        session = ipc_find_session_by_netif(netif, ip_type);
+        if (session) {
+            *p_pdn_id = session->context;
+            IPC_RETRIEVE_PROTOID_FROM_PDNID(*p_pdn_id, *p_proto_idx);
+            IPC_UNMASK_PROTOID_FROM_PDNID(*p_pdn_id);
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+            ret = KAL_TRUE;
+        } else {
+            hif_trace_error(IPC_TR_FIND_PDN_BY_NETIF_SESSION_RLOCK_FAILED, netif_id, ip_type);
+        }
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+    } else {
+        hif_trace_error(IPC_TR_FIND_PDN_BY_NETIF_NETIF_RLOCK_FAILED, netif_id, ip_type);
+    }
+
+    return ret;
+}
+
+kal_bool ipc_send_dl_pkt_in_did_internal(ipc_pkt_t *pkt,
+                                         ipc_hdr_t *hdr,
+                                         kal_uint32 netif_id)
+{
+    ipc_netif_t *netif = NULL;
+    upcm_did *did_head = NULL;
+    upcm_did *did_tail = NULL;
+    upcm_did *did = NULL;
+    upcm_did *retry_prev_did = NULL;
+    upcm_did *next_did = NULL;
+    upcm_did *retry_did = NULL;
+    kal_bool end_of_list = KAL_FALSE;
+    kal_bool dl_cbk_ret = KAL_FALSE;
+
+    if (NULL == pkt) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    if (0 != (netif_id & 0xFFFF0000)) {
+        hif_trace_error(IPC_TR_INVALID_NETIF, __FUNCTION__, netif_id);
+        return KAL_FALSE;
+    }
+
+    if (IPC_PKT_DES_TYPE_DID == pkt->buf_type) {
+        did_head = pkt->did_head;
+        did_tail = pkt->did_tail;
+    } else if (IPC_PKT_DES_TYPE_GPD == pkt->buf_type || IPC_PKT_DES_TYPE_NO_DESC == pkt->buf_type) {
+        ipc_si_hif_type_e hif_type = ipc_utils_get_hif_type_by_netif_id(netif_id);
+
+        /* Copy GPD list to DID/SIT + PRB format */
+        did = upcm_did_alloc_one();
+        if (!did) {
+            hif_trace_error(IPC_TR_DL_PKT_NETIF_DID_ALLOC_DID_NG, pkt->head, pkt->tail, netif_id);
+            return KAL_FALSE;
+        }
+
+        if (IPC_PKT_DES_TYPE_GPD == pkt->buf_type) {
+            if (KAL_TRUE != ipc_utils_cpy_gpd_to_did(pkt->head, pkt->tail, did, hif_type)) {
+                upcm_did_free_one(did);
+                return KAL_FALSE;
+            }
+
+            hif_data_trace(MD_TRC_IPC_DL_TRANS_GPD_TO_DID, pkt->head, did_head, did_tail);
+
+            /* Free the original GPD list */
+            qbmt_dest_q(pkt->head, pkt->tail);
+        } else {
+            /* IPC_PKT_DES_TYPE_NO_DESC == pkt->buf_type */
+            upcm_did_si *sit = UPCM_DID_GET_SIT_PTR(did);
+            upcm_did_si *si_ptr = &sit[0];
+
+            kal_mem_set(si_ptr, 0, sizeof(upcm_did_si));
+            UPCM_DID_SI_SET_EOL(si_ptr);
+            UPCM_DID_SI_SET_F(si_ptr);
+            UPCM_DID_SI_SET_LEN(si_ptr, pkt->data_len);
+            UPCM_DID_SI_SET_DATAPTR(si_ptr, pkt->data);
+            UPCM_DID_SI_SET_HIF_TYPE(si_ptr, hif_type);
+
+            UPCM_DID_SET_PKT_NUM(did, 1);
+            UPCM_DID_SET_SEG_NUM(did, 1);
+        }
+
+        did_head = did;
+        did_tail = did;
+    } else {
+        hif_trace_error(IPC_TR_INVALID_DESCRIPTOR, __FUNCTION__, pkt->buf_type);
+        return KAL_FALSE;
+    }
+
+    netif = ipc_find_netif(netif_id);
+    if (netif) {
+        end_of_list = KAL_FALSE;
+        for (did = did_head; did && !end_of_list; did = next_did) {
+            next_did = UPCM_DID_GET_NEXT(did);
+            end_of_list = (did == did_tail);
+
+            if (!retry_did) {
+                HIF_SWLA_START("ID3");
+
+                hif_data_trace(MD_TRC_IPC_DL_SEND_PKT_DID, netif_id, did, UPCM_DID_GET_PKT_NUM(did));
+                dl_cbk_ret = netif->config.ipc_dlink_did_cb_t(netif->config.callback_context, did);
+
+                HIF_SWLA_STOP("ID3");
+
+                if (!dl_cbk_ret) {
+                    retry_did = did;
+                    UPCM_DID_SET_SW_CTRL_FIELD(did, (kal_uint16)(netif_id & 0x0000FFFF));
+                } else {
+                    retry_prev_did = did;
+                }
+            } else {
+                UPCM_DID_SET_SW_CTRL_FIELD(did, (kal_uint16)(netif_id & 0x0000FFFF));
+            }
+        }
+
+        if (retry_did) {
+            kal_bool to_send_msg;
+
+            hif_data_trace(MD_TRC_IPC_DL_SEND_PKT_DID_PENDING, retry_did, did_tail);
+
+            if (retry_did != did_head) {
+                /* Free DID which have been sent */
+                if (retry_prev_did) {
+                    IPC_ASSERT(UPCM_DID_GET_NEXT(retry_prev_did) == retry_did);
+                    UPCM_DID_SET_NEXT(retry_prev_did, NULL);
+                }
+                upcm_did_dest_q(did_head, retry_prev_did);
+            }
+
+            /* Enqueue all remaining DID, We have to protect IPC_DL_NON_PDN_QUEUE_IDX queue, it may enq by other context */
+            IPC_SPIN_LOCK(ipc_spinlock_g);
+            ipc_did_enqueue_wo_filter_queue(retry_did, did_tail, IPC_DL_NON_PDN_QUEUE_IDX, IPC_DATA_DID_HEAD);
+            IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+            /* Send ILM to IPCore for processing DL queue */
+            to_send_msg = ipc_data_check_and_set_dl_ilm_flag();
+
+            /*
+             * Switch to IPCORE context.
+             */
+            if (to_send_msg) {
+                msg_send6(MOD_NIL, /* src_mod_id */
+                          MOD_IPCORE, /* dest_mod_id */
+                          IPCORE_DATAPATH_SAP, /* sap_id */
+                          MSG_ID_IPCORE_PROCESS_DL_QUEUE_REQ, /* msg_id */
+                          NULL, /* local_para_ptr */
+                          NULL); /* peer_buff_ptr */
+            }
+        } else {
+            upcm_did_dest_q(did_head, did_tail);
+        }
+
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+        return KAL_TRUE;
+    } else {
+        hif_trace_error(IPC_TR_DL_PKT_NETIF_DID_NOT_FOUND, netif_id, did_head, did_tail);
+        upcm_did_dest_q_free_buf(did_head, did_tail);
+    }
+
+    return KAL_FALSE;
+}
+
+kal_bool ipc_send_dl_pkt_in_did(ipc_pkt_t *pkt,
+                                ipc_hdr_t *hdr,
+                                kal_uint32 netif_id)
+{
+    ipc_si_hif_type_e hif_type = ipc_utils_get_hif_type_by_netif_id(netif_id);
+
+    IPC_ASSERT(pkt);
+
+    if (IPC_PKT_DES_TYPE_DID == pkt->buf_type) {
+        ipc_utils_pkt_dump_did(pkt->did_head, pkt->did_tail, hif_type);
+    } else if (IPC_PKT_DES_TYPE_GPD == pkt->buf_type) {
+        ipc_utils_pkt_dump_buff_gpd_list(pkt->head, pkt->tail, KAL_FALSE);
+    } else {
+        IPC_ASSERT(KAL_FALSE);
+        return KAL_FALSE;
+    }
+
+    return ipc_send_dl_pkt_in_did_internal(pkt, hdr, netif_id);
+}
+
+kal_bool ipc_query_pdn_by_netif(kal_uint32 netif_id,
+                                kal_uint8 ip_type,
+                                kal_int32 *pdn_id)
+{
+    ipc_netif_t *netif = NULL;
+    kal_bool ret = KAL_FALSE;
+
+    if (NULL == pdn_id) {
+        hif_trace_error(IPC_TR_INVALID_ARGS, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    netif = ipc_find_netif(netif_id);
+
+    if (netif) {
+        *pdn_id = ipc_map_netif_to_pdn_id(netif, ip_type);
+        if (IPC_INVALID_PDN_ID != *pdn_id) {
+            ret = KAL_TRUE;
+        }
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+    }
+
+    return ret;
+}
+
+#if defined(__MD97__)
+kal_bool ipc_send_dl_did_by_ch_id(kal_uint8 net_type, kal_uint8 ch_id, upcm_did *p_did_head, upcm_did *p_did_tail)
+{
+    kal_uint32 netif_id = 0;
+
+    if ((NULL == p_did_head) || (NULL == p_did_tail)) {
+        hif_trace_error(IPC_TR_INVALID_INPUT_DID, __FUNCTION__);
+        return KAL_FALSE;
+    }
+
+    netif_id = ipc_get_netif_id_from_meta(net_type, ch_id);
+    if (IPC_INVALID_NETIF_ID == netif_id) {
+        hif_trace_error(IPC_TR_INVALID_NETIF_ID, __FUNCTION__, net_type, ch_id);
+        return KAL_FALSE;
+    }
+
+    ipc_data_dl_enq_by_netif(netif_id, p_did_head, p_did_tail);
+    return KAL_TRUE;
+}
+#endif
+
+kal_int32 ipc_reg_filter(ipc_data_path_direction_e data_path_direct,
+                         ipc_filter_rules_t *p_rules,
+                         ipc_filter_ntfy_ctxt_t *p_ntfy_ctxt)
+{
+    kal_int32 filter_id = 0;
+
+    if (DL_DIRECT != data_path_direct && UL_DIRECT != data_path_direct) {
+        hif_trace_error(IPC_TR_INVALID_DATA_PATH_DIR, __FUNCTION__, data_path_direct);
+        return IPC_INVALID_FILTER_ID;
+    }
+
+    if (NULL == p_rules) {
+        hif_trace_error(IPC_TR_INVALID_FILTER_RULES, __FUNCTION__);
+        return IPC_INVALID_FILTER_ID;
+    }
+
+    if (NULL == p_ntfy_ctxt) {
+        hif_trace_error(IPC_TR_INVALID_FILTER_CTXT, __FUNCTION__);
+        return IPC_INVALID_FILTER_ID;
+    }
+
+    switch (p_ntfy_ctxt->ntfy_type) {
+        case IPC_FILTER_NTFY_CBK_FUNC :
+            p_ntfy_ctxt->ntfy_mod.cbk_mod = MOD_NIL;
+            break;
+        case IPC_FILTER_NTFY_ILM :
+            if (DL_DIRECT == data_path_direct) {
+                p_ntfy_ctxt->ntfy_mod.cbk_func = ipc_filter_fwd_dl_pkt_by_msg;
+            } else {
+                p_ntfy_ctxt->ntfy_mod.cbk_func = ipc_filter_fwd_ul_pkt_by_msg;
+            }
+            break;
+        case IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO :
+            p_ntfy_ctxt->ntfy_mod.cbk_mod = MOD_NIL;
+            break;
+        case IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO :
+            if (DL_DIRECT == data_path_direct) {
+                p_ntfy_ctxt->ntfy_mod.with_info_cbk_func = ipc_filter_fwd_dl_pkt_with_info_by_msg;
+            } else {
+                p_ntfy_ctxt->ntfy_mod.with_info_cbk_func = ipc_filter_fwd_ul_pkt_with_info_by_msg;
+            }
+            break;
+        default :
+            hif_trace_error(IPC_TR_INVALID_FILTER_NTFY_TYPE, __FUNCTION__, p_ntfy_ctxt->ntfy_type);
+            return IPC_INVALID_FILTER_ID;
+    }
+    filter_id = ipc_filter_reg_filter_by_ilm(data_path_direct, p_rules, p_ntfy_ctxt);
+
+    hif_trace_info(IPC_TR_REGISTER_FILTER, __FUNCTION__, data_path_direct, p_ntfy_ctxt->ntfy_type, filter_id);
+    return filter_id;
+}
+
+kal_bool ipc_dereg_filter(kal_int32 filter_id)
+{
+    hif_trace_info(IPC_TR_DEGISTER_FILTER, __FUNCTION__, filter_id);
+    return ipc_filter_dereg_filter_by_ilm(filter_id);
+}
+
+kal_bool ipc_get_data_usage_by_netif_id(kal_uint32 netif_id, ipc_data_usage_info_t *data_usage)
+{
+    IPC_ASSERT(data_usage);
+    ipc_data_usage_info_t *ipv4_data_usage = NULL, *ipv6_data_usage = NULL;
+    kal_uint32 ipv4_pdn_id, ipv6_pdn_id;
+    ipc_netif_t *netif = NULL;
+
+    netif = ipc_find_netif(netif_id);
+    if (netif) {
+        ipc_get_pdn_id_from_netif(&ipv4_pdn_id, &ipv6_pdn_id, netif);
+    } else {
+        hif_trace_error(IPC_TR_INVALID_NETIF, __FUNCTION__, netif_id);
+        return KAL_FALSE;
+    }
+
+    if ((ipv4_pdn_id == ipv6_pdn_id) && (ipv4_pdn_id != IPC_INVALID_PDN_ID)) {
+        kal_uint32 ipv4v6_pdn_id = ipv4_pdn_id;
+        ipc_data_usage_info_t *ipv4v6_data_usage = ipc_get_data_usage_by_pdn_sim_id(ipv4v6_pdn_id);
+        memcpy(data_usage, ipv4v6_data_usage, sizeof(ipc_data_usage_info_t));
+    } else if ((ipv4_pdn_id != IPC_INVALID_PDN_ID) && (ipv6_pdn_id == IPC_INVALID_PDN_ID)) {
+        ipv4_data_usage = ipc_get_data_usage_by_pdn_sim_id(ipv4_pdn_id);
+        memcpy(data_usage, ipv4_data_usage, sizeof(ipc_data_usage_info_t));
+    } else if ((ipv4_pdn_id == IPC_INVALID_PDN_ID) && (ipv6_pdn_id != IPC_INVALID_PDN_ID)) {
+        ipv6_data_usage = ipc_get_data_usage_by_pdn_sim_id(ipv6_pdn_id);
+        memcpy(data_usage, ipv6_data_usage, sizeof(ipc_data_usage_info_t));
+    } else if (ipv4_pdn_id != ipv6_pdn_id) {
+        ipv4_data_usage = ipc_get_data_usage_by_pdn_sim_id(ipv4_pdn_id);
+        ipv6_data_usage = ipc_get_data_usage_by_pdn_sim_id(ipv6_pdn_id);
+        data_usage->uplink_bytes     = ipv4_data_usage->uplink_bytes + ipv6_data_usage->uplink_bytes;
+        data_usage->downlink_bytes   = ipv4_data_usage->downlink_bytes + ipv6_data_usage->downlink_bytes;
+        data_usage->uplink_packets   = ipv4_data_usage->uplink_packets + ipv6_data_usage->uplink_packets;
+        data_usage->downlink_packets = ipv4_data_usage->downlink_packets + ipv6_data_usage->downlink_packets;
+    } else {
+        /*invalid ipv4 and ipv6 pdn id*/
+        hif_trace_info(IPC_TR_INVALID_PDN_ID, __FUNCTION__);
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+        return KAL_FALSE;
+    }
+    
+    IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+    return KAL_TRUE;
+}
+
+kal_bool ipc_get_data_usage_by_pdn_id(kal_uint32 pdn_id, kal_uint8 proto_idx, ipc_data_usage_info_t *data_usage)
+{
+    IPC_ASSERT(data_usage);
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, proto_idx);
+
+    ipc_data_usage_info_t *get_data_usage = ipc_get_data_usage_by_pdn_sim_id(pdn_id);
+    
+    if (get_data_usage) {
+        data_usage->uplink_bytes    = get_data_usage->uplink_bytes;
+        data_usage->downlink_bytes  = get_data_usage->downlink_bytes;
+        return KAL_TRUE;
+    }
+
+    return KAL_FALSE;
+}
+
+#ifdef __DISPATCHER_SUPPORT__
+void ipc_reg_cbk_dlvr_dl_did(dispatcher_dlvr_dl_did_f pf_dlvr_did)
+{
+    /* registered both cbk function when IPC_PEER was dispatcher */
+    upcm_reg_cbk_dlvr_dl_sdu(pf_dlvr_did);
+    dispatcher_reg_cbk_dlvr_dl_did(pf_dlvr_did);
+}
+#endif
diff --git a/mcu/middleware/hif/ipcore/src/ipc_module_clean.c b/mcu/middleware/hif/ipcore/src/ipc_module_clean.c
new file mode 100644
index 0000000..98c60f7
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_module_clean.c
@@ -0,0 +1,16 @@
+/*
+ * ipc_module_clean.c
+ *
+ *  Created on: 2018/10/24
+ *      Author: MTK15439
+ */
+
+
+#include "ipc_defs.h"
+
+void ipc_module_clean(void)
+{
+#if defined(__SENSITIVE_DATA_MOSAIC__)
+    ipc_clean_private_data();
+#endif
+}
diff --git a/mcu/middleware/hif/ipcore/src/ipc_notify.c b/mcu/middleware/hif/ipcore/src/ipc_notify.c
new file mode 100644
index 0000000..df9ae02
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_notify.c
@@ -0,0 +1,335 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_notify.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IPCore notification.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "ipc_defs.h"
+#include "ipc_debug.h"
+#include "ipc_notify.h"
+#include "ipc_object.h"
+
+#define IPC_NTFY_MAX_NUM 4
+
+typedef struct _ipc_ntfy_t {
+    IPC_DECLARE_OBJECT
+    kal_int32            ntfy_id;
+    ipc_ntfy_callback_t  cbk_func;
+    void                *p_cbk_args;
+} ipc_ntfy_t;
+
+typedef struct _ipc_ntfy_list_t {
+    IPC_DECLARE_OBJECT
+    kal_uint32   cnt;
+    ipc_ntfy_t  *p_ntfy[IPC_NTFY_MAX_NUM];
+} ipc_ntfy_list_t;
+
+static ipc_ntfy_t       g_ipc_ntfy_pool[IPC_NTFY_MAX_NUM];
+static ipc_ntfy_list_t  g_ipc_ntfy_list[1];
+
+static ipc_ntfy_t *ipc_ntfy_alloc_entry(ipc_ntfy_t *p_ntfy_pool,
+                                        kal_uint32 pool_size,
+                                        ipc_ntfy_callback_t cbk_func,
+                                        void *p_cbk_args)
+{
+    ipc_ntfy_t *p_ntfy = NULL;
+    kal_uint32  idx = 0;
+
+    if (NULL == cbk_func) {
+        hif_trace_error(IPC_TR_ALLOCATE_NTFY_INVALID_PARAMS, cbk_func, p_cbk_args);
+        return NULL;
+    }
+
+    for (idx = 0; idx < pool_size; idx++) {
+        p_ntfy = p_ntfy_pool + idx;
+
+        if (!IPC_IS_VALID_OBJECT(p_ntfy)) {
+            IPC_INIT_OBJECT_BEGIN(p_ntfy, ipc_spinlock_g);
+
+            p_ntfy->ntfy_id = idx;
+            p_ntfy->cbk_func = cbk_func;
+            p_ntfy->p_cbk_args = p_cbk_args;
+
+            IPC_INIT_OBJECT_END(p_ntfy, ipc_spinlock_g);
+            return p_ntfy;
+        }
+    }
+
+    hif_trace_error(IPC_TR_ALLOCATE_NTFY_UNAVAILABLE, cbk_func, p_cbk_args);
+    return NULL;
+}
+
+static void ipc_ntfy_del_entry(ipc_ntfy_t *p_ntfy)
+{
+    IPC_DEINIT_OBJECT_BEGIN(p_ntfy, ipc_spinlock_g);
+    if (p_ntfy) {
+        IPC_DEINIT_OBJECT_END(p_ntfy, ipc_spinlock_g);
+    } else {
+        hif_trace_error(IPC_TR_FREE_NTFY_INVALID_OBJECT);
+    }
+}
+
+static ipc_ntfy_t *ipc_ntfy_get_entry(ipc_ntfy_t *p_ntfy_pool, kal_int32 ntfy_id)
+{
+    ASSERT((0 <= ntfy_id) && (IPC_NTFY_MAX_NUM > ntfy_id));
+
+    return (p_ntfy_pool + ntfy_id);
+}
+
+static void ipc_ntfy_add_to_list(ipc_ntfy_list_t *p_list, ipc_ntfy_t *p_ntfy)
+{
+    IPC_W_LOCK_OBJECT(p_list, ipc_spinlock_g);
+    if (p_list) {
+        p_list->p_ntfy[p_list->cnt] = p_ntfy;
+        p_list->cnt++;
+        IPC_W_UNLOCK_OBJECT(p_list, ipc_spinlock_g);
+    } else {
+        hif_trace_error(IPC_TR_ADD_NTFY_TO_LIST_INVALID_LIST, p_list);
+        IPC_ASSERT(KAL_FALSE);
+    }
+}
+
+static void ipc_ntfy_rm_from_list(ipc_ntfy_list_t *p_list, ipc_ntfy_t *p_ntfy)
+{
+    kal_uint32 idx1 = 0;
+    kal_uint32 idx2 = 0;
+
+    IPC_W_LOCK_OBJECT(p_list, ipc_spinlock_g);
+    if (p_list) {
+        for (idx1 = 0; idx1 < p_list->cnt; idx1++) {
+            if (p_list->p_ntfy[idx1] == p_ntfy) {
+                for (idx2 = idx1; idx2 < p_list->cnt - 1; idx2++) {
+                    p_list->p_ntfy[idx2] = p_list->p_ntfy[idx2 + 1];
+                }
+
+                p_list->p_ntfy[idx2] = NULL;
+                p_list->cnt--;
+                break;
+            }
+        }
+
+        IPC_W_UNLOCK_OBJECT(p_list, ipc_spinlock_g);
+    } else {
+        hif_trace_error(IPC_TR_REMOVE_NTFY_FROM_LIST_INVALID_LIST, p_list);
+        IPC_ASSERT(KAL_FALSE);
+    }
+}
+
+void ipc_ntfy_init(void)
+{
+    kal_uint32 idx = 0;
+    static ipc_ntfy_list_t *nls_set[] = {g_ipc_ntfy_list};
+
+#if defined(__MTK_TARGET__)
+    IPC_ASSERT(0 == sizeof(ipc_ntfy_t) % 4);
+    IPC_ASSERT(0 == sizeof(ipc_ntfy_list_t) % 4);
+#endif
+
+    hif_trace_info(IPC_TR_NTFY_INIT_POOL_INFO, g_ipc_ntfy_pool, sizeof(g_ipc_ntfy_pool) / sizeof(ipc_ntfy_t));
+    kal_mem_set(g_ipc_ntfy_pool, 0, sizeof(g_ipc_ntfy_pool));
+
+    for (idx = 0; idx < sizeof(nls_set) / sizeof(ipc_ntfy_list_t*); idx++) {
+        hif_trace_info(IPC_TR_NTFY_INIT_LIST_INFO, idx, nls_set[idx]);
+        kal_mem_set(nls_set[idx], 0, sizeof(ipc_ntfy_list_t));
+        IPC_INIT_OBJECT_BEGIN(nls_set[idx], ipc_spinlock_g);
+        IPC_INIT_OBJECT_END(nls_set[idx], ipc_spinlock_g);
+    }
+}
+
+kal_int32 ipc_ntfy_new_cbk(ipc_ntfy_callback_t cbk_func, void *p_cbk_args)
+{
+    ipc_ntfy_t *p_ntfy = NULL;
+
+    p_ntfy = ipc_ntfy_alloc_entry(g_ipc_ntfy_pool, IPC_NTFY_MAX_NUM, cbk_func, p_cbk_args);
+    if (p_ntfy) {
+        ipc_ntfy_add_to_list(g_ipc_ntfy_list, p_ntfy);
+        hif_trace_info(IPC_TR_NEW_NTFY_ADD_TO_LIST, p_ntfy->ntfy_id, cbk_func, p_cbk_args);
+
+        return p_ntfy->ntfy_id;
+    } else {
+        hif_trace_info(IPC_TR_NEW_NTFY_NG, cbk_func, p_cbk_args);
+        ipc_ut_set_error(IPC_UT_NEW_NTFY_NG);
+
+        return -1;
+    }
+}
+
+void ipc_ntfy_del_cbk(kal_int32 ntfy_id)
+{
+    ipc_ntfy_t *p_ntfy = NULL;
+
+    if (0 > ntfy_id || IPC_NTFY_MAX_NUM <= ntfy_id) {
+        hif_trace_error(IPC_TR_DEL_NTFY_WITH_INVALID_ID, ntfy_id);
+        ipc_ut_set_error(IPC_UT_DEL_NTFY_WITH_INVALID_ID);
+        return;
+    }
+
+    p_ntfy = ipc_ntfy_get_entry(g_ipc_ntfy_pool, ntfy_id);
+    IPC_R_LOCK_OBJECT(p_ntfy, ipc_spinlock_g);
+    if (p_ntfy) {
+        hif_trace_info(IPC_TR_DEL_NTFY_INFO, ntfy_id, p_ntfy->cbk_func, p_ntfy->p_cbk_args);
+
+        hif_trace_info(IPC_TR_DEL_NTFY_REMOVE_FROM_LIST, ntfy_id);
+        ipc_ntfy_rm_from_list(g_ipc_ntfy_list, p_ntfy);
+
+        IPC_R_UNLOCK_OBJECT(p_ntfy, ipc_spinlock_g);
+        hif_trace_info(IPC_TR_DEL_NTFY_FREE_NTFY, ntfy_id);
+        ipc_ntfy_del_entry(p_ntfy);
+    } else {
+        hif_trace_error(IPC_TR_DEL_NTFY_NOT_FOUND, ntfy_id);
+        ipc_ut_set_error(IPC_UT_DEL_NTFY_NOT_FOUND);
+    }
+}
+
+void ipc_ntfy_do_event_cbk(ipc_netif_t *p_netif, ipc_ntfy_type_e ntfy_type)
+{
+    ipc_ntfy_t *p_ntfy = NULL;
+    kal_uint32 ntfy_idx = 0;
+    kal_int32 ip_id = 0;
+
+    IPC_ASSERT(NULL != p_netif);
+    IPC_ASSERT((IPC_NTFY_TYPE_MIN < ntfy_type) && (IPC_NTFY_TYPE_MAX > ntfy_type));
+
+    IPC_R_LOCK_OBJECT(p_netif, ipc_spinlock_g);
+    if (p_netif) {
+        ip_id = ipc_map_netif_to_ip_id(p_netif);
+        IPC_R_UNLOCK_OBJECT(p_netif, ipc_spinlock_g);
+
+        for (ntfy_idx = 0; ntfy_idx < g_ipc_ntfy_list->cnt; ntfy_idx++) {
+            ipc_ntfy_param_t param;
+
+            p_ntfy = g_ipc_ntfy_list->p_ntfy[ntfy_idx];
+
+            IPC_ASSERT(NULL != p_ntfy);
+            IPC_ASSERT(NULL != p_ntfy->cbk_func);
+
+            param.context = p_ntfy->p_cbk_args;
+            param.ntfy_id = p_ntfy->ntfy_id;
+            param.ntfy_type = ntfy_type;
+            param.netif_id = p_netif->config.netif_id;
+            param.ip_id = ip_id;
+
+            hif_trace_info(IPC_TR_DO_NTFY_INFO, p_ntfy->cbk_func, param.context, param.ntfy_id);
+            hif_trace_info(IPC_TR_DO_NTFY_NTFY_INFO, param.ntfy_type, param.netif_id, param.ip_id);
+
+            /** execute callback function */
+            p_ntfy->cbk_func(&param);
+        }
+    }
+}
+
diff --git a/mcu/middleware/hif/ipcore/src/ipc_packet_parser.c b/mcu/middleware/hif/ipcore/src/ipc_packet_parser.c
new file mode 100644
index 0000000..bee4aeb
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_packet_parser.c
@@ -0,0 +1,560 @@
+#include "ipc_api.h"
+#include "ipc_debug.h"
+#include "kal_public_api.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+
+#define IPC_PACKET_PARSER_CONTINUOUS_BUFF_LEN 18
+#define SHIFT_CONTENT_MF(_msg) shift_content(&p_addr, tmp_len, ip_packet, _msg, ct_data)
+#define GET_CONTINUOUS_CONTENTMF(_hd, _of, _msg) get_continuous_content(p_addr, _hd, _of, &comm_continuous_p, _msg, ct_data)
+#define INVALID_SHIFT_RET(_msg) if(KAL_FALSE == SHIFT_CONTENT_MF(_msg)) return KAL_FALSE
+#define INVALID_GET_CONT_RET(_hd, _of, _msg) if(KAL_FALSE == GET_CONTINUOUS_CONTENTMF(_hd, _of, _msg)) return KAL_FALSE
+
+typedef kal_bool (*SHIFT_CONTENT)(kal_uint8**, kal_uint32, void*, ipc_packet_info_parser_error_code, void*);
+typedef kal_bool (*GET_CONTINUOUS_CONTENT)(kal_uint8*, kal_uint32, kal_uint32, kal_uint8**, ipc_packet_info_parser_error_code, void*);
+typedef struct _ct_data_buff {kal_uint32 data_len; kal_uint16 packet_len;} ct_data_buff;
+typedef struct _ct_data_gpd {qbm_gpd *gpd, *next_bd, *base_bd; kal_uint8 comm_buff[IPC_PACKET_PARSER_CONTINUOUS_BUFF_LEN];} ct_data_gpd;
+typedef struct _ct_data_did {upcm_did* did; kal_uint32 base_si_idx, next_si_idx; kal_uint8 comm_buff[IPC_PACKET_PARSER_CONTINUOUS_BUFF_LEN];} ct_data_did;
+
+void fill_packet_info_udp(const kal_uint8 *udp_header, ipc_packet_info_t *p_info)
+{
+    p_info->src_port= IPC_NE_GET_2B(udp_header);
+    p_info->dst_port= IPC_NE_GET_2B(udp_header + 2);
+    p_info->info_valid_fields|= (IPC_FILTER_BY_SRC_PORT + IPC_FILTER_BY_DST_PORT);
+    p_info->l4_offset= p_info->data_offset;
+    p_info->data_offset+= IPC_HDR_UDP_HEADER_SIZE;
+    p_info->l4_checksum= IPC_NE_GET_2B(udp_header + 6);
+}
+
+void fill_packet_info_tcp(const kal_uint8 *tcp_header, ipc_packet_info_t *p_info)
+{
+    p_info->src_port= IPC_NE_GET_2B(tcp_header);
+    p_info->dst_port= IPC_NE_GET_2B(tcp_header + 2);
+    p_info->tcp_flags= IPC_HDR_TCP_GET_FLAGS(tcp_header);
+    p_info->info_valid_fields|= (IPC_FILTER_BY_SRC_PORT + IPC_FILTER_BY_DST_PORT + IPC_FILTER_BY_TCP_FLAGS);
+    p_info->l4_offset= p_info->data_offset;
+    p_info->data_offset+= IPC_HDR_TCP_GET_OFFSET(tcp_header);
+    p_info->l4_checksum= IPC_NE_GET_2B(tcp_header + 16);
+}
+
+void fill_packet_info_icmp(kal_bool is_v4, const kal_uint8 *icmp_header, ipc_packet_info_t *p_info)
+{
+    if(is_v4 == KAL_TRUE) {
+        p_info->icmpv4_type= IPC_NE_GET_1B(icmp_header);
+        p_info->info_valid_fields|= IPC_FILTER_BY_ICMPV4_TYPE;
+    }
+    else {
+        p_info->icmpv6_type= IPC_NE_GET_1B(icmp_header);
+        p_info->info_valid_fields|= IPC_FILTER_BY_ICMPV6_TYPE;
+    }
+
+    p_info->l4_offset= p_info->data_offset;
+    p_info->data_offset+= IPC_HDR_ICMP_HEADER_SIZE;
+    p_info->l4_checksum= IPC_NE_GET_2B(icmp_header + 2);
+}
+
+void fill_packet_info_esp(const kal_uint8 *esp_header, ipc_packet_info_t *p_info)
+{
+    p_info->spi= IPC_NE_GET_4B(esp_header);
+    p_info->info_valid_fields|= IPC_FILTER_BY_SPI;
+}
+
+kal_bool get_packet_info(void *ip_packet, ipc_packet_info_t *p_info, SHIFT_CONTENT shift_content, GET_CONTINUOUS_CONTENT get_continuous_content, void *ct_data)
+{
+    kal_uint32 ip_header_len= 0;
+    kal_uint16 tmp_len, tmp_payload_len;
+    kal_uint8 *p_addr= (kal_uint8 *)ip_packet;
+    kal_uint8 *comm_continuous_p= NULL;
+
+    p_info->info_valid_fields= 0;
+    QBM_CACHE_INVALID(ip_packet, 1);
+
+    if(IPC_HDR_IS_V4(ip_packet)) {
+        INVALID_GET_CONT_RET(0, 12, V4_IPV4_HDR_FAILED);
+        p_info->ip_id= IPC_NE_GET_2B(comm_continuous_p + 4);
+        p_info->fragment= ((IPC_NE_GET_2B(comm_continuous_p + 6) & 0x3FFF) > 0) ? KAL_TRUE : KAL_FALSE;
+        ip_header_len= (kal_uint32)IPC_HDR_V4_GET_IHL(comm_continuous_p + 0);
+        if(p_info->fragment) {
+            p_info->frag_payload_offset= (IPC_NE_GET_2B(comm_continuous_p + 6) & 0x1FFF) << 3;
+            p_info->frag_flag= (IPC_NE_GET_1B(comm_continuous_p + 6) & 0x60) >> 5;
+            p_info->frag_payload_len= IPC_NE_GET_2B(comm_continuous_p + 2);
+            p_info->frag_buffer_payload_offset= ip_header_len;
+        }
+        p_info->protocol= IPC_NE_GET_1B(comm_continuous_p + 9);
+        p_info->info_valid_fields|= IPC_FILTER_BY_PROTOCOL;
+        p_info->ipv4_checksum= IPC_NE_GET_2B(comm_continuous_p + 10);
+
+        INVALID_GET_CONT_RET(12, 8, V4_IPV4_HDR_FAILED);
+        kal_mem_cpy(p_info->src_addr, comm_continuous_p, 4);
+        kal_mem_cpy(p_info->dst_addr, comm_continuous_p + 4, 4);
+        p_info->info_valid_fields|= (IPC_FILTER_BY_SRC_IPV4 + IPC_FILTER_BY_DST_IPV4);
+
+        if(p_info->fragment && (p_info->frag_payload_offset != 0 || p_info->frag_payload_len < 4)) return KAL_TRUE;
+        p_info->data_offset= ip_header_len;
+
+        if(p_info->protocol == IPC_HDR_PROT_AH) {
+            INVALID_GET_CONT_RET(ip_header_len, 1, V4_AH_HDR_FAILED);
+            p_info->protocol= IPC_NE_GET_1B(comm_continuous_p);
+            p_addr= p_addr + (IPC_NE_GET_1B(comm_continuous_p + 1) + 2) * 4;
+        }
+
+        if(p_info->protocol == IPC_HDR_PROT_UDP) {
+            INVALID_GET_CONT_RET(ip_header_len, 8, V4_UDP_HDR_FAILED);
+            fill_packet_info_udp(comm_continuous_p, p_info);
+        }
+        else if(p_info->protocol == IPC_HDR_PROT_TCP) {
+            INVALID_GET_CONT_RET(ip_header_len, 18, V4_TCP_HDR_FAILED);
+            fill_packet_info_tcp(comm_continuous_p, p_info);
+        }
+        else if(p_info->protocol == IPC_HDR_PROT_ICMP) {
+            INVALID_GET_CONT_RET(ip_header_len, 4, V4_ICMP_HDR_FAILED);
+            fill_packet_info_icmp(KAL_TRUE, comm_continuous_p, p_info);
+        }
+        else if(p_info->protocol == IPC_HDR_PROT_ESP) {
+            INVALID_GET_CONT_RET(ip_header_len, 4, V4_ESP_HDR_FAILED);
+            fill_packet_info_esp(comm_continuous_p, p_info);
+        }
+    }
+    else if(IPC_HDR_IS_V6(ip_packet)) {
+        p_info->fragment= KAL_FALSE;
+
+        INVALID_GET_CONT_RET(0, 8, V6_IPV6_HDR_FAILED);
+        ip_header_len= 40;
+        p_info->data_offset= ip_header_len;
+        p_info->protocol= IPC_NE_GET_1B(comm_continuous_p + 6);
+        p_info->info_valid_fields|= IPC_FILTER_BY_PROTOCOL;
+        tmp_payload_len= IPC_NE_GET_2B(comm_continuous_p + 4);
+        INVALID_GET_CONT_RET(8, 16, V6_IPV6_HDR_FAILED);
+        kal_mem_cpy(p_info->src_addr, comm_continuous_p, 16);
+        p_info->info_valid_fields|= IPC_FILTER_BY_SRC_IPV6;
+        INVALID_GET_CONT_RET(24, 16, V6_IPV6_HDR_FAILED);
+        kal_mem_cpy(p_info->dst_addr, comm_continuous_p, 16);
+        p_info->info_valid_fields|= IPC_FILTER_BY_DST_IPV6;
+
+        tmp_len= ip_header_len;
+        while(1) {
+            if((p_info->protocol == IPC_HDR_PROT_IPV6_HOP) || (p_info->protocol == IPC_HDR_PROT_IPV6_ROUTE) || (p_info->protocol == IPC_HDR_PROT_IPV6_DEST)) {
+                INVALID_SHIFT_RET(FIND_V6_EXT_HDR_SHIFT_FAILED);
+                INVALID_GET_CONT_RET(0, 2, FIND_V6_EXT_HDR_FAILED);
+                p_info->protocol= IPC_NE_GET_1B(comm_continuous_p);
+                tmp_len= (IPC_NE_GET_1B(comm_continuous_p + 1) + 1) * 8;
+                p_info->data_offset+= tmp_len;
+                if(tmp_payload_len >= tmp_len)
+                    tmp_payload_len-= tmp_len;
+                else
+                    return KAL_FALSE;
+            }
+            else if(p_info->protocol == IPC_HDR_PROT_AH) {
+                INVALID_SHIFT_RET(FIND_V6_EXT_HDR_SHIFT_FAILED);
+                INVALID_GET_CONT_RET(0, 2, FIND_V6_EXT_HDR_FAILED);
+                p_info->protocol= IPC_NE_GET_1B(comm_continuous_p);
+                tmp_len= (IPC_NE_GET_1B(comm_continuous_p + 1) + 2) * 4;
+                p_info->data_offset+= tmp_len;
+                if(tmp_payload_len >= tmp_len)
+                    tmp_payload_len-= tmp_len;
+                else
+                    return KAL_FALSE;
+            }
+            else if(p_info->protocol == IPC_HDR_PROT_IPV6_FRAG) {
+                INVALID_SHIFT_RET(FIND_V6_EXT_HDR_SHIFT_FAILED);
+                INVALID_GET_CONT_RET(0, 8, FIND_V6_EXT_HDR_FAILED);
+                p_info->fragment= KAL_TRUE;
+                p_info->ip_id= IPC_NE_GET_4B(comm_continuous_p + 4);
+                p_info->frag_payload_offset= IPC_NE_GET_2B(comm_continuous_p + 2) & 0xFFF8;
+                p_info->frag_flag= IPC_NE_GET_1B(comm_continuous_p + 3) & 0x1;
+                if(tmp_payload_len >= 8)
+                    p_info->frag_payload_len= tmp_payload_len - 8;
+                else
+                    return KAL_FALSE;
+                p_info->protocol= IPC_NE_GET_1B(comm_continuous_p);
+                if (p_info->protocol == IPC_HDR_PROT_IPV6_FRAG) {
+                    p_info->need_reassemble = KAL_TRUE;
+
+                    p_info->data_offset+= IPC_HDR_V6_FRAGMENT_HEADER_SIZE;
+                    p_info->frag_buffer_payload_offset= p_info->data_offset;
+                    break;
+                }
+                tmp_len= IPC_HDR_V6_FRAGMENT_HEADER_SIZE;
+                p_info->data_offset+= IPC_HDR_V6_FRAGMENT_HEADER_SIZE;
+                p_info->frag_buffer_payload_offset= p_info->data_offset;
+            }
+            else
+                break;
+        }
+
+        if(p_info->protocol == IPC_HDR_PROT_UDP) {
+            INVALID_SHIFT_RET(FIND_V6_EXT_HDR_SHIFT_FAILED);
+            INVALID_GET_CONT_RET(0, 8, V6_UDP_HDR_FAILED);
+            fill_packet_info_udp(comm_continuous_p, p_info);
+        }
+        else if(p_info->protocol == IPC_HDR_PROT_TCP) {
+            INVALID_SHIFT_RET(FIND_V6_EXT_HDR_SHIFT_FAILED);
+            INVALID_GET_CONT_RET(0, 18, V6_TCP_HDR_FAILED);
+            fill_packet_info_tcp(comm_continuous_p, p_info);
+        }
+        else if(p_info->protocol == IPC_HDR_PROT_ICMPV6) {
+            INVALID_SHIFT_RET(FIND_V6_EXT_HDR_SHIFT_FAILED);
+            INVALID_GET_CONT_RET(0, 4, V6_ICMP_HDR_FAILED);
+            fill_packet_info_icmp(KAL_FALSE, comm_continuous_p, p_info);
+        }
+        else if(p_info->protocol == IPC_HDR_PROT_ESP) {
+            INVALID_SHIFT_RET(FIND_V6_EXT_HDR_SHIFT_FAILED);
+            INVALID_GET_CONT_RET(0, 4, V6_ESP_HDR_FAILED);
+            fill_packet_info_esp(comm_continuous_p, p_info);
+        }
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_shift_content_ptr(kal_uint8 *base_addr_p, qbm_gpd *gpd, qbm_gpd *base_bd, kal_uint32 offset, kal_uint8 **offset_addr_pp, qbm_gpd **offset_bd_p)
+{
+    kal_uint32 remaining_offset;
+    kal_uint32 remaining_bd_length;
+    kal_uint8 *offset_addr_p;
+    qbm_gpd *curr_bd;
+
+    ASSERT(base_addr_p);
+    ASSERT(gpd);
+    ASSERT(offset_addr_pp);
+    ASSERT(offset_bd_p);
+
+    if(NULL == base_bd) {
+        *offset_addr_pp= base_addr_p + offset;
+        *offset_bd_p= NULL;
+    }
+    else {
+        curr_bd= base_bd;
+        offset_addr_p= base_addr_p;
+        remaining_offset= offset;
+        remaining_bd_length= (kal_uint32)QBM_DES_GET_DATALEN(curr_bd) - (kal_uint32)(base_addr_p - (kal_uint8 *)QBM_DES_GET_DATAPTR(curr_bd));
+
+        while(remaining_offset) {
+            if(remaining_offset <= remaining_bd_length) {
+                /* Found */
+                offset_addr_p= offset_addr_p + remaining_offset;
+                remaining_offset= 0;
+            }
+            else {
+                if(!QBM_DES_GET_EOL(curr_bd)) {
+                    remaining_offset= remaining_offset - remaining_bd_length;
+
+                    /* Shift to next BD and get information for next loop */
+                    curr_bd= (qbm_gpd *)QBM_DES_GET_NEXT(curr_bd);
+                    remaining_bd_length= QBM_DES_GET_DATALEN(curr_bd);
+                    offset_addr_p= (kal_uint8 *)QBM_DES_GET_DATAPTR(curr_bd);
+                }
+                else {
+                    hif_trace_error(IPC_TR_SHIFT_OFFSET_FAILED, gpd, base_bd, curr_bd, QBM_DES_GET_DATALEN(curr_bd), remaining_offset, base_addr_p, offset);
+                    goto process_failed;
+                }
+            }
+        }
+
+        ASSERT(offset_addr_p);
+        /* Set return values */
+        *offset_addr_pp= offset_addr_p;
+        *offset_bd_p= curr_bd;
+    }
+
+    return KAL_TRUE;
+
+process_failed:
+    return KAL_FALSE;
+}
+
+kal_bool ipc_get_continuous_content(kal_uint8 *base_addr_p, kal_uint32 offset, qbm_gpd *gpd, qbm_gpd *base_bd, kal_uint32 length, kal_uint8 **cont_addr_pp, kal_uint8 *cont_buff_p)
+{
+    kal_uint8 *data_src_p;
+    kal_uint8 *data_dst_p;
+    qbm_gpd *curr_bd;
+    kal_uint32 remaining_length;
+    kal_uint32 remaining_bd_length;
+    ASSERT(base_addr_p);
+    ASSERT(gpd);
+    ASSERT(cont_addr_pp);
+    ASSERT(cont_buff_p);
+    *cont_addr_pp= NULL;
+    /* Decide whether original GPD/BD can provide continuous content */
+    /* ----------------------------------------------------- */
+    if(NULL == base_bd) {
+        /* This packet is single GPD and content is continuous */
+        goto org_buff_is_continuous;
+    }
+    if((kal_uint32)QBM_DES_GET_DATALEN(base_bd) >= ((kal_uint32)((kal_uint8 *)base_addr_p - (kal_uint8 *)QBM_DES_GET_DATAPTR(base_bd)) + offset + length)) {
+        /* This BD is enough to support continuous content */
+        goto org_buff_is_continuous;
+    }
+    /* Using alternative buffer (cont_buff_p) */
+    /* ----------------------------------------------------- */
+    /* Copy content to alternative buffer */
+    {
+        data_dst_p= cont_buff_p;
+        curr_bd= base_bd;
+        /* Find data source pointer */
+        if(KAL_TRUE != ipc_shift_content_ptr(base_addr_p, gpd, curr_bd, offset, &data_src_p, &curr_bd)) {
+            hif_trace_error(IPC_TR_CONTENT_LENGTH_TOO_SHORT, gpd, base_bd, curr_bd, base_addr_p, offset, length);
+            goto process_failed;
+        }
+        ASSERT(data_src_p);
+        /* Copy data from source (BD list) to destination (single buffer) */
+        {
+            remaining_length= length;
+            remaining_bd_length= (kal_uint32)QBM_DES_GET_DATALEN(curr_bd) - (kal_uint32)(data_src_p - (kal_uint8 *)QBM_DES_GET_DATAPTR(curr_bd));
+            while(remaining_length) {
+                if(remaining_length <= remaining_bd_length) {
+                    /* Latest copy */
+                    QBM_CACHE_INVALID(data_src_p, remaining_length);
+                    kal_mem_cpy(data_dst_p, data_src_p, remaining_length);
+                    remaining_length= 0;
+                }
+                else {
+                    QBM_CACHE_INVALID(data_src_p, remaining_bd_length);
+                    kal_mem_cpy(data_dst_p, data_src_p, remaining_bd_length);
+                    data_dst_p= data_dst_p + remaining_bd_length;
+                    if(!QBM_DES_GET_EOL(curr_bd)) {
+                        remaining_length= remaining_length - remaining_bd_length;
+                        /* Shift to next BD and get information for next loop */
+                        curr_bd= (qbm_gpd *)QBM_DES_GET_NEXT(curr_bd);
+                        remaining_bd_length= QBM_DES_GET_DATALEN(curr_bd);
+                        data_src_p= (kal_uint8 *)QBM_DES_GET_DATAPTR(curr_bd);
+                    }
+                    else {
+                        hif_trace_error(IPC_TR_CONTENT_LENGTH_TOO_SHORT_TO_COPY, gpd, base_bd, curr_bd, QBM_DES_GET_DATALEN(curr_bd), remaining_length, base_addr_p, offset, length);
+                        goto process_failed;
+                    }
+                }
+            }
+        }
+    }
+    /* continuous buffer is from cont_buff_p and return TRUE */
+    *cont_addr_pp= cont_buff_p;
+    return KAL_TRUE;
+org_buff_is_continuous:
+    QBM_CACHE_INVALID((kal_uint8 *)(base_addr_p + offset), length);
+    *cont_addr_pp= base_addr_p + offset;
+    return KAL_TRUE;
+process_failed:
+    return KAL_FALSE;
+}
+
+kal_bool ipc_shift_did_content_ptr(kal_uint8 *base_addr_p, upcm_did *did, kal_uint32 base_si_idx, kal_uint32 offset, kal_uint8 **offset_addr_pp, kal_uint32 *offset_si_idx_p)
+{
+    kal_uint32 curr_si_idx;
+    upcm_did_si *sit;
+    upcm_did_si *curr_si;
+    kal_uint32 remaining_offset;
+    kal_uint32 remaining_si_length;
+    kal_uint8 *offset_addr_p;
+    ASSERT(base_addr_p);
+    ASSERT(did);
+    ASSERT(offset_addr_pp);
+    ASSERT(offset_si_idx_p);
+    sit= UPCM_DID_GET_SIT_PTR(did);
+    curr_si_idx= base_si_idx;
+    curr_si= &sit[base_si_idx];
+    if(UPCM_DID_SI_GET_EOL(curr_si)) {
+        *offset_addr_pp= base_addr_p + offset;
+        *offset_si_idx_p= base_si_idx;
+    }
+    else {
+        offset_addr_p= base_addr_p;
+        remaining_offset= offset;
+        remaining_si_length= (kal_uint32)(UPCM_DID_SI_GET_LEN(curr_si)) - (kal_uint32)(base_addr_p - ((kal_uint8 *)UPCM_DID_SI_GET_DATAPTR(curr_si) + UPCM_DID_SI_GET_OFFSET(curr_si)));
+        while(remaining_offset) {
+            if(remaining_offset <= remaining_si_length) {
+                /* Found */
+                offset_addr_p= offset_addr_p + remaining_offset;
+                remaining_offset= 0;
+            }
+            else {
+                if(!UPCM_DID_SI_GET_EOL(curr_si)) {
+                    remaining_offset= remaining_offset - remaining_si_length;
+                    /* Shift to next SIT and get information for next loop */
+                    curr_si_idx++;
+                    ASSERT(curr_si_idx < UPCM_DID_MAX_SIT_ENT_NUM);
+                    curr_si= &sit[curr_si_idx];
+                    remaining_si_length= UPCM_DID_SI_GET_LEN(curr_si);
+                    offset_addr_p= (kal_uint8 *)UPCM_DID_SI_GET_DATAPTR(curr_si) + UPCM_DID_SI_GET_OFFSET(curr_si);
+                }
+                else {
+                    hif_trace_error(IPC_TR_DID_SHIFT_OFFSET_FAILED, did, base_si_idx, curr_si_idx, UPCM_DID_SI_GET_LEN(curr_si), remaining_offset, base_addr_p, offset);
+                    goto process_failed;
+                }
+            }
+        }
+        ASSERT(offset_addr_p);
+        /* Set return values */
+        *offset_addr_pp= offset_addr_p;
+        *offset_si_idx_p= curr_si_idx;
+    }
+    return KAL_TRUE;
+process_failed:
+    return KAL_FALSE;
+}
+
+kal_bool ipc_get_continuous_content_did(kal_uint8 *base_addr_p, kal_uint32 offset, upcm_did *did, kal_uint32 base_si_idx, kal_uint32 length, kal_uint8 **cont_addr_pp, kal_uint8 *cont_buff_p)
+{
+    kal_uint32 curr_si_idx;
+    upcm_did_si *sit;
+    upcm_did_si *curr_si;
+    kal_uint8 *data_src_p;
+    kal_uint8 *data_dst_p;
+    kal_uint32 remaining_length;
+    kal_uint32 remaining_si_length;
+    ASSERT(base_addr_p);
+    ASSERT(did);
+    ASSERT(cont_addr_pp);
+    ASSERT(cont_buff_p);
+    *cont_addr_pp= NULL;
+    curr_si_idx= base_si_idx;
+    sit= UPCM_DID_GET_SIT_PTR(did);
+    curr_si= &sit[base_si_idx];
+    /* Determine whether original SIT can provide continuous content or not*/
+    /* ----------------------------------------------------- */
+    if(UPCM_DID_SI_GET_EOL(curr_si)) {
+        /* It's the last SIT and content is continuous */
+        goto org_buff_is_continuous;
+    }
+    if(UPCM_DID_SI_GET_LEN(curr_si) >= ((kal_uint32)((kal_uint8 *)base_addr_p - ((kal_uint8 *)UPCM_DID_SI_GET_DATAPTR(curr_si) + UPCM_DID_SI_GET_OFFSET(curr_si))) + offset + length)) {
+        /* This SIT is enough to support continuous content */
+        goto org_buff_is_continuous;
+    }
+    /* Using alternative buffer (cont_buff_p) */
+    /* ----------------------------------------------------- */
+    /* Copy content to alternative buffer */
+    {
+        data_dst_p= cont_buff_p;
+        /* Find data source pointer */
+        if(KAL_TRUE != ipc_shift_did_content_ptr(base_addr_p, did, curr_si_idx, offset, &data_src_p, &curr_si_idx)) {
+            hif_trace_error(IPC_TR_DID_CONTENT_LENGTH_TOO_SHORT, did, base_si_idx, curr_si_idx, base_addr_p, offset, length);
+            goto process_failed;
+        }
+        ASSERT(data_src_p);
+        curr_si= &sit[curr_si_idx];
+        /* Copy data from source (sit) to destination (single buffer) */
+        {
+            remaining_length= length;
+            remaining_si_length= (kal_uint32)(UPCM_DID_SI_GET_LEN(curr_si)) - (kal_uint32)(data_src_p - ((kal_uint8 *)UPCM_DID_SI_GET_DATAPTR(curr_si) + UPCM_DID_SI_GET_OFFSET(curr_si)));
+            while(remaining_length) {
+                if(remaining_length <= remaining_si_length) {
+                    /* Last copy */
+                    QBM_CACHE_INVALID(data_src_p, remaining_length);
+                    kal_mem_cpy(data_dst_p, data_src_p, remaining_length);
+                    remaining_length= 0;
+                }
+                else {
+                    QBM_CACHE_INVALID(data_src_p, remaining_si_length);
+                    kal_mem_cpy(data_dst_p, data_src_p, remaining_si_length);
+                    data_dst_p= data_dst_p + remaining_si_length;
+                    if(!UPCM_DID_SI_GET_EOL(curr_si)) {
+                        remaining_length= remaining_length - remaining_si_length;
+                        /* Shift to next SI and get information for next loop */
+                        curr_si_idx++;
+                        curr_si= &sit[curr_si_idx];
+                        remaining_si_length= UPCM_DID_SI_GET_LEN(curr_si);
+                        data_src_p= ((kal_uint8 *)UPCM_DID_SI_GET_DATAPTR(curr_si) + UPCM_DID_SI_GET_OFFSET(curr_si));
+                    }
+                    else {
+                        hif_trace_error(IPC_TR_DID_CONTENT_LENGTH_TOO_SHORT_TO_COPY, did, base_si_idx, curr_si_idx, UPCM_DID_SI_GET_LEN(curr_si), remaining_length, base_addr_p, offset, length);
+                        goto process_failed;
+                    }
+                }
+            }
+        }
+    }
+    /* continuous buffer is from cont_buff_p and return TRUE */
+    *cont_addr_pp= cont_buff_p;
+    return KAL_TRUE;
+org_buff_is_continuous:
+    QBM_CACHE_INVALID((kal_uint8 *)(base_addr_p + offset), length);
+    *cont_addr_pp= base_addr_p + offset;
+    return KAL_TRUE;
+process_failed:
+    return KAL_FALSE;
+}
+
+kal_bool _shift_content_buff(kal_uint8 **packet_addr, kal_uint32 offset, void *ip_packet, ipc_packet_info_parser_error_code err_code, void *ct_data)
+{
+    ct_data_buff *s_data= (ct_data_buff*)ct_data;
+    s_data->data_len+= offset;
+    return KAL_TRUE;
+}
+
+kal_bool _get_continuous_content_buff(kal_uint8 *packet_addr, kal_uint32 offset, kal_uint32 content_len, kal_uint8 **comm_continuous_p, ipc_packet_info_parser_error_code err_code, void *ct_data)
+{
+    ct_data_buff *s_data= (ct_data_buff*)ct_data;
+    QBM_CACHE_INVALID(packet_addr + offset, content_len);
+    *comm_continuous_p= packet_addr + s_data->data_len + offset;
+    if(s_data->packet_len < s_data->data_len + offset + content_len) {
+        hif_trace_error(IPC_TR_GET_INFO_SPD_FAILED, err_code, packet_addr, (s_data->data_len + offset + content_len), s_data->packet_len);
+        return KAL_FALSE;
+    }
+    return KAL_TRUE;
+}
+
+kal_bool ipc_get_packet_info(kal_uint8 *p_packet, kal_uint16 packet_len, ipc_packet_info_t *p_info)
+{
+    ct_data_buff ct_data;
+    ct_data.data_len= 0;
+    ct_data.packet_len= packet_len;
+    /* TODO : we seek a general solution for Cache invalidate for all packet content, this is temp solution */
+    QBM_CACHE_INVALID(p_packet, packet_len);
+    return get_packet_info((kal_uint8 *)p_packet, p_info, _shift_content_buff, _get_continuous_content_buff, &ct_data);
+}
+
+kal_bool _shift_content_gpd(kal_uint8 **packet_addr, kal_uint32 offset, void *ip_packet, ipc_packet_info_parser_error_code err_code, void *ct_data)
+{
+    ct_data_gpd *s_data= (ct_data_gpd*)ct_data;
+    if(KAL_FALSE == ipc_shift_content_ptr(*packet_addr, s_data->gpd, s_data->next_bd, offset, packet_addr, &(s_data->next_bd))) {
+        hif_trace_error(IPC_TR_GET_INFO_SHIFT_FAILED, err_code, s_data->gpd, s_data->base_bd, ip_packet, offset, packet_addr, s_data->next_bd);
+        return KAL_FALSE;
+    }
+    return KAL_TRUE;
+}
+
+kal_bool _get_continuous_content_gpd(kal_uint8 *packet_addr, kal_uint32 offset, kal_uint32 content_len, kal_uint8 **comm_continuous_p, ipc_packet_info_parser_error_code err_code, void *ct_data)
+{
+    ct_data_gpd *s_data= (ct_data_gpd*)ct_data;
+    if(KAL_FALSE == ipc_get_continuous_content(packet_addr, offset, s_data->gpd, s_data->next_bd, content_len, comm_continuous_p, s_data->comm_buff)) {
+        hif_trace_error(IPC_TR_GET_INFO_FAILED, err_code, packet_addr, offset, s_data->gpd, s_data->next_bd, content_len);
+        return KAL_FALSE;
+    }
+    return KAL_TRUE;
+}
+
+kal_bool ipc_get_packet_info_gpd(kal_uint8 *p_packet, qbm_gpd *gpd, qbm_gpd *base_bd, ipc_packet_info_t *p_info)
+{
+    ct_data_gpd ct_data;
+    ct_data.gpd= gpd;
+    ct_data.base_bd= ct_data.next_bd= base_bd;
+    return get_packet_info((kal_uint8 *)p_packet, p_info, _shift_content_gpd, _get_continuous_content_gpd, &ct_data);
+}
+
+kal_bool _shift_content_did(kal_uint8 **packet_addr, kal_uint32 offset, void *ip_packet, ipc_packet_info_parser_error_code err_code, void *ct_data)
+{
+    ct_data_did *s_data= (ct_data_did*)ct_data;
+    if(KAL_FALSE == ipc_shift_did_content_ptr(*packet_addr, s_data->did, s_data->next_si_idx, offset, packet_addr, &(s_data->next_si_idx))) {
+        hif_trace_error(IPC_TR_GET_INFO_DID_SHIFT_FAILED, err_code, s_data->did, s_data->base_si_idx, ip_packet, offset, packet_addr, s_data->next_si_idx);
+        return KAL_FALSE;
+    }
+    return KAL_TRUE;
+}
+
+kal_bool _get_continuous_content_did(kal_uint8 *packet_addr, kal_uint32 offset, kal_uint32 content_len, kal_uint8 **comm_continuous_p, ipc_packet_info_parser_error_code err_code, void *ct_data)
+{
+    ct_data_did *s_data= (ct_data_did*)ct_data;
+    if(KAL_FALSE == ipc_get_continuous_content_did(packet_addr, offset, s_data->did, s_data->next_si_idx, content_len, comm_continuous_p, s_data->comm_buff)) {
+        hif_trace_error(IPC_TR_GET_INFO_DID_FAILED, err_code, packet_addr, offset, s_data->did, s_data->next_si_idx, content_len);
+        return KAL_FALSE;
+    }
+    return KAL_TRUE;
+}
+
+kal_bool ipc_get_packet_info_did(kal_uint8 *p_packet, upcm_did *did, kal_uint32 base_si_idx, ipc_packet_info_t *p_info)
+{
+    ct_data_did ct_data;
+    ct_data.did= did;
+    ct_data.base_si_idx= ct_data.next_si_idx= base_si_idx;
+    return get_packet_info((kal_uint8 *)p_packet, p_info, _shift_content_did, _get_continuous_content_did, &ct_data);
+}
diff --git a/mcu/middleware/hif/ipcore/src/ipc_session.c b/mcu/middleware/hif/ipcore/src/ipc_session.c
new file mode 100644
index 0000000..a17d0a1
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_session.c
@@ -0,0 +1,1335 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_session.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IP session management.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_api.h"
+#include "intrCtrl.h"
+#include "mw_sap.h"
+#include "hif_mw_msgid.h"
+
+#include "qmu_bm.h"
+#include "qmu_bm_size.h"
+#include "qmu_bm_util.h"
+
+#include "ipc_defs.h"
+#include "ipc_debug.h"
+#include "ipc_utils.h"
+#include "ipc_filter.h"
+#include "ipc_notify.h"
+
+#if defined (__GEN97_ESL_SPEEDUP__)
+/* reduce mips in ESL by skipping the memory init */
+#define kal_mem_set(a,b,c)
+#endif
+
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+
+/*
+ * 2011/12/16: SD1/Moja guarantees pdn_id falls in [0,15].
+ */
+#define IPC_CONTEXT_TO_SESSION(_context, _session) (_session) = &(ipc_sessions_s[(_context)])
+#define IPC_SESSION_SAVED_MAP_NUM 1
+
+/*------------------------------------------------------------------------------
+ * Private data structure.
+ *----------------------------------------------------------------------------*/
+typedef struct _ipc_session_saved_map_t {
+    kal_bool    is_saved;
+    ipc_conf_t  netif_cfg;
+    kal_uint32  session_cnt;
+    void       *p_session_map[IPC_SESSION_MAP_SIZE];
+} ipc_session_saved_map_t;
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+static ipc_netif_t      ipc_netifs_s[IPC_MAX_NETIF_CNT];
+
+/*
+ *  Prevent the race condition of UL reload:
+ *      - ipc_netif_ul_reload_retry_s: modified in IPCORE context.
+ *      - ipc_netif_ul_set_need_reload_s: modified by netifs in their context.
+ */
+static kal_uint64       ipc_netif_ul_reload_retry_s = 0;
+static kal_uint64       ipc_netif_ul_set_need_reload_s = 0;
+
+static ipc_session_t    ipc_sessions_s[IPC_MAX_SESSION_CNT];
+static kal_bool         ipc_ids_s[IPC_MAX_IP_ID_CNT];
+
+static const ipc_session_transition_action_case_e session_transition_action_table[IPC_SESSION_STATE_MAX /* ORG */][IPC_SESSION_STATE_MAX /* NEW */] =
+{
+/*  NEW                                                                                                                                             ORG */
+/*  MIN         UNBIND      PRE_BIND    BIND        PRE_LINKUP  PRE_LINKUP_IPV4_LEASE   LINKUP      IPV4_LEASE  PRE_IPV4_RELOCATE   IP_REVOKE */
+{   0,          0,          0,          0,          0,          0,                      0,          0,          0,                  0,              /* MIN */                  },
+{   0,          0,          IPC_SST_NA, 0,          0,          0,                      0,          0,          0,                  0,              /* UNBIND */               },
+{   0,          IPC_SST_NA, 0,          IPC_SST_NA, 0,          0,                      0,          0,          0,                  0,              /* PRE_BIND */             },
+{   0,          IPC_SST_NA, IPC_SST_NA, 0,          IPC_SST_LUI,0,                      0,          0,          0,                  0,              /* BIND */                 },
+{   0,          IPC_SST_NA, 0,          0,          0,          IPC_SST_NA,             IPC_SST_LUR,0,          0,                  0,              /* PRE_LINKUP */           },
+{   0,          IPC_SST_NA, 0,          0,          IPC_SST_LUI,0,                      0,          0,          0,                  0,              /* PRE_LINKUP_IPV4_LEASE */},
+{   0,          IPC_SST_LDR,0,          0,          0,          0,                      IPC_SST_LUR,IPC_SST_IDR,0,                  IPC_SST_IDR,    /* LINKUP */               },
+{   0,          IPC_SST_LDR,0,          0,          0,          0,                      0,          0,          IPC_SST_IUI,        0,              /* IPV4_LEASE */           },
+{   0,          IPC_SST_LDR,0,          0,          0,          IPC_SST_NA,             IPC_SST_IUR,0,          0,                  0,              /* PRE_IPV4_RELOCATE */    },
+{   0,          0,          0,          0,          0,          0,                      IPC_SST_IUR,0,          0,                  0,              /* IP_REVOKE */    },
+};
+
+static module_type ipc_link_up_indication_handler;
+static module_type ipc_ip_up_indication_handler;
+static ipc_session_saved_map_t g_saved_session_map[IPC_SESSION_SAVED_MAP_NUM] = {0};
+
+/*------------------------------------------------------------------------------
+ * Private functions.
+ *----------------------------------------------------------------------------*/
+static kal_int32 ipc_new_id(ipc_netif_t *netif)
+{
+    kal_int32   ip_id = -1;
+    kal_int32   idx;
+
+    /*
+     * No need to protect ipc_ids_s[] if only one possible context.
+     */
+    IPC_ASSERT(KAL_FALSE == kal_if_hisr());
+    IPC_UT_ASSERT( (ipc_is_in_reset() || MOD_IPCORE == kal_get_active_module_id()),
+                    IPC_UT_NO_ERROR );
+
+    /*
+     * If the associated netif has a valid ip_id (e.g. IPv4 + IPv6 case), use it.
+     */
+    IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+    if (netif) {
+        ip_id = ipc_map_netif_to_ip_id(netif);
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+    }
+
+    /*
+     * Otherwise, select minimal ip_id available.
+     */
+    if (ip_id < 0) {
+        for (idx = 0; idx < IPC_MAX_IP_ID_CNT; idx++) {
+            if (!ipc_ids_s[idx]) {
+                ipc_ids_s[idx] = KAL_TRUE;
+                ip_id = idx;
+                break;
+            }
+        }
+    }
+    return ip_id;
+}
+
+static void ipc_del_id(kal_int32 ip_id)
+{
+    /* No need to protect ipc_ids_s[] if only one possible context. */
+    IPC_ASSERT(KAL_FALSE == kal_if_hisr());
+    IPC_UT_ASSERT( (ipc_is_in_reset() || MOD_IPCORE == kal_get_active_module_id()),
+                    IPC_UT_NO_ERROR );
+
+    if ((ip_id >= 0) && (ip_id < IPC_MAX_IP_ID_CNT)) {
+        ipc_ids_s[ip_id] = KAL_FALSE;
+    }
+}
+
+/*------------------------------------------------------------------------------
+ * Public functions.
+ *----------------------------------------------------------------------------*/
+void ipc_object_init(void)
+{
+    kal_uint32      idx = 0;
+
+    kal_mem_set(ipc_netifs_s, 0, sizeof(ipc_netifs_s));
+    for (idx = 0; idx < IPC_MAX_NETIF_CNT; idx++) {
+        ipc_netifs_s[idx].bit_id = (1ULL << idx);
+        ipc_netifs_s[idx].object_idx = idx;
+    }
+
+    ipc_netif_ul_reload_retry_s = 0;
+
+    kal_mem_set(ipc_sessions_s, 0, sizeof(ipc_sessions_s));
+    kal_mem_set(ipc_ids_s, 0, sizeof(ipc_ids_s));
+
+    for (idx = 0; idx < IPC_SESSION_SAVED_MAP_NUM; idx++) {
+        kal_mem_set(&g_saved_session_map[idx], 0, sizeof(ipc_session_saved_map_t));
+    }
+
+    ipc_link_up_indication_handler = MOD_IPCORE;
+    ipc_ip_up_indication_handler = MOD_IPCORE;
+}
+
+ipc_netif_t *ipc_find_netif(kal_uint32 netif_id)
+{
+    ipc_netif_t     *netif;
+    kal_uint32       idx;
+
+    for (idx = 0; idx < IPC_MAX_NETIF_CNT; idx++) {
+        netif = &(ipc_netifs_s[idx]);
+        IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+        if (netif) {
+            if (netif->config.netif_id == netif_id) {
+                return netif;
+            } else {
+                IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+            }
+        }
+    }
+    return NULL;
+}
+
+ipc_netif_t *ipc_find_netif_by_bit_id(kal_uint64 bit_id)
+{
+    ipc_netif_t     *netif;
+    kal_uint32       min = 0;
+    kal_uint32       max = IPC_MAX_NETIF_CNT - 1;
+    kal_uint32       cut;
+
+    do {
+        cut = ((max + min) >> 1);
+        netif = &(ipc_netifs_s[cut]);
+
+        if (bit_id == netif->bit_id) {
+            IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+            if (netif) {
+                return netif;
+            } else {
+                break;
+            }
+        } else if (bit_id < netif->bit_id) {
+            max = cut - 1;
+        } else {
+            min = cut + 1;
+        }
+    } while (min <= max);
+
+    return NULL;
+}
+
+ipc_netif_t *ipc_find_netif_by_object_id(kal_uint32 object_idx)
+{
+    ipc_netif_t     *netif = &ipc_netifs_s[object_idx];
+
+    IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+    return netif;
+}
+
+/* Should be spinlock protect from caller function with p_netif */
+static kal_bool ipc_session_save_netif_map(ipc_netif_t *p_netif, kal_uint8 ip_type)
+{
+    kal_uint32 i = 0;
+    kal_uint32 idx = 0;
+    kal_uint32 pdn_id = 0;
+    kal_bool is_matched = KAL_FALSE;
+    ipc_session_t *p_session = NULL;
+
+    IPC_ASSERT(NULL != p_netif);
+
+    for (i = 0; i < IPC_SESSION_SAVED_MAP_NUM; i++) {
+        if (KAL_FALSE == g_saved_session_map[i].is_saved) {
+            kal_mem_cpy(&(g_saved_session_map[i].netif_cfg), &(p_netif->config), sizeof(ipc_conf_t));
+            g_saved_session_map[i].session_cnt = p_netif->session_cnt;
+
+            if (ip_type != IPC_IP_TYPE_MIXED) {
+                idx = ipc_session_type_hash(ip_type);
+                g_saved_session_map[i].p_session_map[idx] = p_netif->session_map[idx];
+                p_session = (ipc_session_t * )g_saved_session_map[i].p_session_map[idx];
+            } else {
+                g_saved_session_map[i].p_session_map[0] = p_netif->session_map[0];
+                g_saved_session_map[i].p_session_map[1] = p_netif->session_map[1];
+                p_session = (ipc_session_t * )g_saved_session_map[i].p_session_map[0];
+            }
+            pdn_id = p_session->context;
+            g_saved_session_map[i].is_saved = KAL_TRUE;
+            is_matched = KAL_TRUE;
+
+            hif_trace_info(IPC_TR_SAVED_PDN_MAPPING, __FUNCTION__, pdn_id, p_netif->config.netif_id);
+            break;
+        }
+    }
+
+    return is_matched;
+}
+
+void ipc_session_send_restore_netif_ind(kal_uint32 netif_id, kal_uint8 ip_type, kal_bool is_link_update, kal_bool is_up)
+{
+    ipc_restore_netif_struct_t *p_param = NULL;
+
+    p_param = (ipc_restore_netif_struct_t *)construct_local_para(sizeof(ipc_restore_netif_struct_t), TD_RESET);
+    IPC_ASSERT(NULL != p_param);
+
+    p_param->netif_id = netif_id;
+    p_param->ip_type = ip_type;
+    p_param->is_link_update = is_link_update;
+    p_param->is_up = is_up;
+
+    msg_send6(kal_get_active_module_id(), /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_IPCORE_RESTORE_NETIF_IND, /* msg_id */
+              (struct local_para_struct *)p_param, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+
+    return;
+}
+
+/* Should be spinlock protect from caller function with p_netif */
+kal_bool ipc_session_restore_netif_map(ipc_netif_t *p_netif, kal_uint8 *p_ip_type)
+{
+    kal_uint32 i = 0;
+    ipc_session_t *p_session = NULL;
+    kal_bool ret = KAL_FALSE;
+
+    IPC_ASSERT(NULL != p_netif);
+    IPC_ASSERT(NULL != p_ip_type);
+
+    for (i = 0; i < IPC_SESSION_SAVED_MAP_NUM; i++) {
+        if (KAL_TRUE == g_saved_session_map[i].is_saved) {
+            if (p_netif->config.netif_id == g_saved_session_map[i].netif_cfg.netif_id) {
+                kal_mem_cpy(&(p_netif->config), &(g_saved_session_map[i].netif_cfg), sizeof(ipc_conf_t));
+                p_netif->session_cnt = g_saved_session_map[i].session_cnt;
+                p_netif->session_map[0] = g_saved_session_map[i].p_session_map[0];
+                p_netif->session_map[1] = g_saved_session_map[i].p_session_map[1];
+
+                if (1 == p_netif->session_cnt) {
+                    if (NULL != p_netif->session_map[0]) {
+                        p_session = (ipc_session_t *)p_netif->session_map[0];
+                        p_session->netif = (ipc_netif_t *)p_netif;
+                        *p_ip_type = p_session->type;
+                    } else if (NULL != p_netif->session_map[1]) {
+                        p_session = (ipc_session_t *)p_netif->session_map[1];
+                        p_session->netif = (ipc_netif_t *)p_netif;
+                        *p_ip_type = p_session->type;
+                    } else {
+                        /* it should not exist two session context are NULL */
+                        IPC_ASSERT(KAL_FALSE);
+                    }
+                } else if ((2 == p_netif->session_cnt) && (NULL != p_netif->session_map[1])) {
+                    p_session = (ipc_session_t *)p_netif->session_map[1];
+                    p_session->netif = (ipc_netif_t *)p_netif;
+                    *p_ip_type = p_session->type;
+                } else {
+                    /* it should not exist two session context are NULL */
+                    IPC_ASSERT(KAL_FALSE);
+                }
+
+                hif_trace_info(IPC_TR_RESTORE_PDN_MAPPING, __FUNCTION__, p_session->context, p_netif->config.netif_id);
+
+                kal_mem_set(&g_saved_session_map[i], 0, sizeof(ipc_session_saved_map_t));
+                g_saved_session_map[i].is_saved = KAL_FALSE;
+                ret = KAL_TRUE;
+            }
+        }
+    }
+
+    return ret;
+}
+
+static void ipc_session_delete_saved_map(ipc_session_t *p_session)
+{
+    kal_uint32 i = 0;
+    kal_uint32 idx = 0;
+    ipc_session_t *p_saved_session = NULL;
+
+    IPC_ASSERT(NULL != p_session);
+    IPC_R_LOCK_OBJECT(p_session, ipc_spinlock_g);
+
+    for (i = 0; i < IPC_SESSION_SAVED_MAP_NUM; i++) {
+        if (KAL_TRUE == g_saved_session_map[i].is_saved) {
+            if (0 < g_saved_session_map[i].session_cnt) {
+                idx = ipc_session_type_hash(p_session->type);
+                p_saved_session = (ipc_session_t *)g_saved_session_map[i].p_session_map[idx];
+                if (p_saved_session->context == p_session->context) {
+                    /* unbind pdn matched saved pdn, we will delete it */
+                    kal_mem_set(&g_saved_session_map[i], 0, sizeof(ipc_session_saved_map_t));
+                    g_saved_session_map[i].is_saved = KAL_FALSE;
+                    hif_trace_info(IPC_TR_DELETE_PDN_MAPPING, __FUNCTION__, p_session->context);
+                }
+            }
+        }
+    }
+
+    IPC_R_UNLOCK_OBJECT(p_session, ipc_spinlock_g);
+    return;
+}
+
+static void ipc_session_update_saved_map(ipc_session_t *p_old_session, kal_uint32 new_session_context)
+{
+    kal_uint32 i = 0;
+    kal_uint32 idx = 0;
+    ipc_session_t *p_saved_session = NULL;
+
+    IPC_ASSERT(NULL != p_old_session);
+    IPC_R_LOCK_OBJECT(p_old_session, ipc_spinlock_g);
+
+    for (i = 0; i < IPC_SESSION_SAVED_MAP_NUM; i++) {
+        if (KAL_TRUE == g_saved_session_map[i].is_saved) {
+            if (0 < g_saved_session_map[i].session_cnt) {
+                idx = ipc_session_type_hash(p_old_session->type);
+                p_saved_session = (ipc_session_t *)g_saved_session_map[i].p_session_map[idx];
+                if (p_saved_session->context == p_old_session->context) {
+                    /* rebind pdn matched saved pdn, we will update it with new pdn */
+                    p_saved_session->context = new_session_context;
+                    hif_trace_info(IPC_TR_UPDATED_PDN_MAPPING, __FUNCTION__, p_saved_session->context, new_session_context);
+                }
+            }
+        }
+    }
+
+    IPC_R_UNLOCK_OBJECT(p_old_session, ipc_spinlock_g);
+    return;
+}
+
+ipc_netif_t *ipc_new_netif(ipc_conf_t *config)
+{
+    ipc_netif_t     *netif;
+    kal_uint32       idx;
+
+    netif = ipc_find_netif(config->netif_id);
+    if (NULL == netif) {
+        for (idx = 0; idx < IPC_MAX_NETIF_CNT; idx++) {
+            netif = &(ipc_netifs_s[idx]);
+            if (!IPC_IS_VALID_OBJECT(netif)) {
+                IPC_INIT_OBJECT_BEGIN(netif, ipc_spinlock_g);
+
+                kal_mem_cpy( &(netif->config), config, sizeof(ipc_conf_t) );
+                netif->session_cnt = 0;
+                kal_mem_set( netif->session_map, 0, sizeof(netif->session_map) );
+
+                IPC_INIT_OBJECT_END(netif, ipc_spinlock_g);
+
+                ipc_set_netif_ul_reload_retry(netif, KAL_FALSE);
+                hif_trace_info(IPC_TR_NETIF_ATTACHED, config->module_id, config->netif_id);
+                return netif;
+            }
+        }
+        hif_trace_error(IPC_TR_NETIF_ATTACH_OUT_OF_SPACE, config->module_id, config->netif_id);
+    } else {
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+        hif_trace_error(IPC_TR_NETIF_ATTACH_DUPLICATED, config->module_id, config->netif_id);
+    }
+
+    return NULL;
+}
+
+kal_bool ipc_del_netif(ipc_netif_t *netif)
+{
+    kal_uint32      idx;
+    ipc_session_t  *session;
+
+    if (IPC_IS_VALID_OBJECT(netif)) {
+        ipc_set_netif_ul_reload_retry(netif, KAL_FALSE);
+        IPC_DEINIT_OBJECT_BEGIN(netif, ipc_spinlock_g);
+        IPC_ASSERT(netif);
+
+        for (idx = 0; idx < IPC_SESSION_MAP_SIZE; idx++) {
+            session =  netif->session_map[idx];
+
+            IPC_W_LOCK_OBJECT(session, ipc_spinlock_g);
+            if (session)
+            {
+                if (netif->config.features & IPC_F_KEEP_PDN_MAPPING) {
+                    if (KAL_FALSE == ipc_session_save_netif_map(netif, session->type)) {
+                        hif_trace_error(IPC_TR_SAVED_PDN_MAPPING_FAILED, __FUNCTION__);
+                    }
+                }
+
+                session->netif = NULL;
+                IPC_W_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            }
+        }
+
+        hif_trace_info(IPC_TR_NETIF_DETACHED, netif->config.module_id, netif->config.netif_id);
+        IPC_DEINIT_OBJECT_END(netif, ipc_spinlock_g);
+        return KAL_TRUE;
+    } else {
+        hif_trace_error(IPC_TR_NETIF_DETACH_INVALID);
+        return KAL_FALSE;
+    }
+}
+
+kal_bool ipc_query_netif_list(ipc_netif_list_t *netif_list_p)
+{
+    ipc_netif_t *netif;
+    kal_uint32 idx;
+
+    IPC_ASSERT(netif_list_p);
+
+    hif_trace_info(IPC_TR_QUERY_NETIF_LIST_START, netif_list_p);
+    if (netif_list_p)
+    {
+        kal_mem_set(netif_list_p, 0, sizeof(ipc_netif_list_t));
+
+        for (idx = 0; idx < IPC_MAX_NETIF_CNT; idx++) {
+            netif = &(ipc_netifs_s[idx]);
+            IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+            if (netif) {
+                netif_list_p->list[netif_list_p->netif_cnt].netif_id = netif->config.netif_id;
+                netif_list_p->netif_cnt ++;
+                IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+                hif_trace_info(IPC_TR_QUERY_NETIF_LIST_INFO,    netif_list_p->netif_cnt,
+                                                                netif_list_p->list[netif_list_p->netif_cnt-1].netif_id);
+            }
+        }
+
+        hif_trace_info(IPC_TR_QUERY_NETIF_LIST_SUCCESS, netif_list_p->netif_cnt);
+        return KAL_TRUE;
+    }
+    hif_trace_error(IPC_TR_QUERY_NETIF_LIST_FAILED);
+    return KAL_FALSE;
+}
+
+void ipc_update_link_up_ind_handler(module_type module_id)
+{
+    hif_trace_info(IPC_TR_UPDATE_LINK_UP_IND_HDLR_START, module_id);
+    ipc_link_up_indication_handler = module_id;
+}
+
+void ipc_update_ip_up_ind_handler(module_type module_id)
+{
+    hif_trace_info(IPC_TR_UPDATE_IP_UP_IND_HDLR_START, module_id);
+    ipc_ip_up_indication_handler = module_id;
+}
+
+void ipc_indicate_netif_link_change(ipc_netif_t *netif, kal_uint8 ip_type, kal_bool link_update, kal_bool is_up)
+{
+    ipc_link_handshake_msg_t    *link_handshake_msg_p;
+    module_type                 src_mod_id;
+    module_type                 dest_mod_id;
+    msg_type                    message_type;
+    kal_uint32                  netif_id;
+    kal_int32                   ip_id;
+
+    if (NULL == netif) return;
+
+    /* IP CORE supports LINK_UP_IND / IP_UP_IND only */
+    IPC_ASSERT(KAL_TRUE == is_up);
+
+    IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+    if (netif) {
+        netif_id = netif->config.netif_id;
+        ip_id = ipc_map_netif_to_ip_id(netif);
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+        link_handshake_msg_p = (ipc_link_handshake_msg_t *)construct_local_para(sizeof(ipc_link_handshake_msg_t), TD_RESET);
+        IPC_ASSERT(link_handshake_msg_p);
+
+        link_handshake_msg_p->netif_id = netif_id;
+        link_handshake_msg_p->ip_id = ip_id;
+        link_handshake_msg_p->ip_type = ip_type;
+
+        if (KAL_TRUE == link_update)
+        {   /* To update Link status */
+            src_mod_id      = (MOD_IPCORE == ipc_link_up_indication_handler)?MOD_NIL:MOD_IPCORE;
+            dest_mod_id     = ipc_link_up_indication_handler;
+            message_type    = MSG_ID_IPCORE_LINK_UP_IND;
+        } else
+        {   /* To update IP status */
+            src_mod_id      = (MOD_IPCORE == ipc_ip_up_indication_handler)?MOD_NIL:MOD_IPCORE;
+            dest_mod_id     = ipc_ip_up_indication_handler;
+            message_type    = MSG_ID_IPCORE_IP_UP_IND;
+        }
+
+        msg_send6(src_mod_id, /* src_mod_id */
+                  dest_mod_id, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  message_type, /* msg_id */
+                  (struct local_para_struct *)link_handshake_msg_p, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+    }
+}
+
+void ipc_notify_netif_link_change(ipc_netif_t *netif, kal_uint8 ip_type, kal_bool link_update, kal_bool is_up)
+{
+    ipc_link_req_t *p_link_req = NULL;
+    void           *p_context = NULL;
+    module_type     module_id = 0;
+    msg_type        message_type = 0;
+    ipc_ntfy_type_e notify_type = IPC_NTFY_TYPE_INVALID;
+
+    if (NULL == netif) {
+        return;
+    }
+
+    IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+    if (netif) {
+        p_context = netif->config.callback_context;
+        module_id = netif->config.module_id;
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+        p_link_req = (ipc_link_req_t *)construct_local_para(sizeof(ipc_link_req_t), TD_RESET);
+        IPC_ASSERT(p_link_req);
+
+        p_link_req->callback_context = p_context;
+        p_link_req->ip_type = ip_type;
+
+        if (KAL_TRUE == link_update) {
+            /* To update Link status */
+            message_type = is_up ? MSG_ID_IPCORE_LINK_UP_REQ : MSG_ID_IPCORE_LINK_DOWN_REQ;
+            notify_type = is_up ? IPC_NTFY_TYPE_LINK_UP : IPC_NTFY_TYPE_LINK_DOWN;
+        } else {
+            /* To update IP status */
+            message_type = is_up ? MSG_ID_IPCORE_IP_UP_REQ : MSG_ID_IPCORE_IP_DOWN_REQ;
+            notify_type = is_up ? IPC_NTFY_TYPE_IP_UP : IPC_NTFY_TYPE_IP_DOWN;
+        }
+
+        /* Callback for notifications */
+        ipc_ntfy_do_event_cbk(netif, notify_type);
+
+#ifdef ATEST_SYS_IPCORE
+        ipc_ut_msg_send6(MOD_IPCORE, /* src_mod_id */
+                         module_id, /* dest_mod_id */
+                         IPCORE_SAP, /* sap_id */
+                         message_type, /* msg_id */
+                         (struct local_para_struct *) p_link_req, /* local_para_ptr */
+                         NULL); /* peer_buff_ptr */
+#else
+        msg_send6(MOD_IPCORE, /* src_mod_id */
+                  module_id, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  message_type, /* msg_id */
+                  (struct local_para_struct *)p_link_req, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+#endif
+    }
+
+    return;
+}
+
+void ipc_notify_all_netif_link_change(kal_uint8 ip_type, kal_bool link_up)
+{
+    kal_uint32      idx;
+    ipc_netif_t    *netif;
+
+    for (idx = 0; idx < IPC_MAX_NETIF_CNT; idx++) {
+        netif = &(ipc_netifs_s[idx]);
+
+        IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+        if (netif) {
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+
+            ipc_notify_netif_link_change(netif, ip_type, KAL_TRUE, link_up);
+        }
+    }
+}
+
+kal_int32 ipc_map_netif_to_ip_id(ipc_netif_t *netif)
+{
+    ipc_session_t  *session;
+    kal_uint32      idx;
+    kal_int32       ip_id;
+
+    IPC_ASSERT(IPC_IS_VALID_OBJECT(netif));
+
+    if (netif->session_cnt > 0) {
+        for (idx = 0; idx < IPC_SESSION_MAP_SIZE; idx++) {
+            session =  netif->session_map[idx];
+            IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+            if (session) {
+                ip_id = session->ip_id;
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                return ip_id;
+            }
+        }
+    }
+
+    return -1;
+}
+
+kal_int32 ipc_map_netif_to_pdn_id(ipc_netif_t *netif, kal_uint8 ip_type)
+{
+    ipc_session_t  *session = NULL;
+    kal_uint32      pdn_id = 0;
+    kal_uint32      idx = 0;
+
+    IPC_ASSERT(IPC_IS_VALID_OBJECT(netif));
+
+    if (netif->session_cnt > 0) {
+        idx = ipc_session_type_hash(ip_type);
+
+        if ((0 <= idx) && (idx < 2)) {
+            session =  netif->session_map[idx];
+        } else {
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            return IPC_INVALID_PDN_ID;
+        }
+
+        IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+        if (session) {
+            pdn_id = session->context;
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            return pdn_id;
+        }
+    }
+
+    return IPC_INVALID_PDN_ID;
+}
+
+void ipc_set_netif_ul_reload_retry(ipc_netif_t *netif, kal_bool need_ul_reload)
+{
+    kal_uint64       netif_bit_id = netif->bit_id;
+    kal_uint64       set_reload;
+
+    IPC_ASSERT(IPC_IS_VALID_OBJECT(netif));
+
+    hif_data_trace(MD_TRC_IPC_UL_RELOAD_RETRY, need_ul_reload, netif, netif->config.netif_id, netif->config.ipc_ul_reload_callback_t, ipc_netif_ul_set_need_reload_s);
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+
+    /*
+     * Check if netif_ul_set_need_reload has been set
+     * since the last time IPCORE called the netif reload cbk.
+     */
+    set_reload = ipc_netif_ul_set_need_reload_s & netif_bit_id;
+    if (  ((need_ul_reload) || (set_reload)) &&
+          (netif->config.ipc_ul_reload_callback_t) )
+    {
+        ipc_netif_ul_reload_retry_s |= (netif_bit_id);
+    } else
+    {
+        ipc_netif_ul_reload_retry_s &= (~(netif_bit_id));
+    }
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    if ((!need_ul_reload) && (set_reload))
+    {
+        hif_data_trace(MD_TRC_IPC_UL_RELOAD_RETRY_RACE_COND, 0, need_ul_reload, set_reload, ipc_netif_ul_reload_retry_s);
+    } else
+    {
+        hif_data_trace(MD_TRC_IPC_UL_RELOAD_RETRY_FLAG, 0, ipc_netif_ul_reload_retry_s, ipc_netif_ul_set_need_reload_s);
+    }
+}
+
+void ipc_set_netif_ul_set_need_reload(ipc_netif_t *netif, kal_bool need_ul_reload)
+{
+    kal_uint64       netif_bit_id = netif->bit_id;
+
+    IPC_ASSERT(IPC_IS_VALID_OBJECT(netif));
+
+    hif_data_trace(MD_TRC_IPC_UL_SET_NEED_RELOAD, need_ul_reload, netif, netif->config.netif_id, netif->config.ipc_ul_reload_callback_t);
+
+    IPC_SPIN_LOCK(ipc_spinlock_g);
+    if ((need_ul_reload) && (netif->config.ipc_ul_reload_callback_t))
+    {
+        ipc_netif_ul_set_need_reload_s |= (netif_bit_id);
+    } else
+    {
+        ipc_netif_ul_set_need_reload_s &= (~(netif_bit_id));
+    }
+    IPC_SPIN_UNLOCK(ipc_spinlock_g);
+
+    hif_data_trace(MD_TRC_IPC_UL_SET_NEED_RELOAD_FLAG, 0, ipc_netif_ul_set_need_reload_s);
+}
+
+kal_uint64 ipc_get_all_netif_ul_reload_retry(void)
+{
+    return ipc_netif_ul_reload_retry_s;
+}
+
+kal_bool ipc_update_session_state(ipc_session_t *session, ipc_session_state_e session_state)
+{
+    ipc_session_state_e org_session_state;
+    ipc_netif_t        *netif;
+    kal_uint8           type;
+    kal_bool            retval = KAL_TRUE;
+
+    hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_START, session, session_state);
+
+    if (session)
+    {
+        IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+        if (session)
+        {
+            org_session_state = session->state;
+            netif = session->netif;
+            type = session->type;
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+            hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_ORG_AND_NEW, session, type, netif, org_session_state, session_state);
+
+            /* Update state */
+            IPC_W_LOCK_OBJECT(session, ipc_spinlock_g);
+            if (session) {
+                session->state = session_state;
+                IPC_W_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_TRANSITION_SUCCESS, session, session_state);
+            } else
+            {   /* Session write fail */
+                hif_trace_error(IPC_TR_UPDATE_SESSION_STATE_WRITE_FAIL, session, session_state);
+                IPC_ASSERT(0);
+                retval = KAL_FALSE;
+            }
+
+            /* Run corresponding state transition action */
+            if (    (org_session_state > IPC_SESSION_STATE_MIN) &&
+                    (org_session_state < IPC_SESSION_STATE_MAX) &&
+                    (session_state > IPC_SESSION_STATE_MIN) &&
+                    (session_state < IPC_SESSION_STATE_MAX)         )
+            {
+                switch (session_transition_action_table[org_session_state][session_state])
+                {
+                    case IPC_SST_NA:
+                        hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_SST_NA, session, org_session_state, session_state);
+                        break;
+                    case IPC_SST_LUI:
+                        hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_SST_LUI, session, org_session_state, session_state);
+                        ipc_indicate_netif_link_change(netif, type, KAL_TRUE, KAL_TRUE);
+                        break;
+                    case IPC_SST_LUR:
+                        hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_SST_LUR, session, org_session_state, session_state, netif, type);
+                        ipc_notify_netif_link_change(netif, type, KAL_TRUE, KAL_TRUE);
+                        break;
+                    case IPC_SST_LDR:
+                        hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_SST_LDR, session, org_session_state, session_state, netif, type);
+                        ipc_notify_netif_link_change(netif, type, KAL_TRUE, KAL_FALSE);
+                        break;
+                    case IPC_SST_IUI:
+                        hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_SST_IUI, session, org_session_state, session_state);
+                        ipc_indicate_netif_link_change(netif, type, KAL_FALSE, KAL_TRUE);
+                        break;
+                    case IPC_SST_IUR:
+                        hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_SST_IUR, session, org_session_state, session_state, netif, type);
+                        ipc_notify_netif_link_change(netif, type, KAL_FALSE, KAL_TRUE);
+                        break;
+                    case IPC_SST_IDR:
+                        hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_SST_IDR, session, org_session_state, session_state, netif, type);
+                        ipc_notify_netif_link_change(netif, type, KAL_FALSE, KAL_FALSE);
+                        break;
+                    default:
+                        /* Illegal state transition */
+                        hif_trace_error(IPC_TR_UPDATE_SESSION_STATE_ILLEGAL_TRANSITION, session, org_session_state, session_state, session_transition_action_table[org_session_state][session_state]);
+                        IPC_ASSERT(0);
+                        retval = KAL_FALSE;
+                }
+            } else
+            {   /* Invalid state */
+                hif_trace_error(IPC_TR_UPDATE_SESSION_STATE_OUT_OF_RANGE, session, org_session_state, session_state, IPC_SESSION_STATE_MIN, IPC_SESSION_STATE_MAX);
+                IPC_ASSERT(0);
+                retval = KAL_FALSE;
+            }
+
+        } else
+        {   /* Session read fail */
+            hif_trace_error(IPC_TR_UPDATE_SESSION_STATE_READ_FAIL, session);
+            retval = KAL_FALSE;
+        }
+    }else
+    {   /* Session check fail */
+        hif_trace_error(IPC_TR_UPDATE_SESSION_STATE_CHK_FAIL, session);
+        retval = KAL_FALSE;
+    }
+
+    hif_trace_info(IPC_TR_UPDATE_SESSION_STATE_END, session, session_state, retval);
+
+    return retval;
+}
+
+ipc_session_t *ipc_find_session_by_context(kal_uint32 session_context)
+{
+    ipc_session_t   *session;
+
+    IPC_CONTEXT_TO_SESSION(session_context, session);
+    IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+    if (session) {
+        IPC_ASSERT(session->context == session_context);
+        return session;
+    }
+    return NULL;
+}
+
+ipc_session_t *ipc_find_session_by_netif(ipc_netif_t *netif, kal_uint8 session_type)
+{
+    kal_uint32     idx;
+    ipc_session_t *session;
+    ipc_netif_t   *netif_local;
+
+    session = NULL;
+    netif_local = netif;
+
+    IPC_R_LOCK_OBJECT(netif_local, ipc_spinlock_g);
+    if (netif_local)
+    {
+        idx = ipc_session_type_hash((session_type == IPC_IP_TYPE_MIXED) ? IPC_IP_TYPE_IPV4: session_type);
+        IPC_ASSERT(idx < IPC_SESSION_MAP_SIZE);
+        session = netif_local->session_map[idx];
+        IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+        IPC_R_UNLOCK_OBJECT(netif_local, ipc_spinlock_g);
+    }
+
+    return session;
+}
+
+ipc_session_t *ipc_find_session_by_ip_id(kal_int32 ip_id, kal_uint8 session_type)
+{
+    ipc_netif_t     *netif;
+    ipc_session_t   *session;
+    ipc_session_t   *session_found = NULL;
+    kal_uint32       idx1, idx2;
+
+    IPC_ASSERT(0 <= ip_id);
+
+    for (idx1 = 0; idx1 < IPC_MAX_NETIF_CNT && NULL == session_found; idx1++) {
+        netif = &(ipc_netifs_s[idx1]);
+
+        IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+        if (netif) {
+
+            idx2 = ipc_session_type_hash((session_type == IPC_IP_TYPE_MIXED) ? IPC_IP_TYPE_IPV4: session_type);
+            session = netif->session_map[idx2];
+            IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+            if (session) {
+                if ( session->ip_id == ip_id) {
+                    session_found = session;
+                    /*
+                     * Caller is expected to release session's read lock,
+                     * so don't release it here.
+                     */
+                } else {
+                    IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                }
+            }
+
+            IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+        }
+    }
+
+    return session_found;
+}
+
+ipc_session_t *ipc_new_session_internal(ipc_netif_t *netif, kal_uint32 session_context, kal_uint8 session_type, ipc_session_state_e session_state, kal_int32 ip_id)
+{
+    ipc_session_t *session = NULL;
+    kal_uint32    idx = 0;
+
+    IPC_ASSERT(IPC_IS_VALID_OBJECT(netif));
+    IPC_ASSERT(session_type == IPC_IP_TYPE_IPV4 ||
+               session_type == IPC_IP_TYPE_IPV6 ||
+               session_type == IPC_IP_TYPE_MIXED );
+    IPC_ASSERT((session_state > IPC_SESSION_STATE_MIN) &&
+               (session_state < IPC_SESSION_STATE_MAX));
+
+    hif_trace_info(IPC_TR_SESSION_BIND_START, session_context, session_type, session_state);
+
+    /*
+     * If netif already bind session, return NULL directly
+     */
+    if (session_type == IPC_IP_TYPE_MIXED) {
+        if (netif->session_map[0] || netif->session_map[1]) {
+            hif_trace_error(IPC_TR_SESSION_BIND_NETIF_BOUND_MIXED,
+                            netif,
+                            netif->config.netif_id,
+                            netif->session_map[ipc_session_type_hash(IPC_IP_TYPE_IPV4)],
+                            netif->session_map[ipc_session_type_hash(IPC_IP_TYPE_IPV6)],
+                            session_context,
+                            session_type,
+                            session_state);
+            return NULL;
+        }
+    } else {
+        idx = ipc_session_type_hash(session_type);
+        if (netif->session_map[idx]) {
+            hif_trace_error(IPC_TR_SESSION_BIND_NETIF_BOUND_SPECIFIC_IP_VER,
+                            netif,
+                            netif->config.netif_id,
+                            netif->session_map[ipc_session_type_hash(IPC_IP_TYPE_IPV4)],
+                            netif->session_map[ipc_session_type_hash(IPC_IP_TYPE_IPV6)],
+                            session_context,
+                            session_type,
+                            session_state);
+            return NULL;
+        }
+    }
+
+    /*
+     * Allocate and configure new session
+     */
+    session = ipc_find_session_by_context(session_context);
+    if (NULL == session) {
+        IPC_CONTEXT_TO_SESSION(session_context, session);
+        if (!IPC_IS_VALID_OBJECT(session)) {
+            IPC_INIT_OBJECT_BEGIN(session, ipc_spinlock_g);
+
+            session->context = session_context;
+            session->type = session_type;
+            session->dhcp4c_running = KAL_FALSE;
+            session->dhcp4c_id = 0xff;
+            session->dhcp4c_dl_filter_id = -1;
+            session->ip_id = (ip_id == -1) ? ipc_new_id(netif) : ip_id;
+            session->netif = netif;
+            session->state = session_state;
+
+            /*
+             * If there's no IP session conflict (i.e. the same type),
+             * no need to acquire a write lock on netif.
+             */
+            if (session_type != IPC_IP_TYPE_MIXED) {
+                idx = ipc_session_type_hash(session_type);
+                IPC_ASSERT(netif->session_map[idx] == NULL);
+                netif->session_map[idx] = session;
+                netif->session_cnt++;
+            } else {
+                IPC_ASSERT(netif->session_map[0] == NULL && netif->session_map[1] == NULL);
+                netif->session_map[0] = session;
+                netif->session_map[1] = session;
+                netif->session_cnt += 2;
+            }
+
+            IPC_INIT_OBJECT_END(session, ipc_spinlock_g);
+            hif_trace_info(IPC_TR_SESSION_BOUND, session_context, session_type, session_state, session->ip_id);
+            return session;
+        } else {
+            hif_trace_error(IPC_TR_SESSION_BIND_OUT_OF_SPACE, session_context, session_type,session_state);
+        }
+    } else {
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+        hif_trace_error(IPC_TR_SESSION_BIND_DUPLICATED, session_context, session_type, session_state);
+    }
+
+    return NULL;
+}
+
+ipc_session_t *ipc_new_session(ipc_netif_t *netif, kal_uint32 session_context, kal_uint8 session_type, ipc_session_state_e session_state)
+{
+    return ipc_new_session_internal(netif, session_context, session_type, session_state, -1);
+}
+
+void ipc_del_session_internal(ipc_session_t *session, kal_bool to_del_ip_id)
+{
+    ipc_netif_t    *netif;
+    kal_uint32      idx;
+
+    IPC_DEINIT_OBJECT_BEGIN(session, ipc_spinlock_g);
+    if (session) {
+
+        netif = session->netif;
+        IPC_W_LOCK_OBJECT(netif, ipc_spinlock_g);
+        if (netif) {
+            if (session->type != IPC_IP_TYPE_MIXED) {
+                idx = ipc_session_type_hash(session->type);
+                IPC_ASSERT(netif->session_map[idx] == session);
+                netif->session_map[idx] = NULL;
+                netif->session_cnt--;
+            } else {
+                IPC_ASSERT(netif->session_map[0] == session && netif->session_map[1] == session);
+                netif->session_map[0] = NULL;
+                netif->session_map[1] = NULL;
+                netif->session_cnt = 0;
+            }
+            if (to_del_ip_id) {
+                to_del_ip_id = (netif->session_cnt == 0);
+            }
+
+            IPC_W_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+        }
+
+        if (to_del_ip_id) {
+            ipc_del_id(session->ip_id);
+        }
+
+        hif_trace_info(IPC_TR_SESSION_DEACTIVATED, session->context, session->type, session->ip_id);
+        IPC_DEINIT_OBJECT_END(session, ipc_spinlock_g);
+    } else {
+        hif_trace_error(IPC_TR_SESSION_DEACTIVATE_INVALID_SESSION);
+    }
+}
+
+void ipc_del_session(ipc_session_t *session)
+{
+    ipc_session_delete_saved_map(session);
+    ipc_del_session_internal(session, KAL_TRUE);
+}
+
+ipc_session_t *ipc_replace_session(ipc_netif_t *netif, ipc_session_t *old_session, kal_uint32 new_session_context, kal_uint8 new_session_type, ipc_session_state_e new_session_state)
+{
+    kal_int32       ip_id;
+    ipc_session_t  *new_session;
+
+    hif_trace_info(IPC_TR_SESSION_BIND_START, new_session_context, new_session_type, new_session_state);
+
+    IPC_R_LOCK_OBJECT(old_session, ipc_spinlock_g);
+    if (old_session) {
+        ip_id = old_session->ip_id;
+        IPC_R_UNLOCK_OBJECT(old_session, ipc_spinlock_g);
+
+        ipc_session_update_saved_map(old_session, new_session_context);
+        ipc_del_session_internal(old_session, KAL_FALSE);
+        new_session = ipc_new_session_internal(netif, new_session_context, new_session_type, new_session_state, ip_id);
+        if (!new_session) {
+            /* Replace session failed. Need to check whether to delete ip_id or not. */
+            IPC_R_LOCK_OBJECT(netif, ipc_spinlock_g);
+            if (netif) {
+                if (netif->session_cnt == 0) {
+                    ipc_del_id(ip_id);
+                }
+                IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+            } else {
+                hif_trace_error(IPC_TR_SESSION_REPLACE_NETIF_RLOCK_FAIL);
+            }
+
+            return NULL;
+        }
+
+        hif_trace_info(IPC_TR_SESSION_REPLACED, new_session_context, new_session_type, new_session_state, ip_id);
+        return new_session;
+    } else {
+        hif_trace_error(IPC_TR_SESSION_REPLACE_SESSION_RLOCK_FAIL);
+    }
+
+    return NULL;
+}
diff --git a/mcu/middleware/hif/ipcore/src/ipc_task.c b/mcu/middleware/hif/ipcore/src/ipc_task.c
new file mode 100644
index 0000000..fd1a579
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_task.c
@@ -0,0 +1,307 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_task.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IP Core task implementation.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "ipc_defs.h"
+#include "ipc_debug.h"
+#include "ipc_utils.h"
+#include "ipc_data.h"
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+#define IPC_MOD_CNT (sizeof(ipc_module_list_g) / sizeof(module_type))
+
+/*------------------------------------------------------------------------------
+ * Private data structure.
+ *----------------------------------------------------------------------------*/
+typedef kal_bool (*ipc_init_func_t)(void);
+typedef void (*ipc_on_ilm_func_t)(ilm_struct *);
+typedef kal_bool (*ipc_on_reset_func_t)(void);
+
+/*------------------------------------------------------------------------------
+ * Private variables.
+ *----------------------------------------------------------------------------*/
+module_type ipc_module_list_g[] = {
+    #undef IPC_MODULE_ID
+    #undef IPC_MODULE_PREFIX
+    #define IPC_MODULE_ID(_id) _id,
+    #define IPC_MODULE_PREFIX(_prefix) 
+    #include "ipc_config.h"
+
+    MOD_IPCORE,
+};
+
+/*
+ * Note, each module in IP Core task with prefix xyz must implement the following functions:
+ *
+ * 1. module initializeation function:
+ *    kal_bool xyz_init(void);
+ *
+ * 2. ilm handler:
+ *    void xyz_on_ilm(ilm_struct *ilm);
+ *
+ * 3. reset handler:
+ *    kal_bool xyz_reset(void);
+ */
+#undef IPC_MODULE_ID
+#undef IPC_MODULE_PREFIX
+#define IPC_MODULE_ID(_id) 
+#define IPC_MODULE_PREFIX(_prefix) extern kal_bool _prefix ## _init (void);
+#include "ipc_config.h"
+
+const ipc_init_func_t ipc_init_func_list_g[] = {
+    #undef IPC_MODULE_ID
+    #undef IPC_MODULE_PREFIX
+    #define IPC_MODULE_ID(_id) 
+    #define IPC_MODULE_PREFIX(_prefix) _prefix ## _init,
+    #include "ipc_config.h"
+
+    ipc_init,
+};
+
+#undef IPC_MODULE_ID
+#undef IPC_MODULE_PREFIX
+#define IPC_MODULE_ID(_id) 
+#define IPC_MODULE_PREFIX(_prefix) extern void _prefix ## _on_ilm (ilm_struct *ilm);
+#include "ipc_config.h"
+
+const ipc_on_ilm_func_t ipc_ilm_func_list_g[] = {
+    #undef IPC_MODULE_ID
+    #undef IPC_MODULE_PREFIX
+    #define IPC_MODULE_ID(_id) 
+    #define IPC_MODULE_PREFIX(_prefix) _prefix ## _on_ilm,
+    #include "ipc_config.h"
+
+    ipc_on_ilm,
+};
+
+#undef IPC_MODULE_ID
+#undef IPC_MODULE_PREFIX
+#define IPC_MODULE_ID(_id) 
+#define IPC_MODULE_PREFIX(_prefix) extern kal_bool _prefix ## _reset (void);
+#include "ipc_config.h"
+
+const ipc_on_reset_func_t ipc_reset_func_list_g[] = {
+    #undef IPC_MODULE_ID
+    #undef IPC_MODULE_PREFIX
+    #define IPC_MODULE_ID(_id) 
+    #define IPC_MODULE_PREFIX(_prefix) _prefix ## _reset,
+    #include "ipc_config.h"
+
+    ipc_reset,
+};
+
+/*------------------------------------------------------------------------------
+ * Private fucntions.
+ *----------------------------------------------------------------------------*/
+static kal_bool ipc_task_init(void)
+{
+    kal_uint32  idx;
+    kal_bool    ret = KAL_TRUE;;
+
+    for (idx = 0; idx < IPC_MOD_CNT; ++idx) {
+        ret = ipc_init_func_list_g[idx]();
+        if (!ret) {
+            break;
+        }
+    }
+    return ret;
+}
+
+void ipc_dispatch_ilm(ilm_struct *ilm)
+{
+    kal_uint32  idx;
+
+    for (idx = 0; idx < IPC_MOD_CNT; ++idx) {
+        if (ilm->dest_mod_id == ipc_module_list_g[idx]) {
+            /*
+             * Switch to active module.
+             */
+            kal_set_active_module_id(ilm->dest_mod_id);
+
+            /*
+             * Dispatch ILM according to dest_mod_id.
+             */
+            ipc_ilm_func_list_g[idx](ilm);
+            break;
+        }
+    }
+
+    if (IPC_MOD_CNT == idx) {
+        /*
+         * Wrong destination.
+         */
+        hif_trace_error(IPC_TR_ILM_WRONG_DEST_MOD, ilm->dest_mod_id);
+    }
+
+    /*
+     * Free the ILM.
+     */
+    destroy_ilm(ilm);
+}
+
+static void ipc_task_main(task_entry_struct *task_entry_ptr)
+{
+    ilm_struct  current_ilm;
+
+#if IPC_PEER==IPC_PEER_NULL_DROP || IPC_PEER==IPC_PEER_NULL_LOOPBACK
+    ipc_notify_all_netif_link_change(IPC_IP_TYPE_MIXED, KAL_TRUE);
+#endif
+
+    while (1) {
+        /* 
+         * Receive message from ext queue, this may suspend.
+         */
+        if (KAL_TRUE == msg_receive_extq(&current_ilm)) {
+            ipc_dispatch_ilm(&current_ilm);
+            while (msg_receive_intq(&current_ilm)){
+                ipc_dispatch_ilm(&current_ilm);
+            }
+        }
+    }
+}
+
+#ifndef ATEST_SYS_IPCORE
+static
+#endif
+kal_bool ipc_task_reset(void)
+{
+    kal_uint32  idx;
+    kal_bool    ret = KAL_TRUE;
+
+    for (idx = 0; idx < IPC_MOD_CNT; ++idx) {
+        ret = ipc_reset_func_list_g[idx]();
+        if (!ret) {
+            break;
+        }
+    }
+    return ret;
+}
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+kal_bool ipc_create(comptask_handler_struct **handle)
+{
+    static const comptask_handler_struct info =
+    {
+        ipc_task_main,     /* task entry function */
+        ipc_task_init,     /* task initialization function */
+        ipc_task_reset,    /* task reset handler */
+    };
+
+    *handle = (comptask_handler_struct *)&info;
+    return KAL_TRUE;
+}
diff --git a/mcu/middleware/hif/ipcore/src/ipc_task_clean.c b/mcu/middleware/hif/ipcore/src/ipc_task_clean.c
new file mode 100644
index 0000000..1d8fa18
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_task_clean.c
@@ -0,0 +1,26 @@
+/*
+ * ipc_task_clean.c
+ *
+ *  Created on: 2018/10/24
+ *      Author: MTK15439
+ */
+
+#include "ipc_defs.h"
+#if defined(__MDDP_WH_SUPPORT__) || defined(__MDDP_USB_SUPPORT__)
+#include "dpfm_api.h"
+#endif
+
+void IPCore_Task_Clean_Handler(void)
+{
+#if defined(__SENSITIVE_DATA_MOSAIC__)
+    ipc_module_clean();
+    upcm_module_clean();
+#if defined(__MDDP_WH_SUPPORT__) || defined(__MDDP_USB_SUPPORT__)
+    dpfm_module_clean();
+#endif
+#ifdef __DISPATCHER_SUPPORT__
+    dispatcher_module_clean();
+#endif
+#endif
+}
+
diff --git a/mcu/middleware/hif/ipcore/src/ipc_ut.c b/mcu/middleware/hif/ipcore/src/ipc_ut.c
new file mode 100644
index 0000000..8f32406
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_ut.c
@@ -0,0 +1,26211 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_ut.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IPCORE unit test implementation.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifdef ATEST_SYS_IPCORE
+
+#include "kal_public_api.h"
+#include "sysservice_msgid.h"
+#include "intrCtrl.h"
+#include "sys_test.h"
+
+#include "upcm.h"
+#include "ipcore_upcm_struct.h"
+#include "upcm_msgid.h"
+#include "l4c_ipcore_struct.h"
+#include "l4_msgid.h"
+#include "dispatcher_msgid.h"
+#if defined(__LTM_SIMULATION_SUPPORT__)
+    #include "lms_api.h"
+#endif
+
+#include "dhcp4c_struct.h"
+#include "ipc_dhcp_adp.h"
+#include "mw_sap.h"
+#include "md_sap.h"
+#include "hif_mw_msgid.h"
+#include "dpcopro_custom.h"
+
+#include "nmu_util.h"
+#include "hmu.h"
+
+#include "ipc_defs.h"
+#include "ipc_debug.h"
+#include "ipc_utils.h"
+#include "ipc_filter.h"
+#include "ipc_enums.h"
+#include "ipc_data.h"
+#include "ipc_data_ipf.h"
+#include "sim_public_enum.h"
+
+#include "ccci_ipc_msgid.h"
+#include "pfm_api.h"
+#include "pfm_struct.h"
+#include "pfm_defs.h"
+#include "pfm_enums.h"
+#include "tmc_struct.h"
+
+#ifdef __SE7_SD8_AUTO_UT__
+    #define IPC_UT_LOG_LV           3
+#else
+    #define IPC_UT_LOG_LV           2
+#endif
+#define IPC_UT_MAX_NET_CNT          3
+#define IPC_UT_NETID_START          0x1A
+#define IPC_UT_LHIF_NETID_START     0x41A
+#define IPC_UT_DPFM_NETID_START      0x11A
+#define IPC_UT_BAD_NETIF_ID         0xc9
+#define IPC_UT_PDN_ID               0xf
+#define IPC_UT_PDN_ID_2             0xe
+#define IPC_UT_MSG_LATENCY          (1 * KAL_MILLISECS_PER_TICK)
+#define IPC_UT_INVALID_IP_ID        IPC_MAX_IP_ID_CNT
+#define IPC_UT_UL_EBI               0x1F
+#define IPC_UT_DL_EBI               0x1F
+#define IPC_UT_LOW_PRIORITY         3
+#define IPC_UT_MID_PRIORITY         2
+#define IPC_UT_HIGH_PRIORITY        1
+
+#define IPC_UT_GEN_INVALID_LEN_PKT  1
+#define IPC_INVALID_MAX_PKT_LEN     2048
+#define IPC_INVALID_PKT_LEN1        1501
+#define IPC_INVALID_PKT_LEN2        1502
+#define IPC_INVALID_PKT_LEN3        1503
+
+#define IPC_UT_INVALID_PKT_CASE     5
+#define IPC_UT_INVALID_PKT_CNT      5
+
+#define IPC_UT_SPD_RING_BUFFER_SIZE 20480 //(IPC_INVALID_MAX_PKT_LEN * IPC_UT_INVALID_PKT_CNT * 2)
+#define IPC_UT_META_TABLE_SIZE      20
+#define IPC_UT_DID_TABLE_SIZE       2
+#define IPC_UT_DID_MAX_SIT_NUM      30
+#define IPC_UT_DID_MAX_DATA_BUF_NUM 60 //(IPC_UT_DID_TABLE_SIZE * IPC_UT_DID_MAX_SIT_NUM)
+
+#define IPC_UT_INVALID_UL_PROTO_IDX -1
+
+#define IPC_UT_META_MATCH_IDX       5
+#define IPC_UT_RBID_MAX_NUM         37
+
+#define IPC_UT_HW_FLTR_TOTAL_NUM    IPC_MAX_FILTER_CNT
+#define IPC_UT_HW_FLTR_PER_ENT_SIZE 16 //each entry 16B
+#define IPC_UT_HW_FLTR_BUF_SIZE     (IPC_UT_HW_FLTR_TOTAL_NUM*IPC_UT_HW_FLTR_PER_ENT_SIZE)
+#define IPC_UT_EA_MAX_CASE_NUM      3
+#define IPC_UT_IPV4_TCP_EA_LEN      40
+#define IPC_UT_IPV6_TCP_EA_LEN      20
+#define IPC_UT_INAVLID_PRIV_DATA    -1
+
+#define IPC_UT_IPV6_DPFM_SRC_PORT    0x222
+#define IPC_UT_IPV6_DPFM_DST_PORT    0x223
+
+typedef enum {
+    IPC_UT_STAGE_BEFORE_BINDING = 0,
+    IPC_UT_STAGE_BINDING,
+    IPC_UT_STAGE_UNBINDING
+} ipc_ut_test_stage_e;
+
+typedef enum {
+    IPC_UT_SPD_AT_THE_HEAD_OF_LIST = 0,
+    IPC_UT_SPD_AT_THE_END_OF_LIST = 1,
+    IPC_UT_SPD_IN_THE_MIDDLE_OF_LIST = 2
+} ipc_ut_spd_position_e;
+
+typedef struct {
+    ipc_conf_t          conf;
+    ipc_handle_t        handle;
+
+    kal_uint8           pdn_id;
+    kal_uint8           ip_type;
+    kal_bool            need_retry;
+    kal_bool            ul_reload_called;
+
+    ipc_session_t      *session[3]; // 0: v4v6, 1: v4, 2: v6
+} ipc_ut_netif_t;
+
+typedef struct {
+    ipc_filter_rules_t  rules;
+    kal_int32           filter_id;
+} ipc_ut_filter_info_t;
+
+typedef struct {
+    /* Content */
+    module_type _src_mod_id;
+    module_type _dest_mod_id;
+    sap_type _sap_id;
+    msg_type _msg_id;
+    local_para_struct *_local_para_ptr;
+    peer_buff_struct *_peer_buff_ptr;
+
+    /* Trigger count */
+    kal_int32 _trigger_cnt;
+} ipc_ut_msg_t;
+
+#define IPC_UT_NTFY_PARAM_MAX_COUNT   (IPC_NTFY_TYPE_MAX * IPC_MAX_NTFY_CNT * IPC_MAX_NETIF_CNT)
+typedef struct {
+    kal_int32 count;
+    ipc_ntfy_param_t params[IPC_UT_NTFY_PARAM_MAX_COUNT];
+} ipc_ut_ntfy_param_t;
+
+typedef struct {
+    kal_int32 count;
+    kal_bool  ntfy_valid[IPC_MAX_NTFY_CNT];
+    kal_int32 ntfy_context[IPC_MAX_NTFY_CNT];
+    kal_int32 ntfy_id[IPC_MAX_NTFY_CNT];
+} ipc_ut_ntfy_info_t;
+
+typedef struct {
+    kal_int32   filter_id;
+    kal_uint8   ip_type;
+    kal_uint8   protocol;
+    kal_uint16  dst_port;
+    kal_uint32  magic_code;
+} ipc_ut_garbage_filter_t;
+
+typedef enum {
+    IPC_UT_LHIF_META_AP0 = 0,
+    IPC_UT_IPF_DL_0,
+    IPC_UT_META_QUEUE_NUM_MAX,
+}ipc_ut_meta_type_e;
+
+typedef struct {
+    kal_uint32  type_idx;
+    kal_uint8   *base_addr;
+    kal_uint8   read_idx;
+    kal_uint8   write_idx;
+    kal_uint8   *buff_addr_base;
+}ipc_ut_meta_queue_t;
+
+typedef struct tmc_ut_ul_thrott {
+    kal_uint8  ctrl_cmd;    /* tmc_ctrl_cmd_enum */
+    kal_uint8  thrott_ctrl; /* tmc_throt_ctrl_enum */
+    kal_uint8  active_period_100ms;
+    kal_uint8  suspend_period_100ms;
+} tmc_ut_ul_thrott;
+
+typedef struct ipc_ut_unk_hdr_stats_t {
+    kal_bool   is_valid;
+    kal_uint32 unk_hdr_cnt;
+    kal_uint16 begin_cntl;
+    kal_uint16 end_cntl;
+    kal_uint16 rb_idx;
+    kal_uint16 protocol_idx;
+} ipc_ut_unk_hdr_stats_t;
+
+extern kal_bool ipc_reset(void);
+extern kal_bool ipc_task_reset(void);
+extern void ipc_on_retry_ul_reload(void);
+extern void ipc_dest_ior(ipc_io_request_t *ior);
+extern void ipc_on_downlink(kal_uint32 pdn_id, qbm_gpd *p_head, qbm_gpd *p_tail);
+extern void ipc_on_lte_tick_source(kal_bool is_lte_tick);
+extern void ipc_on_pdn_bind_top(module_type src_mod_id, local_para_struct *local_para_ptr);
+extern void ipc_on_query_info(module_type src_mod_id, local_para_struct *local_para_ptr);
+extern void ipc_on_pdn_unbind(local_para_struct *local_para_ptr);
+extern void ipc_notify_all_netif_link_change(kal_uint8 ip_type, kal_bool link_up);
+#if defined(__MD93__)
+extern void tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(kal_uint32 ap_param);
+#else
+extern void tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk(kal_uint32 ap_param);
+#endif
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+ipc_ut_error_e ipc_ut_error_g;
+kal_bool ipc_ut_dpfm_is_activated_g = KAL_FALSE;
+
+/*------------------------------------------------------------------------------
+ * Private variables.
+ *----------------------------------------------------------------------------*/
+static ipc_ut_netif_t ipc_ut_nets_s[IPC_UT_MAX_NET_CNT];
+static ipc_ut_filter_info_t ipc_ut_info_set[IPC_MAX_FILTER_CNT];
+static ipc_filter_info_t ipc_ut_ul_filter_info;
+static kal_int32 ipc_ut_ul_filter_id = -1;
+static kal_int32 ipc_ut_ul_filter_gpd_cnt = 0;
+static kal_uint32 ipc_ut_ul_pdn_id = 0;
+static kal_int32 ipc_ut_ul_gpd_cnt = 0;
+static kal_uint32 ipc_ut_ul_meta_cnt = 0;
+static kal_uint32 ipc_ut_ul_meta_non_igr_cnt = 0;
+static qbm_gpd *ipc_ut_ul_head_gpd = NULL;
+static qbm_gpd *ipc_ut_ul_tail_gpd = NULL;
+static ipc_filter_info_t ipc_ut_dl_filter_info;
+static kal_int32 ipc_ut_dl_filter_id = -1;
+static kal_int32 ipc_ut_dl_filter_gpd_cnt = 0;
+static kal_int32 ipc_ut_dl_filter_expect_gpd_cnt = 0;
+static kal_int32 ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt = 0;
+static kal_int32 ipc_ut_str_garbage_expect_host_cnt = 0;
+static kal_int32 ipc_ut_dl_filter_spd_payload_cnt = 0;
+static kal_int32 ipc_ut_dl_callback_gpd_cnt = 0;
+static kal_int32 ipc_ut_dl_callback_spd_payload_cnt = 0;
+static kal_int32 ipc_ut_dl_callback_did_cnt = 0;
+static kal_int32 ipc_ut_dl_callback_did_pkt_cnt = 0;
+static kal_int32 ipc_ut_dl_callback_did_dpfm_cnt = 0;
+static kal_int32 ipc_ut_dl_callback_did_dpfm_pkt_cnt = 0;
+static qbm_gpd *ipc_ut_dl_head_gpd = NULL;
+static qbm_gpd *ipc_ut_dl_tail_gpd = NULL;
+static qbm_gpd *ipc_ut_ul_ebi_head_gpd = NULL;
+static qbm_gpd *ipc_ut_ul_ebi_tail_gpd = NULL;
+static kal_int16 ipc_ut_ul_proto_idx = IPC_UT_INVALID_UL_PROTO_IDX;
+static ipc_ut_msg_t ipc_ut_msg_sent;
+static void *ipc_latest_local_param_p = NULL;
+static kal_uint32 ipc_latest_local_param_size = 0;
+static void *ipc_latest_peer_buff_p = NULL;
+static kal_uint32 ipc_latest_peer_buff_size = 0;
+static ipc_ut_ntfy_param_t ipc_ut_ntfy_param;
+static ipc_ut_ntfy_info_t ipc_ut_ntfy_info;
+static kal_uint8 ipc_ut_garbage_filter_buf_s[2048];
+static kal_uint8 ipc_ut_checksum_buf_s[2048];
+static kal_uint32 g_received_cnt = 0;
+static kal_uint32 g_ipc_ut_igr_meta_cnt = 0;
+static kal_uint32 g_ipc_ut_received_ignore_ea_cnt = 0;
+static kal_uint32 g_ipc_ut_ea_cnt = 0;
+static kal_uint32 g_ipc_ut_ea_drop_cnt = 0;
+static kal_uint32 g_cbk_pkt_recv_cnt = 0;
+static kal_uint32 g_cbk_pkt_send_cnt = 0;
+static kal_uint32 g_normal_cbk_pkt_recv_cnt = 0;
+static kal_bool g_is_block = KAL_TRUE;
+static kal_bool g_is_insert = KAL_FALSE;
+static kal_uint32 g_current_flow = 0;
+static kal_uint32 g_chk_pkt_cnt = 0;
+static ipc_ut_unk_hdr_stats_t g_ut_unk_hdr_stat_recv[MAX_SIM_NUM][IPC_UT_RBID_MAX_NUM] = {0};
+static ipc_ut_unk_hdr_stats_t g_ut_unk_hdr_stat_send[MAX_SIM_NUM][IPC_UT_RBID_MAX_NUM] = {0};
+static kal_uint32 g_unk_pkt_v4_cnt = 0;
+static kal_uint32 g_unk_pkt_v6_cnt = 0;
+static kal_uint32 g_mbim_priv_data = 0;
+
+#if defined(__MD97__)
+static kal_uint32 g_ipc_ut_sdap_pkt_alloc_cnt = 0;
+static kal_uint32 g_ipc_ut_sdap_pkt_received_cnt = 0;
+static ipc_data_rq_info_list g_rq_info_list = {0};
+static ipc_data_rq_info_list g_prepare_rq_info_list = {0};
+#endif
+
+static upcm_did ipc_ut_did_tbl_s[IPC_UT_DID_TABLE_SIZE];
+static kal_uint8 ipc_ut_did_data_buf_s[IPC_UT_DID_MAX_DATA_BUF_NUM][2048];
+static kal_uint8 ipc_ut_did_packet_igr_s[] = {
+        1, 0, 0, 1, 0, 1, 0, 0, 0, 1,
+        0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 1, 0, 0, 1, 0, 0, 0, 1};
+
+static ipc_ut_meta_queue_t ipc_ut_meta_queues[IPC_UT_META_QUEUE_NUM_MAX];
+
+static lhif_meta_tbl_t ipc_ut_meta_tbl_s[IPC_UT_META_TABLE_SIZE];
+static kal_uint8 (*ipc_ut_meta_ring_buf_s)[2048] = ipc_ut_did_data_buf_s;
+static kal_uint8 ipc_ut_meta_tbl_read_idx_s = 0;
+static kal_uint8 ipc_ut_meta_tbl_write_idx_s = 0;
+
+static ipf_dl_meta ipc_ut_dl_meta_tbl_s[IPC_UT_META_TABLE_SIZE];
+static kal_uint8 ipc_ut_dl_meta_tbl_read_idx_s = 0;
+static kal_uint8 ipc_ut_dl_meta_tbl_write_idx_s = 0;
+static kal_uint8 ipc_ut_hw_filter_buf_s[IPC_UT_HW_FLTR_BUF_SIZE];
+static kal_uint8 ipc_ut_dl_meta_buf_free_num_s = 0;
+static kal_uint8 ipc_ut_dl_ipf_match_filter_id_v4_s = 0xFF;
+static kal_uint8 ipc_ut_dl_ipf_match_filter_id_v6_s = 0xFF;
+
+// static kal_uint8 ipc_ut_spd_ring_buf_s[IPC_UT_SPD_RING_BUFFER_SIZE];
+static kal_uint8 *ipc_ut_spd_ring_buf_s = ipc_ut_did_data_buf_s[0];
+static kal_uint8 ipc_ut_spd_packet_igr_s[] = {
+        1, 0, 0, 1, 0, 1, 0, 0, 0, 1,
+        0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 1, 0, 0, 1, 0, 0, 0, 1};
+
+static kal_uint8 ipc_ut_ipv4_udp_packet_example[] = {
+0x45,0x00,0x01,0xd2,0x0e,0x18,0x40,0x00,0x40,0x11,0x2d,0x01,0x7f,0x00,0x00,0x01
+,0x7f,0x00,0x00,0x01,0xe4,0xad,0xa1,0xb8,0x01,0xbe,0xff,0xd1,0xb2,0x01,0x00,0x00
+,0x73,0x73,0x6c,0x5f,0x76,0x65,0x72,0x69,0x66,0x79,0x5f,0x63,0x61,0x6c,0x6c,0x62
+,0x61,0x63,0x6b,0x3a,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x65
+,0x3a,0x0a,0x20,0x20,0x20,0x20,0x44,0x61,0x74,0x61,0x3a,0x0a,0x20,0x20,0x20,0x20
+,0x20,0x20,0x20,0x20,0x56,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3a,0x20,0x33,0x20,0x28
+,0x30,0x78,0x32,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x53,0x65,0x72
+,0x69,0x61,0x6c,0x20,0x4e,0x75,0x6d,0x62,0x65,0x72,0x3a,0x0a,0x20,0x20,0x20,0x20
+,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x37,0x33,0x3a,0x37,0x62,0x3a,0x36,0x63
+,0x3a,0x63,0x65,0x3a,0x64,0x66,0x3a,0x30,0x31,0x3a,0x36,0x63,0x3a,0x61,0x64,0x3a
+,0x64,0x31,0x3a,0x33,0x33,0x3a,0x35,0x64,0x3a,0x33,0x61,0x3a,0x62,0x63,0x3a,0x35
+,0x61,0x3a,0x61,0x33,0x3a,0x31,0x37,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
+,0x49,0x73,0x73,0x75,0x65,0x72,0x3a,0x20,0x43,0x3d,0x55,0x53,0x2c,0x20,0x4f,0x3d
+,0x47,0x6f,0x6f,0x67,0x6c,0x65,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x53,0x65,0x72
+,0x76,0x69,0x63,0x65,0x73,0x2c,0x20,0x43,0x4e,0x3d,0x47,0x6f,0x6f,0x67,0x6c,0x65
+,0x20,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x20,0x41,0x75,0x74,0x68,0x6f,0x72
+,0x69,0x74,0x79,0x20,0x47,0x33,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x56
+,0x61,0x6c,0x69,0x64,0x69,0x74,0x79,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20
+,0x20,0x20,0x20,0x20,0x4e,0x6f,0x74,0x20,0x42,0x65,0x66,0x6f,0x72,0x65,0x3a,0x20
+,0x4d,0x61,0x79,0x20,0x32,0x31,0x20,0x32,0x30,0x3a,0x34,0x34,0x3a,0x31,0x31,0x20
+,0x32,0x30,0x31,0x39,0x20,0x47,0x4d,0x54,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20
+,0x20,0x20,0x20,0x20,0x20,0x4e,0x6f,0x74,0x20,0x41,0x66,0x74,0x65,0x72,0x20,0x3a
+,0x20,0x41,0x75,0x67,0x20,0x31,0x33,0x20,0x32,0x30,0x3a,0x33,0x31,0x3a,0x30,0x30
+,0x20,0x32,0x30,0x31,0x39,0x20,0x47,0x4d,0x54,0x0a,0x20,0x20,0x20,0x20,0x20,0x20
+,0x20,0x20,0x53,0x75,0x62,0x6a,0x65,0x63,0x74,0x3a,0x20,0x43,0x3d,0x55,0x53,0x2c
+,0x20,0x53,0x54,0x3d,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x2c,0x20
+,0x4c,0x3d,0x4d,0x6f,0x75,0x6e,0x74,0x61,0x69,0x6e,0x20,0x56,0x69,0x65,0x77,0x2c
+,0x20,0x4f,0x3d,0x47,0x6f,0x6f,0x67,0x6c,0x65,0x20,0x4c,0x4c,0x43,0x2c,0x20,0x43
+,0x4e,0x3d,0x73,0x75,0x70,0x6c,0x2e,0x67,0x6f,0x6f,0x67,0x6c,0x65,0x2e,0x63,0x6f
+,0x6d,0x0a};
+
+static kal_uint8 ipc_ut_ipv4_udp_packet[] = {
+    0x45, 0x28, 0x00, 0x24, 0x01, 0x53, 0x00, 0x00, 0x80, 0x11, 0x2f, 0xd1, 0x90, 0x4C, 0x9a, 0x72,
+    0x0a, 0x13, 0x0c, 0x84,
+    0x9c, 0x8d, /*src port*/
+    0xec, 0xb9, /*dst port*/
+    0x00, 0x10, /*length*/
+    0x48, 0xc7, /*checksum*/
+    0x81, 0xcb, 0x00, 0x01,
+    0xb0, 0xd4, 0xf1, 0xa0};
+
+static kal_uint8 ipc_ut_ipv6_udp_packet[] = {
+    0x6b,0x80,0x00,0x00,0x00,0x34,0x11,0x77,0x24,0x09,0x80,0x19,0x88,0x30,0x41,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x24,0x09,0x88,0x09,0x88,0x74,0x07,0x4d,
+    0x40,0xbf,0x4c,0x60,0x96,0x75,0x53,0x94,0x55,0x86,0x9c,0x8a,0x00,0x34,0x25,0x40,
+    0x80,0x60,0xc1,0x87,0x13,0x39,0x58,0x18,0x16,0x9c,0xbd,0x7c,0xf3,0xd2,0x6f,0x2f,
+    0x7e,0x14,0x57,0x92,0x79,0xe7,0x0d,0xc4,0x54,0x14,0x2a,0x23,0xda,0x0d,0xb5,0xd3,
+    0xc2,0xd5,0x0f,0xfd,0x35,0x62,0xce,0xca,0xca,0x37,0xd6,0xdc};
+
+
+static kal_uint8 ipc_ut_ipv4_tcp_syn_packet[] = {
+    0x45, 0x00, 0x00, 0x34, 0x31, 0xde, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x94,
+    0x4a, 0x7d, 0x17, 0x5e, 0xdd, 0x5c, 0x01, 0xbb, 0xc4, 0xb9, 0x44, 0x47, 0x00, 0x00, 0x00, 0x00,
+    0x80, 0x02, 0x20, 0x00, 0xc1, 0x71, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x03, 0x03, 0x08,
+    0x01, 0x01, 0x04, 0x02};
+
+static kal_uint8 ipc_ut_ipv4_tcp_ack_packet[] = {
+    0x45, 0x00, 0x00, 0x28, 0x31, 0xeb, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x94,
+    0x4a, 0x7d, 0x17, 0x5e, 0xdd, 0x5c, 0x01, 0xbb, 0xc4, 0xb9, 0x44, 0x48, 0x7e, 0xd3, 0x4c, 0xcc,
+    0x50, 0x10, 0x01, 0x00, 0xa5, 0xa0, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv4_tcp_syn_packet_2[] = {
+    0x45, 0x00, 0x00, 0x34, 0xa1, 0x26, 0x40, 0x00, 0x80, 0x06, 0xd6, 0x35, 0xc0, 0xa8, 0x01, 0x0c,
+    0xc0, 0xa8, 0x01, 0x0b, 0x04, 0x43, 0x13, 0x8e, 0xd9, 0x25, 0x44, 0x8c, 0x00, 0x00, 0x00, 0x00,
+    0x80, 0x02, 0xff, 0xff, 0xb6, 0x2d, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x03, 0x03, 0x00,
+    0x01, 0x01, 0x04, 0x02};
+
+static kal_uint8 ipc_ut_ipv6_tcp_syn_packet[] = {
+    0x60, 0x00, 0x00, 0x00, 0x00, 0x28, 0x06, 0x40, 0x20, 0x01, 0x06, 0xf8, 0x10, 0x2d, 0x00, 0x00,
+    0x02, 0xd0, 0x09, 0xff, 0xfe, 0xe3, 0xe8, 0xde, 0x20, 0x01, 0x06, 0xf8, 0x09, 0x00, 0x07, 0xc0,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe7, 0x41, 0x00, 0x50, 0xab, 0xdc, 0xd6, 0x60,
+    0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x16, 0x80, 0x41, 0xa2, 0x00, 0x00, 0x02, 0x04, 0x05, 0xa0,
+    0x04, 0x02, 0x08, 0x0a, 0x00, 0x0a, 0x22, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x05};
+
+static kal_uint8 ipc_ut_ipv6_tcp_ack_packet[] = {
+    0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x20, 0x01, 0x06, 0xf8, 0x10, 0x2d, 0x00, 0x00,
+    0x02, 0xd0, 0x09, 0xff, 0xfe, 0xe3, 0xe8, 0xde, 0x20, 0x01, 0x06, 0xf8, 0x09, 0x00, 0x07, 0xc0,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe7, 0x41, 0x00, 0x50, 0xab, 0xdc, 0xd6, 0x61,
+    0x01, 0x4a, 0x73, 0x9f, 0x50, 0x10, 0x16, 0x80, 0x57, 0x28, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv6_tcp_syn_packet_2[] = {
+    0x60, 0x00, 0x00, 0x00, 0x00, 0x28, 0x06, 0x40, 0x3f, 0xfe, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01,
+    0x02, 0x00, 0x86, 0xff, 0xfe, 0x05, 0x80, 0xda, 0x3f, 0xfe, 0x05, 0x01, 0x04, 0x10, 0x00, 0x00,
+    0x02, 0xc0, 0xdf, 0xff, 0xfe, 0x47, 0x03, 0x3e, 0x03, 0xfe, 0x00, 0x16, 0xd6, 0x76, 0xf3, 0x21,
+    0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x20, 0x00, 0x18, 0xd5, 0x00, 0x00, 0x02, 0x04, 0x05, 0xa0,
+    0x01, 0x03, 0x03, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x08, 0xca, 0x57, 0x00, 0x00, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_non_ip_packet[] = {
+        0x00, 0x00, 0x45, 0x50, 0x9e, 0x00, 0x00, 0x80, 0x11, 0x96, 0x3a, 0xac, 0x16, 0x97, 0x53,
+        0xac, 0x15, 0x64, 0x50, 0xc0, 0x51, 0x00, 0x35, 0x00, 0x31, 0x7d, 0x15, 0x2d, 0x89, 0x01, 0x00,
+        0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x50, 0x43, 0x31, 0x30, 0x30, 0x36, 0x30,
+        0x30, 0x31, 0x34, 0x08, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6b, 0x03, 0x69, 0x6e, 0x63,
+        0x00, 0x00, 0x1c, 0x00, 0x01};
+
+static kal_uint8 ipc_ut_ipv4_dns_packet[] = {
+        0x45, 0x00, 0x00, 0x45, 0x50, 0x9e, 0x00, 0x00, 0x80, 0x11, 0x96, 0x3a, 0xac, 0x16, 0x97, 0x53,
+        0xac, 0x15, 0x64, 0x50, 0xc0, 0x51, 0x00, 0x35, 0x00, 0x31, 0x7d, 0x15, 0x2d, 0x89, 0x01, 0x00,
+        0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x50, 0x43, 0x31, 0x30, 0x30, 0x36, 0x30,
+        0x30, 0x31, 0x34, 0x08, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6b, 0x03, 0x69, 0x6e, 0x63,
+        0x00, 0x00, 0x1c, 0x00, 0x01};
+
+/* DHCP REQ packet : 172.22.151.76(Client) => 172.21.95.1(Server) */
+static kal_uint8 ipc_ut_ipv4_dhcp_ul_packet[] = {
+        0x45, 0x00, 0x01, 0x61, 0x97, 0xe6, 0x00, 0x00, 0x80, 0x11, 0x53, 0x2c, 0xac, 0x16, 0x97, 0x4c,
+        0xac, 0x15, 0x5f, 0x01, 0x00, 0x44, 0x00, 0x43, 0x01, 0x4d, 0xf5, 0xa2, 0x01, 0x01, 0x06, 0x00,
+        0xa9, 0x29, 0x06, 0x7b, 0x00, 0x00, 0x00, 0x00, 0xac, 0x16, 0x97, 0x4c, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xd4, 0x80, 0x56, 0x15, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x03, 0x3d,
+        0x07, 0x01, 0x00, 0x13, 0xd4, 0x80, 0x56, 0x15, 0x0c, 0x0c, 0x70, 0x63, 0x30, 0x37, 0x30, 0x31,
+        0x30, 0x31, 0x33, 0x39, 0x39, 0x37, 0x51, 0x1c, 0x00, 0x00, 0x00, 0x70, 0x63, 0x30, 0x37, 0x30,
+        0x31, 0x30, 0x31, 0x33, 0x39, 0x39, 0x37, 0x2e, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6b,
+        0x2e, 0x69, 0x6e, 0x63, 0x3c, 0x08, 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, 0x37, 0x0b,
+        0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21, 0xf9, 0x2b, 0x2b, 0x03, 0xdc, 0x01, 0x00,
+        0xff};
+
+/* DHCP ACK packet : 172.22.151.252(Server) => 172.22.151.76(Client) */
+static kal_uint8 ipc_ut_ipv4_dhcp_packet[] = {
+        0x45, 0x01, 0x01, 0x5f, 0x5f, 0x54, 0x00, 0x00, 0x40, 0x11, 0x92, 0xc3, 0xac, 0x16, 0x97, 0xfc,
+        0xac, 0x16, 0x97, 0x4c, 0x00, 0x43, 0x00, 0x44, 0x01, 0x4b, 0xcf, 0x7d, 0x02, 0x01, 0x06, 0x01,
+        0x58, 0xdc, 0x8b, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x16, 0x97, 0x4c,
+        0x00, 0x00, 0x00, 0x00, 0xac, 0x16, 0x97, 0xfc, 0x00, 0x13, 0xd4, 0x80, 0x56, 0x15, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x3a,
+        0x04, 0x00, 0x05, 0x46, 0x00, 0x3b, 0x04, 0x00, 0x09, 0x3a, 0x80, 0x33, 0x04, 0x00, 0x0a, 0x8c,
+        0x00, 0x36, 0x04, 0xac, 0x15, 0x5f, 0x01, 0x01, 0x04, 0xff, 0xff, 0xff, 0x00, 0x51, 0x03, 0x00,
+        0xff, 0xff, 0x0f, 0x0d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6b, 0x2e, 0x69, 0x6e, 0x63,
+        0x00, 0x03, 0x04, 0xac, 0x16, 0x97, 0xfe, 0x06, 0x08, 0xac, 0x15, 0x64, 0x50, 0xac, 0x15, 0x64,
+        0x03, 0x2c, 0x08, 0xac, 0x15, 0x65, 0x0a, 0xac, 0x15, 0x64, 0x2a, 0x2e, 0x01, 0x08, 0xff};
+
+static kal_uint8 ipc_ut_ipv4_incomplete_ip_header_packet[] = {
+        0x45, 0x00, 0x01
+        };
+
+static kal_uint8 ipc_ut_ipv4_incomplete_udp_header_packet[] = {
+        0x45, 0x00, 0x00, 0x1a, 0x50, 0x9e, 0x00, 0x00, 0x80, 0x11, 0x96, 0x3a, 0xac, 0x16, 0x97, 0x53,
+        0xac, 0x15, 0x64, 0x50, 0xc0, 0x51, 0x00, 0x35, 0x00, 0x31};
+
+static kal_uint8 ipc_ut_ipv4_frag0_packet[] = {
+        0x45, 0x00, 0x01, 0x48, 0x13, 0xb6, 0x80, 0x00, 0x80, 0x11, 0xe2, 0x10, 0xac, 0x16, 0x97, 0xc8,
+        0xff, 0xff, 0xff, 0xff, 0x00, 0x44, 0x00, 0x43, 0x01, 0x34, 0x82, 0x90, 0x01, 0x01, 0x06, 0x00,
+        0x6f, 0x4c, 0x32, 0x9a, 0x00, 0x00, 0x00, 0x00, 0xac, 0x16, 0x97, 0xc8, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x37, 0xe6, 0x5d, 0xe8, 0x6f, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x08, 0x3d,
+        0x07, 0x01, 0x44, 0x37, 0xe6, 0x5d, 0xe8, 0x6f, 0x0c, 0x0a, 0x50, 0x43, 0x31, 0x31, 0x30, 0x39,
+        0x30, 0x30, 0x30, 0x35, 0x3c, 0x08, 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, 0x37, 0x0c,
+        0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21, 0xf9, 0x2b, 0xfc, 0x2b, 0x03, 0xdc, 0x01,
+        0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv4_frag1_packet[] = {
+        0x45, 0x00, 0x01, 0x48, 0x13, 0xb6, 0x00, 0x10, 0x80, 0x11, 0xe2, 0x10, 0xac, 0x16, 0x97, 0xc8,
+        0xff, 0xff, 0xff, 0xff, 0x00, 0x44, 0x00, 0x43, 0x01, 0x34, 0x82, 0x90, 0x01, 0x01, 0x06, 0x00,
+        0x6f, 0x4c, 0x32, 0x9a, 0x00, 0x00, 0x00, 0x00, 0xac, 0x16, 0x97, 0xc8, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x37, 0xe6, 0x5d, 0xe8, 0x6f, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x08, 0x3d,
+        0x07, 0x01, 0x44, 0x37, 0xe6, 0x5d, 0xe8, 0x6f, 0x0c, 0x0a, 0x50, 0x43, 0x31, 0x31, 0x30, 0x39,
+        0x30, 0x30, 0x30, 0x35, 0x3c, 0x08, 0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30, 0x37, 0x0c,
+        0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21, 0xf9, 0x2b, 0xfc, 0x2b, 0x03, 0xdc, 0x01,
+        0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv6_mdns_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 0x39, 0x11, 0xff, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x02, 0x17, 0x31, 0xff, 0xfe, 0x7e, 0x96, 0xab, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x14, 0xe9, 0x14, 0xe9, 0x00, 0x39, 0x1d, 0x62,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x57, 0x69, 0x6d,
+        0x61, 0x78, 0x4d, 0x61, 0x63, 0x2d, 0x74, 0x6a, 0x2d, 0x31, 0x30, 0x36, 0x04, 0x5f, 0x72, 0x66,
+        0x62, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x21, 0x00,
+        0x01};
+
+static kal_uint8 ipc_ut_ipv6_dhcp_ul_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 0x56, 0x11, 0x80, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x02, 0x13, 0xd4, 0xff, 0xfe, 0x80, 0x56, 0x15, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x22, 0x02, 0x23, 0x00, 0x56, 0x98, 0x9b,
+        0x01, 0x00, 0x12, 0x69, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x06, 0x18, 0xc5, 0xe1, 0xd2,
+        0x00, 0x13, 0xd4, 0x80, 0x56, 0x15, 0x00, 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x17};
+
+static kal_uint8 ipc_ut_ipv6_dhcp_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 0x42, 0x11, 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x22, 0x02, 0x23, 0x00, 0x42, 0x93, 0x19,
+        0x01, 0x5d, 0x6f, 0xba, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x15, 0xbd, 0x26, 0xde,
+        0x20, 0xcf, 0x30, 0x0d, 0xe2, 0x47, 0x00, 0x08, 0x00, 0x02, 0xff, 0xff, 0x00, 0x03, 0x00, 0x12,
+        0x47, 0xe2, 0x0d, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x02,
+        0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18};
+
+static kal_uint8 ipc_ut_ipv6_ext0_dhcp_ul_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 86+16+24+24, /* payload length */ 0, /* next header */ 0x80, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x02, 0x13, 0xd4, 0xff, 0xfe, 0x80, 0x56, 0x15, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* hop-by-hop */
+        60, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* destination options header */
+        43, 2, 1, 2, 0, 0, 201, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* routing header*/
+        17, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+        /* 86-byte */
+        0x02, 0x22, 0x02, 0x23, 0x00, 0x56, 0x98, 0x9b,
+        0x01, 0x00, 0x12, 0x69, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x06, 0x18, 0xc5, 0xe1, 0xd2,
+        0x00, 0x13, 0xd4, 0x80, 0x56, 0x15, 0x00, 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x17};
+
+static kal_uint8 ipc_ut_ipv6_ext0_dhcp_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+16+24+24, /* payload length */ 0, /* next header */ 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* hop-by-hop */
+        60, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* destination options header */
+        43, 2, 1, 2, 0, 0, 201, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* routing header*/
+        17, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+        /* 66-byte */
+        0x02, 0x22, 0x02, 0x23, 0x00, 0x42, 0x93, 0x19,
+        0x01, 0x5d, 0x6f, 0xba, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x15, 0xbd, 0x26, 0xde,
+        0x20, 0xcf, 0x30, 0x0d, 0xe2, 0x47, 0x00, 0x08, 0x00, 0x02, 0xff, 0xff, 0x00, 0x03, 0x00, 0x12,
+        0x47, 0xe2, 0x0d, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x02,
+        0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18};
+
+static kal_uint8 ipc_ut_ipv6_ext1_dhcp_ul_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 86+16+12, /* payload length */ 0, /* next header */ 0x80, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x02, 0x13, 0xd4, 0xff, 0xfe, 0x80, 0x56, 0x15, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* hop-by-hop */
+        51, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* authentication header */
+        17, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+        /* 86-byte */
+        0x02, 0x22, 0x02, 0x23, 0x00, 0x56, 0x98, 0x9b,
+        0x01, 0x00, 0x12, 0x69, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x06, 0x18, 0xc5, 0xe1, 0xd2,
+        0x00, 0x13, 0xd4, 0x80, 0x56, 0x15, 0x00, 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x05, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x17};
+
+static kal_uint8 ipc_ut_ipv6_ext1_dhcp_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+16+12, /* payload length */ 0, /* next header */ 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* hop-by-hop */
+        51, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* authentication header */
+        17, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+        /* 66-byte */
+        0x02, 0x22, 0x02, 0x23, 0x00, 0x42, 0x93, 0x19,
+        0x01, 0x5d, 0x6f, 0xba, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x15, 0xbd, 0x26, 0xde,
+        0x20, 0xcf, 0x30, 0x0d, 0xe2, 0x47, 0x00, 0x08, 0x00, 0x02, 0xff, 0xff, 0x00, 0x03, 0x00, 0x12,
+        0x47, 0xe2, 0x0d, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x02,
+        0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18};
+
+static kal_uint8 ipc_ut_ipv6_incomplete_ip_header_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 0x39, 0x11, 0xff, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv6_incomplete_hop_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+15, /* payload length */ 0, /* next header */ 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* hop-by-hop */
+        60, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static kal_uint8 ipc_ut_ipv6_incomplete_ah_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+11, /* payload length */ 51, /* next header */ 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* authentication header */
+        41, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+static kal_uint8 ipc_ut_ipv6_unknown_ext_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+16+16, /* payload length */ 0, /* next header */ 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* hop-by-hop */
+        254, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* unknown header */
+        17, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+        /* 66-byte */
+        0x02, 0x22, 0x02, 0x23, 0x00, 0x42, 0x93, 0x19,
+        0x01, 0x5d, 0x6f, 0xba, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x15, 0xbd, 0x26, 0xde,
+        0x20, 0xcf, 0x30, 0x0d, 0xe2, 0x47, 0x00, 0x08, 0x00, 0x02, 0xff, 0xff, 0x00, 0x03, 0x00, 0x12,
+        0x47, 0xe2, 0x0d, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x02,
+        0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18};
+
+static kal_uint8 ipc_ut_ipv6_incomplete_ipv4enc_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+12+2, /* payload length */ 51, /* next header */ 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* authentication header */
+        4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* IPv4 encapsulation */
+        0x45, 0x00};
+
+static kal_uint8 ipc_ut_ipv6_frag_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+8, /* payload length */ 44, /* next header */ 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* fragment header */
+        17, 0, 0, 0, 0, 0, 0, 0,
+
+        /* 66-byte */
+        0x02, 0x22, 0x02, 0x23, 0x00, 0x42, 0x93, 0x19,
+        0x01, 0x5d, 0x6f, 0xba, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x15, 0xbd, 0x26, 0xde,
+        0x20, 0xcf, 0x30, 0x0d, 0xe2, 0x47, 0x00, 0x08, 0x00, 0x02, 0xff, 0xff, 0x00, 0x03, 0x00, 0x12,
+        0x47, 0xe2, 0x0d, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x02,
+        0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18};
+
+static kal_uint8 ipc_ut_ipv6_ipv4enc_frag0_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+12+20, /* payload length */ 51, /* next header */ 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* authentication header */
+        4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* IPv4 encapsulation */
+        0x45, 0x00, 0x00, 66+20, /* total length */ 0x13, 0xb6, 0x80, 0x00, 0x80, 17, /* protocol*/ 0xe2, 0x10, 0xac, 0x16, 0x97, 0xc8,
+        0xff, 0xff, 0xff, 0xff,
+
+        /* 66-byte */
+        0x02, 0x22, 0x02, 0x23, 0x00, 0x42, 0x93, 0x19,
+        0x01, 0x5d, 0x6f, 0xba, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x15, 0xbd, 0x26, 0xde,
+        0x20, 0xcf, 0x30, 0x0d, 0xe2, 0x47, 0x00, 0x08, 0x00, 0x02, 0xff, 0xff, 0x00, 0x03, 0x00, 0x12,
+        0x47, 0xe2, 0x0d, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x02,
+        0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18};
+
+static kal_uint8 ipc_ut_ipv6_ipv4enc_frag1_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+12+20, /* payload length */ 51, /* next header */ 0x01, 0xfe, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* authentication header */
+        4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* IPv4 encapsulation */
+        0x45, 0x00, 0x00, 66+20, /* total length */ 0x13, 0xb6, 0x80, 0x00, 0x80, 17, /* protocol*/ 0xe2, 0x10, 0xac, 0x16, 0x97, 0xc8,
+        0xff, 0xff, 0xff, 0xff,
+
+        /* 66-byte */
+        0x02, 0x22, 0x02, 0x23, 0x00, 0x42, 0x93, 0x19,
+        0x01, 0x5d, 0x6f, 0xba, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x15, 0xbd, 0x26, 0xde,
+        0x20, 0xcf, 0x30, 0x0d, 0xe2, 0x47, 0x00, 0x08, 0x00, 0x02, 0xff, 0xff, 0x00, 0x03, 0x00, 0x12,
+        0x47, 0xe2, 0x0d, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x02,
+        0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x17, 0x00, 0x18};
+
+static kal_uint8 ipc_ut_ipv6_incomplete_ipv6enc_packet[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 66+12+4, /* payload length */ 51, /* next header */ 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x22, 0xcf, 0x30, 0xff, 0xfe, 0x0d, 0xe2, 0x47, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,
+
+        /* authentication header */
+        41, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* IPv6 encapsulation */
+        0x60, 0x00, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv6_udp_zero_checksum_packet[] = {
+    0x60, 0x50, 0x00, 0x00, 0x00, 0x51, 0x11, 0x80, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x9c, 0x40, 0xea, 0x60, 0x00, 0x51, 0x00, 0x00,
+    0x80, 0x62, 0x51, 0x8a, 0x00, 0x66, 0x60, 0xc0, 0x52, 0x77, 0xd1, 0x80, 0xf4, 0x60, 0xc3, 0x1b,
+    0x84, 0xc7, 0xce, 0x42, 0xa1, 0x2d, 0xff, 0xff, 0x84, 0x7d, 0xe8, 0x63, 0x77, 0xf5, 0xe7, 0xc1,
+    0x47, 0xf4, 0x59, 0x85, 0x3c, 0xa8, 0xab, 0xcc, 0xe8, 0xfb, 0xab, 0x99, 0x5d, 0x20, 0x6c, 0x24,
+    0x7b, 0x94, 0xfa, 0xd3, 0x25, 0x3e, 0x68, 0x7c, 0x93, 0x39, 0x24, 0x36, 0xc3, 0xd4, 0x8a, 0x54,
+    0x87, 0xb6, 0x06, 0x30, 0xaa, 0x1a, 0xdf, 0xc4, 0x60};
+
+static kal_uint8 ipc_ut_ipv4_tcp_fin_ack_packet[] = {
+    0x45, 0x00, 0x00, 0x28, 0x31, 0xeb, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x94,
+    0x4a, 0x7d, 0x17, 0x5e, 0xdd, 0x5c, 0x01, 0xbb, 0xc4, 0xb9, 0x44, 0x48, 0x7e, 0xd3, 0x4c, 0xcc,
+    0x50, 0x11, 0x01, 0x00, 0xa5, 0xa0, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv4_tcp_fin_ack_packet_2[] = {
+    0x45, 0x00, 0x00, 0x28, 0x31, 0xeb, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x92, 0x91,
+    0x4a, 0x7d, 0x17, 0x5e, 0xdd, 0x5c, 0x01, 0xbb, 0xc4, 0xb9, 0x44, 0x48, 0x7e, 0xd3, 0x4c, 0xcc,
+    0x50, 0x11, 0x01, 0x00, 0xa5, 0xa0, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv6_tcp_fin_ack_packet[] = {
+    0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x20, 0x01, 0x06, 0xf8, 0x10, 0x2d, 0x00, 0x00,
+    0x02, 0xd0, 0x09, 0xff, 0xfe, 0xe3, 0xe8, 0xde, 0x20, 0x01, 0x06, 0xf8, 0x09, 0x00, 0x07, 0xc0,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe7, 0x41, 0x00, 0x50, 0xab, 0xdc, 0xd6, 0x61,
+    0x01, 0x4a, 0x73, 0x9f, 0x50, 0x11, 0x16, 0x80, 0x57, 0x28, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv6_tcp_fin_ack_packet_2[] = {
+    0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x20, 0x02, 0x06, 0xf8, 0x10, 0x2d, 0x00, 0x00,
+    0x02, 0xd0, 0x06, 0xff, 0xfe, 0xe5, 0xe9, 0xde, 0x20, 0x01, 0x06, 0xf8, 0x09, 0x00, 0x07, 0xc0,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe7, 0x41, 0x00, 0x50, 0xab, 0xdc, 0xd6, 0x61,
+    0x01, 0x4a, 0x73, 0x9f, 0x50, 0x11, 0x16, 0x80, 0x57, 0x28, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv4_tcp_empty_ack_packet[] = {
+    0x45, 0x00, 0x00, 0x28, 0x31, 0xeb, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x94,
+    0x4a, 0x7d, 0x17, 0x5e, 0xdd, 0x5c, 0x01, 0xbb, 0xc4, 0xb9, 0x44, 0x48, 0x7e, 0xd3, 0x4c, 0xcc,
+    0x50, 0x10, 0x01, 0x00, 0xa5, 0xa0, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv6_tcp_empty_ack_packet[] = {
+    0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x20, 0x01, 0x06, 0xf8, 0x10, 0x2d, 0x00, 0x00,
+    0x02, 0xd0, 0x09, 0xff, 0xfe, 0xe3, 0xe8, 0xde, 0x20, 0x01, 0x06, 0xf8, 0x09, 0x00, 0x07, 0xc0,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xe7, 0x41, 0x00, 0x50, 0xab, 0xdc, 0xd6, 0x61,
+    0x01, 0x4a, 0x73, 0x9f, 0x50, 0x10, 0x16, 0x80, 0x57, 0x28, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv4_ul_syn_window_scale_packets_1[] = {
+    0x45, 0x00, 0x00, 0x34, 0x5c, 0x32, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x2c,
+    0xd8, 0x3a, 0xc8, 0xee,   0xea, 0x7d, 0x01, 0xbb, 0x1e, 0x2a, 0x0a, 0x1d, 0x00, 0x00, 0x00, 0x00,
+    0x80, 0x02, 0x20, 0x00, 0xe4, 0x92, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x02, 0x02, 0x04,
+    0x01, 0x01, 0x04, 0x02};
+
+static kal_uint8 ipc_ut_ipv4_ul_syn_window_scale_packets_2[] = {
+    0x45, 0x00, 0x00, 0x34, 0x5c, 0x32, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x2d,
+    0xd8, 0x3a, 0xc8, 0xee,   0xea, 0x7d, 0x01, 0xbb, 0x1e, 0x2a, 0x0a, 0x1d, 0x00, 0x00, 0x00, 0x00,
+    0x80, 0x02, 0x20, 0x00, 0xe4, 0x92, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x03, 0x03, 0x04,
+    0x01, 0x01, 0x04, 0x02};
+
+static kal_uint8 ipc_ut_ipv4_ul_syn_window_scale_packets_3[] = {
+    0x45, 0x00, 0x00, 0x34, 0x5c, 0x32, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x2e,
+    0xd8, 0x3a, 0xc8, 0xee,   0xea, 0x7d, 0x01, 0xbb, 0x1e, 0x2a, 0x0a, 0x1d, 0x00, 0x00, 0x00, 0x00,
+    0x80, 0x02, 0x20, 0x00, 0xe4, 0x92, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x03, 0x03, 0x08,
+    0x01, 0x01, 0x04, 0x02};
+
+/* ack */
+static kal_uint8 ipc_ut_ipv4_ul_syn_window_scale_packets_4[] = {
+    0x45, 0x00, 0x00, 0x28, 0xef, 0xf3, 0x00, 0x00, 0x33, 0x06, 0xb3, 0x70, 0xd8, 0x3a, 0xc8, 0xee, 0xac, 0x16,
+    0x97, 0x2e, 0x01, 0xbb, 0xea, 0x7d, 0xf2, 0xd1, 0x7b, 0x3f, 0x1e, 0x2a, 0x0c, 0x23, 0x50, 0x10, 0x00, 0xac,
+    0x46, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/* not formal packet, only for TCP RST error testing */
+static kal_uint8 ipc_ut_ipv4_tcp_error_frag1_packet[] = {
+    0x45, 0x00, 0x00, 0x28, 0x31, 0xeb, 0x00, 0x10, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x94,
+    0x4a, 0x7d, 0x17, 0x5e, 0xdd, 0x5c, 0x01, 0xbb, 0xc4, 0xb9, 0x44, 0x48, 0x7e, 0xd3, 0x4c, 0xcc,
+    0x50, 0x10, 0x01, 0x00, 0xa5, 0xa0, 0x00, 0x00};
+
+static kal_uint8 ipc_ut_ipv4_ul_syn_window_scale_packets_5[] = {
+    0x45, 0x00, 0x00, 0x34, 0x5c, 0x32, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x2c,
+    0xd8, 0x3a, 0xc8, 0xee,   0xea, 0x7d, 0x01, 0xbb, 0x1e, 0x2a, 0x0a, 0x1d, 0x00, 0x00, 0x00, 0x00,
+    0x80, 0x02, 0x20, 0x01, 0xe4, 0x92, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x02, 0x02, 0x04,
+    0x01, 0x01, 0x04, 0x02};
+
+static kal_uint8 ipc_ut_ipv4_ul_syn_window_scale_packets_6[] = {
+    0x45, 0x00, 0x00, 0x34, 0x5c, 0x32, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x2d,
+    0xd8, 0x3a, 0xc8, 0xee,   0xea, 0x7d, 0x01, 0xbb, 0x1e, 0x2a, 0x0a, 0x1d, 0x00, 0x00, 0x00, 0x00,
+    0x80, 0x02, 0x20, 0x02, 0xe4, 0x92, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x03, 0x03, 0x04,
+    0x01, 0x01, 0x04, 0x02};
+
+static kal_uint8 ipc_ut_ipv4_ul_syn_window_scale_packets_7[] = {
+    0x45, 0x00, 0x00, 0x34, 0x5c, 0x32, 0x40, 0x00, 0x80, 0x06, 0x00, 0x00, 0xac, 0x16, 0x97, 0x2e,
+    0xd8, 0x3a, 0xc8, 0xee,   0xea, 0x7d, 0x01, 0xbb, 0x1e, 0x2a, 0x0a, 0x1d, 0x00, 0x00, 0x00, 0x00,
+    0x80, 0x02, 0x20, 0x03, 0xe4, 0x92, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x03, 0x03, 0x08,
+    0x01, 0x01, 0x04, 0x02};
+
+static kal_uint8 g_ipc_ut_v6_esp_pkt_1[] = {0x60, 0x00, 0x00, 0x00, 0x00, 0x08,
+                                            0x32, 0x3f, 0x20, 0x01, 0x04, 0x70,
+                                            0xe5, 0xbf, 0x10, 0x01, 0x85, 0x19,
+                                            0x2d, 0x1f, 0xc5, 0x7d, 0xfc, 0x4f,
+                                            0x20, 0x01, 0x04, 0x70, 0xe5, 0xbf,
+                                            0xde, 0xad, 0x7d, 0xb0, 0x09, 0x21,
+                                            0xa2, 0xe9, 0x1c, 0x21, 0x49, 0x50,
+                                            0x76, 0x46, 0x20, 0x45, 0x53, 0x50};
+
+static kal_uint8 g_ipc_ut_v6_ah_esp_pkt_1[] = {0x60, 0x00, 0x00, 0x00, 0x00,
+                                               8 + 24, 0x33, 0x3f, 0x20, 0x01,
+                                               0x04, 0x70, 0xe5, 0xbf, 0x10,
+                                               0x01, 0x85, 0x19, 0x2d, 0x1f,
+                                               0xc5, 0x7d, 0xfc, 0x4f, 0x20,
+                                               0x01, 0x04, 0x70, 0xe5, 0xbf,
+                                               0xde, 0xad, 0x7d, 0xb0, 0x09,
+                                               0x21, 0xa2, 0xe9, 0x1c, 0x21,
+                                               0x32, 0x04, 0x00, 0x00, 0x81,
+                                               0x79, 0xb7, 0x05, 0x00, 0x00,
+                                               0x00, 0x01, 0x27, 0xcf, 0xc0,
+                                               0xa5, 0xe4, 0x3d, 0x69, 0xb3,
+                                               0x72, 0x8e, 0xc5, 0xb0, 0x49,
+                                               0x50, 0x76, 0x56, 0x20, 0x45,
+                                               0x53, 0x50};
+
+static kal_uint8 g_ipc_ut_v6_routing_esp_pkt_1[] = {0x60, 0x0f, 0xbb, 0x74,
+                                                    0x00, 0x88, 0x2b, 0x3f,
+                                                    0xfc, 0x00, 0x00, 0x42,
+                                                    0x00, 0x00, 0x00, 0x01,
+                                                    0x00, 0x00, 0x00, 0x00,
+                                                    0x00, 0x00, 0x00, 0x02,
+                                                    0xfc, 0x00, 0x00, 0x02,
+                                                    0x00, 0x00, 0x00, 0x05,
+                                                    0x00, 0x00, 0x00, 0x00,
+                                                    0x00, 0x00, 0x00, 0x01,
+                                                    0x32, 0x06, 0x04, 0x02,
+                                                    0x02, 0x00, 0x00, 0x00,
+                                                    0xfc, 0x00, 0x00, 0x02,
+                                                    0x00, 0x00, 0x00, 0x06,
+                                                    0x00, 0x00, 0x00, 0x00,
+                                                    0x00, 0x00, 0x00, 0x01,
+                                                    0xfc, 0x00, 0x00, 0x02,
+                                                    0x00, 0x00, 0x00, 0x07,
+                                                    0x00, 0x00, 0x00, 0x00,
+                                                    0x00, 0x00, 0x00, 0x01,
+                                                    0xfc, 0x00, 0x00, 0x02,
+                                                    0x00, 0x00, 0x00, 0x05,
+                                                    0x00, 0x00, 0x00, 0x00,
+                                                    0x00, 0x00, 0x00, 0x01,
+                                                    0x49, 0x50, 0x76, 0x76,
+                                                    0x20, 0x45, 0x53, 0x50};
+
+static kal_uint8 g_ipc_ut_v6_routing_ah_esp_pkt_1[] = {0x60, 0x0f, 0xbb, 0x74,
+                                                       0x00, 0x88 + 24, 0x2b,
+                                                       0x3f, 0xfc, 0x00, 0x00,
+                                                       0x42, 0x00, 0x00, 0x00,
+                                                       0x01, 0x00, 0x00, 0x00,
+                                                       0x00, 0x00, 0x00, 0x00,
+                                                       0x02, 0xfc, 0x00, 0x00,
+                                                       0x02, 0x00, 0x00, 0x00,
+                                                       0x05, 0x00, 0x00, 0x00,
+                                                       0x00, 0x00, 0x00, 0x00,
+                                                       0x01, 0x33, 0x06, 0x04,
+                                                       0x02, 0x02, 0x00, 0x00,
+                                                       0x00, 0xfc, 0x00, 0x00,
+                                                       0x02, 0x00, 0x00, 0x00,
+                                                       0x06, 0x00, 0x00, 0x00,
+                                                       0x00, 0x00, 0x00, 0x00,
+                                                       0x01, 0xfc, 0x00, 0x00,
+                                                       0x02, 0x00, 0x00, 0x00,
+                                                       0x07, 0x00, 0x00, 0x00,
+                                                       0x00, 0x00, 0x00, 0x00,
+                                                       0x01, 0xfc, 0x00, 0x00,
+                                                       0x02, 0x00, 0x00, 0x00,
+                                                       0x05, 0x00, 0x00, 0x00,
+                                                       0x00, 0x00, 0x00, 0x00,
+                                                       0x01, 0x32, 0x04, 0x00,
+                                                       0x00, 0x81, 0x79, 0xb7,
+                                                       0x05, 0x00, 0x00, 0x00,
+                                                       0x01, 0x27, 0xcf, 0xc0,
+                                                       0xa5, 0xe4, 0x3d, 0x69,
+                                                       0xb3, 0x72, 0x8e, 0xc5,
+                                                       0xb0, 0x49, 0x50, 0x76,
+                                                       0x66, 0x20, 0x45, 0x53,
+                                                       0x50};
+
+static kal_uint8 g_ipc_ut_v4_esp_pkt_1[] = {0x45, 0x00, 0x00, 0xb8, 0x20, 0x20,
+                                            0x40, 0x00, 0x40, 0x32, 0x05, 0xf2,
+                                            0x0a, 0x00, 0x00, 0x01, 0x0a, 0x00,
+                                            0x00, 0x02, 0x00, 0x00, 0x00, 0x0a,
+                                            0x00, 0x00, 0x00, 0xf4, 0xf4, 0xcf,
+                                            0xf9, 0x23, 0x0a, 0x5d, 0x0f, 0x97,
+                                            0x16, 0xde, 0xd0, 0xa7, 0xdd, 0x25,
+                                            0x7c, 0x83, 0x97, 0x17, 0xeb, 0x36,
+                                            0xf4, 0x22, 0xd1, 0x31, 0x4e, 0xaa,
+                                            0xfc, 0x14, 0x32, 0x17, 0x74, 0x60,
+                                            0x96, 0x28, 0xdf, 0x6c, 0x0a, 0x21,
+                                            0x78, 0x49, 0xa6, 0xc7, 0xc3, 0x0b,
+                                            0x47, 0xa9, 0x92, 0xdb, 0x1b, 0x7b,
+                                            0xcb, 0x74, 0x7c, 0xc1, 0xd1, 0xf7,
+                                            0x8d, 0x88, 0xf9, 0x8e, 0x79, 0xc7,
+                                            0x31, 0xdd, 0x6a, 0x88, 0xc0, 0x35,
+                                            0x5c, 0x7b, 0x2a, 0x82, 0x1a, 0x14,
+                                            0x7e, 0x7b, 0x6b, 0xd3, 0xec, 0x76,
+                                            0xd4, 0x93, 0x19, 0xdf, 0xc9, 0x09,
+                                            0xab, 0xa5, 0xc7, 0x5d, 0x6c, 0x92,
+                                            0x9c, 0xeb, 0xce, 0xd6, 0x52, 0x70,
+                                            0xce, 0x83, 0x58, 0xea, 0x85, 0x9c,
+                                            0x25, 0xc0, 0xdf, 0x5f, 0xd9, 0xe0,
+                                            0x14, 0xf6, 0x91, 0x04, 0x69, 0xca,
+                                            0x73, 0x95, 0xd7, 0xed, 0xfb, 0x01,
+                                            0x7e, 0xa1, 0x31, 0xea, 0x21, 0x06,
+                                            0x82, 0xd8, 0x77, 0xa8, 0x63, 0x0e,
+                                            0xb4, 0x14, 0xe5, 0x1e, 0x4e, 0x2a,
+                                            0xd4, 0x2f, 0x00, 0x1a, 0x2d, 0x90,
+                                            0xc2, 0x89, 0xb4, 0x2a, 0xba, 0xb0,
+                                            0x05, 0x05, 0x3e, 0xf1};
+
+static kal_uint8 g_ipc_ut_v4_ah_esp_pkt_1[] = {0x45, 0x00, 0x00, 0xb4, 0x00,
+                                               0x6b, 0x00, 0x00, 0xff, 0x33,
+                                               0xa6, 0xa9, 0x0a, 0x00, 0x00,
+                                               0x01, 0x0a, 0x00, 0x00, 0x02,
+                                               0x32, 0x04, 0x00, 0x00, 0x81,
+                                               0x79, 0xb7, 0x05, 0x00, 0x00,
+                                               0x00, 0x01, 0x27, 0xcf, 0xc0,
+                                               0xa5, 0xe4, 0x3d, 0x69, 0xb3,
+                                               0x72, 0x8e, 0xc5, 0xb0, 0x48,
+                                               0xda, 0xc2, 0xe4, 0x00, 0x00,
+                                               0x00, 0x01, 0x07, 0x41, 0xbe,
+                                               0x7f, 0x8a, 0xde, 0x40, 0xc0,
+                                               0x2b, 0xd8, 0x1a, 0xee, 0x0f,
+                                               0x50, 0x6f, 0x2c, 0x46, 0xdc,
+                                               0xbd, 0x49, 0xac, 0xad, 0x30,
+                                               0xbb, 0x5a, 0x09, 0x70, 0x80,
+                                               0xc3, 0xd6, 0x88, 0xd4, 0x9b,
+                                               0x5f, 0x22, 0x5c, 0xe8, 0x71,
+                                               0x84, 0xd1, 0xf9, 0xf8, 0xad,
+                                               0x62, 0x67, 0xfa, 0x1a, 0xa2,
+                                               0x18, 0x97, 0x0f, 0xd1, 0x35,
+                                               0xb6, 0x99, 0x37, 0x24, 0x54,
+                                               0x44, 0x5f, 0x6b, 0xd3, 0xcc,
+                                               0x19, 0xb1, 0x5f, 0xb7, 0x01,
+                                               0xb2, 0x34, 0xd9, 0x4a, 0x07,
+                                               0xec, 0x6b, 0xfc, 0x2d, 0x3d,
+                                               0x13, 0x35, 0xb3, 0x01, 0x35,
+                                               0x66, 0xb4, 0x74, 0xd7, 0xc3,
+                                               0x25, 0x9b, 0x7f, 0xe4, 0xb9,
+                                               0x22, 0xa5, 0xbf, 0xa3, 0xd0,
+                                               0x90, 0xc8, 0x9a, 0x9b, 0x6d,
+                                               0x6a, 0xb7, 0xf2, 0xba, 0x11,
+                                               0xff, 0xc7, 0xa3, 0x87, 0xb6,
+                                               0x05, 0x58, 0x7a, 0x24, 0xa8,
+                                               0x29, 0x9c, 0x7d, 0x89, 0xc2,
+                                               0x21, 0x99, 0xa1, 0xbd, 0x00};
+
+static kal_uint8 g_ipc_ut_v6_hop_dst_route_esp_pkt_1[] = {0x60, 0x00, 0x00,
+                                                          0x00, 0x00,
+                                                          8 + 16 + 24 + 24 + 24,
+                                                          0x0, 0x3f, 0x20, 0x01,
+                                                          0x04, 0x70, 0xe5,
+                                                          0xbf, 0x10, 0x01,
+                                                          0x85, 0x19, 0x2d,
+                                                          0x1f, 0xc5, 0x7d,
+                                                          0xfc, 0x4f, 0x20,
+                                                          0x01, 0x04, 0x70,
+                                                          0xe5, 0xbf, 0xde,
+                                                          0xad, 0x7d, 0xb0,
+                                                          0x09, 0x21, 0xa2,
+                                                          0xe9, 0x1c, 0x21,
+
+                                                          /* hop-by-hop */
+                                                          60,
+                                                          1, 0, 0, 0, 0, 0, 0,
+                                                          0, 0, 0, 0, 0, 0, 0,
+                                                          0,
+                                                          /* destination options header */
+                                                          43,
+                                                          2, 1, 2, 0, 0, 201,
+                                                          16, 0, 0, 0, 0, 0, 0,
+                                                          0, 0, 0, 0, 0, 0, 0,
+                                                          0, 0, 0,
+                                                          /* routing header*/
+                                                          0x32,
+                                                          2, 2, 1, 0, 0, 0, 0,
+                                                          0, 0, 0, 0, 0, 0, 0,
+                                                          0, 0, 0, 0, 0, 0, 0,
+                                                          0, 0,
+
+                                                          0x49,
+                                                          0x50, 0x86, 0x37,
+                                                          0x20, 0x45, 0x53, 0x50};
+
+static kal_uint8 g_ipc_ut_v6_hop_dst_route_ah_esp_pkt_1[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 8 + 16 + 24 + 24 + 24, 0x0, 0x3f, 0x20,
+        0x01, 0x04, 0x70, 0xe5, 0xbf, 0x10, 0x01, 0x85, 0x19, 0x2d, 0x1f, 0xc5,
+        0x7d, 0xfc, 0x4f, 0x20, 0x01, 0x04, 0x70, 0xe5, 0xbf, 0xde, 0xad, 0x7d,
+        0xb0, 0x09, 0x21, 0xa2, 0xe9, 0x1c, 0x21,
+
+        /* hop-by-hop */
+        60,
+        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* destination options header */
+        43,
+        2, 1, 2, 0, 0, 201, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* routing header*/
+        0x33,
+        2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+        0x32,
+        0x04, 0x00, 0x00, 0x81, 0x79, 0xb7, 0x05, 0x00, 0x00, 0x00, 0x01, 0x27,
+        0xcf, 0xc0, 0xa5, 0xe4, 0x3d, 0x69, 0xb3, 0x72, 0x8e, 0xc5, 0xb0, 0x49,
+        0x50, 0x76, 0x37, 0x20, 0x45, 0x53, 0x50};
+
+static kal_uint8 g_ipc_ut_v6_hop_dst_route_frag_ah_esp_pkt_1[] = {
+        0x60, 0x00, 0x00, 0x00, 0x00, 8 + 16 + 24 + 24 + 24 + 8, 0x0, 0x3f,
+        0x20, 0x01, 0x04, 0x70, 0xe5, 0xbf, 0x10, 0x01, 0x85, 0x19, 0x2d, 0x1f,
+        0xc5, 0x7d, 0xfc, 0x4f, 0x20, 0x01, 0x04, 0x70, 0xe5, 0xbf, 0xde, 0xad,
+        0x7d, 0xb0, 0x09, 0x21, 0xa2, 0xe9, 0x1c, 0x21,
+
+        /* hop-by-hop */
+        60,
+        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* destination options header */
+        43,
+        2, 1, 2, 0, 0, 201, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* routing header*/
+        44,
+        2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        /* fragment header */
+        0x33,
+        0, 0, 0, 0, 0, 0, 0,
+
+        0x32,
+        0x04, 0x00, 0x00, 0x81, 0x79, 0xb7, 0x05, 0x00, 0x00, 0x00, 0x01, 0x27,
+        0xcf, 0xc0, 0xa5, 0xe4, 0x3d, 0x69, 0xb3, 0x72, 0x8e, 0xc5, 0xb0, 0x49,
+        0x50, 0x77, 0x37, 0x20, 0x45, 0x53, 0x50};
+
+static kal_uint8 g_ipc_ut_igmp_pkt_1[] = {0x46, 0x00, 0x00, 0x30, 0x05, 0xf9,
+                                         0x00, 0x00, 0x01, 0x02, 0x7c, 0x0e,
+                                         0xc0, 0xa8, 0x02, 0x02, 0xe0, 0x00,
+                                         0x00, 0x16, 0x94, 0x04, 0x00, 0x00,
+                                         0x22, 0x00, 0x05, 0x06, 0x00, 0x00,
+                                         0x00, 0x02, 0x04, 0x00, 0x00, 0x00,
+                                         0xe0, 0x00, 0x00, 0xfc, 0x04, 0x00,
+                                         0x00, 0x00, 0xef, 0xff, 0xff, 0xfa};
+
+static kal_uint8 g_ipc_ut_igmp_pkt_2[] = {0x46, 0x00, 0x00, 0x28, 0x05, 0xf0,
+                                         0x00, 0x00, 0x01, 0x02, 0x7c, 0x1f,
+                                         0xc0, 0xa8, 0x02, 0x02, 0xe0, 0x00,
+                                         0x00, 0x16, 0x94, 0x04, 0x00, 0x00,
+                                         0x22, 0x00, 0xf9, 0x01, 0x00, 0x00,
+                                         0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+                                         0xe0, 0x00, 0x00, 0xfc, 0x00, 0x00,
+                                         0x00, 0x00, 0x00, 0x00};
+/* UDP large packet 2000 bytes */
+static kal_uint8 g_ipc_ut_large_udp_pkt[] = {
+    0x45, 0x00, 0x07, 0xec, 0x28, 0xb3, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0xac, 0x11, 0x15, 0x8e,
+    0x3e, 0xd2, 0x12, 0x28, 0xf1, 0xca, 0x14, 0x50, 0x07, 0xd8, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x7f,
+    0x5d, 0x6f, 0x34, 0xae, 0x00, 0x09, 0x61, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x18,
+    0x00, 0x10, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39
+};
+
+/* UDP large packet 3632 bytes */
+static kal_uint8 g_ipc_ut_large_udp_pkt_s3632[] = {
+    0x45, 0x00, 0x0E, 0x30, 0x28, 0xb3, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0xac, 0x11, 0x15, 0x8e,
+    0x3e, 0xd2, 0x12, 0x28, 0x1e, 0xd2, 0x14, 0x50, 0x07, 0xd8, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x7f,
+    0x5d, 0x6f, 0x34, 0xae, 0x00, 0x09, 0x61, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x18,
+    0x00, 0x10, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x36, 0x37, 0x38, 0x39,
+    0x45, 0x00, 0x0E, 0x30, 0x28, 0xb3, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0xac, 0x11, 0x15, 0x8e,
+    0x3e, 0xd2, 0x12, 0x28, 0xf1, 0xca, 0x14, 0x50, 0x07, 0xd8, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x7f,
+    0x5d, 0x6f, 0x34, 0xae, 0x00, 0x09, 0x61, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x18,
+    0x00, 0x10, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31,
+    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
+    0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31
+};
+
+/* ICMPv6 RA packet */
+static kal_uint8 g_ipc_ut_icmpv6_ra_pkt[] = {
+    0x60, 0x00, 0x00, 0x00, 0x00, 0x38, 0x3a, 0xff, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x86, 0x00, 0xc6, 0x34, 0xff, 0x00, 0xfd, 0x20,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x40, 0x40, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x24, 0x08, 0x84, 0xe2, 0x03, 0x1a, 0xbf, 0xca,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0x9c
+};
+
+static kal_uint8 g_ipc_ut_icmpv6_rs_pkt[] = {
+    0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3a, 0xff, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xbc, 0x5a, 0xf9, 0x63, 0x58, 0x32, 0x0f, 0xab, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x85, 0x00, 0xf0, 0xee, 0x00, 0x00, 0x00, 0x00,
+    0x01, 0x01, 0x00, 0x0c, 0x29, 0xc4, 0x43, 0xd3
+};
+
+static kal_uint8 g_ipc_ut_icmp_rs_pkt[] = {
+    0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x00, 0x01, 0x01, 0xee, 0xa1, 0xc0, 0xa8, 0xca, 0x97,
+    0xff, 0xff, 0xff, 0xff, 0x0a, 0x00, 0xf5, 0xff, 0x00, 0x00, 0x00, 0x00
+};
+
+static kal_uint8 g_ipc_ut_icmp_ra_pkt[] = {
+    0x45, 0x00, 0x00, 0x24, 0x00, 0x00, 0x40, 0x00, 0x01, 0x01, 0xee, 0xa1, 0xc0, 0xa8, 0xca, 0x97,
+    0xff, 0xff, 0xff, 0xff, 0x09, 0x00, 0x34, 0x55, 0x01, 0x02, 0x00, 0xff, 0xc0, 0xa8, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+    0x8f, 0x00, 0x2b, 0x5a, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0xff, 0x05, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00,
+    0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02
+};
+
+static const unsigned char pkt2508_1[] = {
+    0x66, 0x80, 0x00, 0x00, 0x04, 0xe8, 0x2c, 0x38, 0x20, 0x01, 0x20, 0x61, 0x20, 0x00, 0x00, 0x1d,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x01, 0x20, 0x61, 0x20, 0x40, 0x90, 0x53,
+    0x07, 0x09, 0x05, 0x6b, 0x52, 0xfa, 0x05, 0xdd, 0x2c, 0x00, 0x00, 0x01, 0x00, 0x28, 0x74, 0x4a,
+    0x32, 0x00, 0x00, 0x01, 0x67, 0xa1, 0xfe, 0x64, 0x48, 0x1f, 0xde, 0x70, 0x00, 0x00, 0x00, 0x0b,
+    0xed, 0xf8, 0x54, 0x8b, 0xc8, 0x3f, 0xa2, 0x02, 0x39, 0xf8, 0x9c, 0xd2, 0xd8, 0xec, 0xcc, 0x03,
+    0xa4, 0x70, 0x7c, 0xfc, 0xa4, 0x79, 0x86, 0xfc, 0xcf, 0x15, 0x6c, 0x2b, 0xbe, 0x33, 0x1d, 0x22,
+    0x85, 0x69, 0xc0, 0x90, 0x88, 0xa1, 0x4d, 0xbc, 0x92, 0x27, 0x4a, 0x6c, 0xbb, 0x38, 0xda, 0xcf,
+    0x0d, 0xc2, 0x88, 0xd9, 0x7c, 0x34, 0xaf, 0x30, 0xde, 0x72, 0xb6, 0xd5, 0x66, 0xd7, 0x2a, 0x01,
+    0xfb, 0x4a, 0x87, 0x66, 0x27, 0x72, 0xa5, 0x35, 0x41, 0x02, 0x4b, 0x46, 0x0d, 0xa4, 0xb6, 0xd3,
+    0x91, 0xae, 0x88, 0x6a, 0x92, 0x32, 0x3f, 0x1e, 0xe5, 0xc2, 0x15, 0x55, 0x0d, 0x04, 0xc9, 0x83,
+    0x09, 0xa4, 0x3a, 0x39, 0x59, 0xda, 0xda, 0x4f, 0xb1, 0x07, 0xa3, 0x17, 0xa1, 0x13, 0x7b, 0xfb,
+    0x72, 0xe5, 0xce, 0x16, 0xfd, 0x18, 0xa9, 0xe2, 0xbe, 0xbf, 0x7a, 0xd9, 0x73, 0x70, 0xb7, 0xc4,
+    0xa7, 0xb3, 0x06, 0x16, 0xb8, 0x6e, 0x21, 0x36, 0xd7, 0xf3, 0x67, 0xbf, 0x58, 0x6d, 0xdf, 0x52,
+    0x12, 0x18, 0x60, 0xf7, 0xe2, 0xf7, 0x6d, 0x97, 0xaa, 0xd9, 0xf8, 0x78, 0xb9, 0xdb, 0x82, 0x7a,
+    0xc4, 0x91, 0xba, 0xfe, 0xdd, 0x9e, 0x17, 0x3b, 0x31, 0xb6, 0xc8, 0x2a, 0x5f, 0xbc, 0x53, 0x01,
+    0xbf, 0xb8, 0x53, 0x23, 0x98, 0xbd, 0xdd, 0x45, 0x83, 0xee, 0x31, 0x06, 0xa7, 0x4b, 0x37, 0x77,
+    0x4d, 0xb3, 0x23, 0xa3, 0xce, 0x0e, 0x3c, 0xbc, 0x28, 0x1b, 0xa0, 0xf8, 0x64, 0x1a, 0x92, 0xc3,
+    0x9c, 0xf0, 0x94, 0x8c, 0x96, 0x5c, 0x90, 0xb2, 0x72, 0x1e, 0x0b, 0x44, 0x8d, 0xee, 0x69, 0x4c,
+    0x4f, 0xb2, 0xca, 0x1a, 0x38, 0x6d, 0x37, 0x56, 0xf8, 0x7b, 0xa4, 0x4e, 0xd4, 0xf7, 0xb4, 0xa9,
+    0x3f, 0x74, 0xf8, 0x99, 0x8d, 0x12, 0x93, 0x97, 0x09, 0x41, 0xb4, 0x06, 0xe1, 0xbb, 0x1b, 0x22,
+    0x13, 0xb3, 0x48, 0x13, 0x55, 0x4b, 0x78, 0xdd, 0x96, 0x31, 0x78, 0x46, 0x72, 0xc5, 0xfd, 0x54,
+    0x8d, 0x0e, 0xfc, 0x37, 0x68, 0xed, 0xb2, 0x72, 0x03, 0x85, 0x06, 0x55, 0x7b, 0xfc, 0x3a, 0x59,
+    0xc4, 0x48, 0x0e, 0x0e, 0x14, 0x79, 0xaa, 0x8a, 0x73, 0xfa, 0xd8, 0x9d, 0xe1, 0x58, 0xb6, 0x2c,
+    0x19, 0x81, 0xbb, 0x3d, 0x5e, 0x81, 0x45, 0x6e, 0x97, 0x26, 0x75, 0x62, 0x67, 0x00, 0x88, 0x8e,
+    0x48, 0xf9, 0x90, 0xf6, 0xb6, 0x70, 0x9e, 0xd8, 0x45, 0x93, 0x60, 0xa9, 0x2d, 0xc4, 0x26, 0xa7,
+    0x1d, 0x94, 0x27, 0x79, 0x1f, 0xa9, 0xc6, 0x48, 0xd6, 0x58, 0xeb, 0xef, 0x8b, 0x4b, 0x8c, 0x25,
+    0x9d, 0x2d, 0x89, 0x70, 0x01, 0x80, 0x7a, 0xe7, 0xfb, 0x43, 0x90, 0x8b, 0x1c, 0x0b, 0xc9, 0x4f,
+    0xd0, 0x1e, 0xac, 0x64, 0x41, 0x7c, 0x7c, 0x63, 0xec, 0xe1, 0xad, 0xdd, 0x8f, 0xb8, 0x42, 0x87,
+    0xfe, 0x76, 0xab, 0x88, 0x8a, 0x55, 0x7a, 0x6a, 0xd0, 0x86, 0xa5, 0x29, 0x84, 0x75, 0x01, 0xca,
+    0x38, 0x7f, 0x0e, 0xc9, 0xfc, 0xfe, 0xb1, 0xf0, 0x89, 0xb4, 0x7e, 0x15, 0xce, 0xcc, 0xcf, 0x76,
+    0xec, 0x68, 0xa1, 0xeb, 0xa6, 0x8a, 0x8c, 0xec, 0x59, 0x9f, 0x4c, 0x28, 0xea, 0x8b, 0x83, 0x57,
+    0xe8, 0x78, 0x36, 0x56, 0x2a, 0x13, 0xcf, 0x7d, 0x10, 0x3d, 0x83, 0x31, 0xca, 0xaa, 0xc3, 0xa4,
+    0xf1, 0x41, 0xd0, 0x02, 0xa9, 0x04, 0x70, 0xa9, 0x39, 0x00, 0x41, 0x41, 0x12, 0x95, 0xea, 0xfd,
+    0xa9, 0xe3, 0x15, 0xe6, 0x84, 0x9a, 0x3d, 0xbf, 0x6b, 0x88, 0xf3, 0x3b, 0xce, 0x06, 0xef, 0x8d,
+    0x14, 0x72, 0xb1, 0x11, 0x09, 0x1c, 0xf9, 0x53, 0xa5, 0x15, 0xd5, 0x95, 0xe4, 0xd5, 0x65, 0xdb,
+    0xab, 0xf0, 0x3f, 0x0f, 0xba, 0xb8, 0x7f, 0xf1, 0x36, 0x6b, 0xf2, 0x4d, 0xb5, 0xd9, 0xf7, 0xe2,
+    0xad, 0x9c, 0x54, 0xfb, 0x01, 0x54, 0xc3, 0x2d, 0x2b, 0x00, 0xb2, 0xdb, 0xd0, 0x8c, 0x15, 0xe0,
+    0x3b, 0xab, 0x3d, 0x29, 0xe1, 0x6b, 0xcd, 0x43, 0x71, 0x0c, 0xbe, 0xcd, 0x3d, 0xd1, 0xf6, 0xd0,
+    0x80, 0x13, 0xbd, 0x61, 0x21, 0x7e, 0x03, 0x7b, 0x25, 0x5d, 0xf3, 0xce, 0xa6, 0x9c, 0xd6, 0x4c,
+    0x70, 0x1b, 0x92, 0x52, 0xf3, 0x8d, 0x5a, 0x9a, 0xa6, 0x21, 0x50, 0x3b, 0x02, 0x95, 0x1f, 0xa1,
+    0x86, 0x22, 0xb6, 0x4a, 0x57, 0x22, 0x78, 0x7d, 0xbd, 0x44, 0xb8, 0x05, 0x99, 0x26, 0x75, 0x01,
+    0xec, 0xeb, 0x58, 0xe9, 0xe8, 0xc5, 0xfd, 0x2f, 0xf2, 0xf6, 0x0c, 0xdc, 0x1d, 0x34, 0xe1, 0x15,
+    0x30, 0x41, 0xfd, 0x23, 0x2e, 0x85, 0x37, 0x5f, 0xd1, 0xe7, 0x61, 0xb6, 0x60, 0x30, 0x8b, 0x6d,
+    0xe7, 0xe4, 0xd3, 0x67, 0x37, 0xb8, 0xec, 0xe8, 0x7e, 0xa5, 0xde, 0xd0, 0x1c, 0x4d, 0x4c, 0x2b,
+    0x29, 0x88, 0x19, 0x9f, 0xbf, 0xba, 0xa8, 0x36, 0x43, 0x6c, 0xde, 0xfd, 0x5e, 0x61, 0x5d, 0x3c,
+    0xe3, 0x89, 0x87, 0xb8, 0x92, 0x26, 0xc5, 0xf6, 0xdb, 0x1d, 0x89, 0x2b, 0x01, 0x98, 0x3b, 0x2d,
+    0xfe, 0xe5, 0x28, 0x00, 0x9f, 0x76, 0x75, 0xae, 0x50, 0xd7, 0xb8, 0x88, 0x6f, 0xcb, 0x11, 0x25,
+    0xbd, 0x8d, 0x57, 0x5c, 0xfb, 0x45, 0x9b, 0xfe, 0x1c, 0xac, 0x09, 0x11, 0x55, 0x1b, 0x11, 0x8c,
+    0xc8, 0x54, 0x1f, 0x65, 0x1a, 0x4f, 0xcb, 0x70, 0x7d, 0x45, 0x64, 0x73, 0x11, 0x08, 0x46, 0x88,
+    0x5d, 0x84, 0x56, 0x6b, 0x19, 0xfc, 0x77, 0x8e, 0x0d, 0x26, 0x44, 0xad, 0x37, 0x6b, 0x2d, 0xdf,
+    0xfe, 0x41, 0xb0, 0x4f, 0x1f, 0x5d, 0x5e, 0x9c, 0x2c, 0x56, 0xf8, 0x89, 0x52, 0x09, 0x97, 0x5c,
+    0x8e, 0xbb, 0xcb, 0x8d, 0x26, 0xac, 0xa3, 0xbd, 0xa6, 0x87, 0x68, 0xaa, 0xa5, 0x0c, 0x30, 0xa7,
+    0x13, 0x8f, 0x13, 0x23, 0x84, 0x88, 0x5b, 0xa0, 0xeb, 0x39, 0x5e, 0xce, 0x00, 0x8d, 0x19, 0x54,
+    0x1d, 0x12, 0x52, 0xe9, 0x4b, 0xb2, 0x08, 0x87, 0x2b, 0xda, 0xf4, 0x53, 0x7c, 0xfa, 0x9e, 0x92,
+    0x76, 0x54, 0x1c, 0x4f, 0xd8, 0x1b, 0x5b, 0x20, 0xe6, 0xfc, 0x17, 0x14, 0x72, 0x5c, 0xe1, 0xce,
+    0x41, 0x68, 0x16, 0x62, 0xc8, 0x16, 0x0a, 0x63, 0x30, 0x90, 0xf4, 0xa8, 0x8d, 0x0f, 0xe2, 0xf9,
+    0xda, 0x32, 0x8b, 0xd0, 0x72, 0x25, 0x01, 0xbf, 0x0a, 0xeb, 0xbb, 0x50, 0x1e, 0x7c, 0x69, 0xad,
+    0xba, 0x3f, 0x7d, 0x25, 0x99, 0xbf, 0x9c, 0x57, 0x7e, 0xb0, 0x35, 0xcc, 0xfd, 0x51, 0x67, 0x14,
+    0x9c, 0x55, 0xd0, 0xb5, 0xb6, 0xb6, 0x51, 0xc4, 0x0a, 0x35, 0x81, 0xbd, 0x8b, 0x62, 0xf4, 0x87,
+    0xa5, 0x85, 0x64, 0x77, 0x73, 0x5e, 0x3c, 0x0f, 0x5d, 0xb1, 0xe4, 0x9c, 0x58, 0xbb, 0x80, 0x3a,
+    0x38, 0xaa, 0x30, 0x38, 0xd9, 0xfb, 0x75, 0x1d, 0x93, 0xfb, 0xd3, 0xf2, 0xd3, 0x4a, 0x45, 0x2f,
+    0xe5, 0xb8, 0x03, 0xe8, 0x83, 0x78, 0x80, 0x1a, 0x76, 0x20, 0x41, 0x6f, 0x82, 0x18, 0x89, 0x11,
+    0xe2, 0x3a, 0xad, 0xd5, 0x0c, 0x5e, 0xa6, 0x4a, 0x95, 0x51, 0x23, 0x4c, 0xc1, 0x4d, 0x88, 0x45,
+    0x6c, 0xaa, 0xe9, 0xf7, 0x18, 0x44, 0xfa, 0x4c, 0x47, 0x1d, 0xc7, 0x9e, 0xa5, 0x12, 0xd3, 0x80,
+    0x30, 0x05, 0x2e, 0x5f, 0x77, 0x09, 0xc3, 0xfa, 0x78, 0x48, 0x36, 0x92, 0x40, 0x86, 0x39, 0x47,
+    0x63, 0xaa, 0x75, 0x27, 0x44, 0xb9, 0x5c, 0x9c, 0xf7, 0x9d, 0x3e, 0x4e, 0x95, 0x5e, 0x10, 0x67,
+    0x4a, 0xdf, 0xbb, 0xcb, 0x82, 0x1c, 0x7d, 0xf0, 0xfd, 0xe1, 0x74, 0x34, 0x4d, 0xa4, 0x14, 0x94,
+    0x55, 0x67, 0x88, 0x01, 0xff, 0xd5, 0x62, 0x11, 0x37, 0xb1, 0xea, 0x7d, 0x52, 0xf3, 0x2e, 0xe2,
+    0x95, 0x9f, 0xa1, 0x81, 0x9b, 0xef, 0xe5, 0x14, 0x75, 0x13, 0x73, 0x69, 0xf4, 0xfa, 0x09, 0xeb,
+    0x2f, 0x1c, 0xed, 0xf4, 0x2d, 0xc7, 0x2b, 0xda, 0x55, 0xb8, 0xe4, 0xd0, 0x9c, 0x32, 0x38, 0xbb,
+    0x34, 0xaf, 0xf8, 0x09, 0x4d, 0x00, 0x97, 0x4c, 0x93, 0x80, 0x22, 0xdf, 0xd1, 0xe6, 0x57, 0x1c,
+    0x86, 0xc9, 0xa7, 0x1f, 0xbb, 0xd1, 0x12, 0x93, 0x0a, 0xbc, 0x3a, 0xf8, 0x5b, 0xaf, 0x33, 0xd6,
+    0xd6, 0x17, 0x73, 0x6b, 0xc5, 0x4f, 0xda, 0x8b, 0x45, 0xe5, 0xab, 0x88, 0x42, 0x6b, 0xe7, 0xbb,
+    0x96, 0xc9, 0x89, 0xc0, 0x71, 0xb6, 0x0a, 0x8f, 0x43, 0xf2, 0x80, 0xe4, 0x3b, 0xe9, 0x60, 0x98,
+    0xa2, 0x6b, 0x56, 0xef, 0xe7, 0x81, 0x72, 0x71, 0xd5, 0x3c, 0x73, 0xff, 0x3d, 0x15, 0x21, 0x3b,
+    0x3b, 0xa0, 0x0d, 0x57, 0x8e, 0x82, 0x82, 0x6c, 0x47, 0xc1, 0x32, 0x24, 0x77, 0xb2, 0xe3, 0x38,
+    0x68, 0x57, 0x7f, 0xa3, 0x04, 0xa2, 0x20, 0x4d, 0xee, 0xe8, 0x6b, 0x18, 0xb1, 0x0f, 0x37, 0x6d,
+    0x67, 0x9b, 0xd6, 0xbd, 0xb7, 0x65, 0x7d, 0x0f, 0xb0, 0x17, 0x5f, 0xd8, 0x37, 0x6d, 0x12, 0xdb,
+    0x69, 0x1c, 0x12, 0x11, 0x4d, 0xaa, 0x58, 0xf9, 0x7d, 0x6d, 0x40, 0x69, 0xd2, 0x3e, 0x5c, 0x35,
+    0xc9, 0x49, 0xd9, 0x44, 0xfd, 0x17, 0x5c, 0xa8, 0x8d, 0xe2, 0xe9, 0x5c, 0x39, 0x85, 0xab, 0xbe,
+    0xd2, 0x61, 0xab, 0x41, 0x37, 0xd0, 0x6c, 0x39, 0xb9, 0x57, 0x2c, 0xdf, 0x03, 0x34, 0x4b, 0xed
+};
+
+static const unsigned char pkt2509_1[] = {
+    0x66, 0x80, 0x00, 0x00, 0x00, 0xa8, 0x2c, 0x38, 0x20, 0x01, 0x20, 0x61, 0x20, 0x00, 0x00, 0x1d,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x01, 0x20, 0x61, 0x20, 0x40, 0x90, 0x53,
+    0x07, 0x09, 0x05, 0x6b, 0x52, 0xfa, 0x05, 0xdd, 0x2c, 0x00, 0x04, 0xe0, 0x00, 0x28, 0x74, 0x4a,
+    0x28, 0xb0, 0x77, 0xea, 0x91, 0x1e, 0xfc, 0xda, 0xa2, 0xc3, 0xf1, 0x57, 0x96, 0xd9, 0xd5, 0x72,
+    0xbc, 0xe4, 0x9c, 0xa8, 0xba, 0x77, 0x93, 0x3c, 0x04, 0x9f, 0x86, 0xc5, 0x12, 0xe3, 0x09, 0x07,
+    0x63, 0xa0, 0xd3, 0x0f, 0xff, 0x36, 0xe9, 0xf0, 0x0b, 0x65, 0x10, 0xe8, 0xa5, 0x0d, 0xf9, 0x4e,
+    0x3f, 0x4a, 0x27, 0xee, 0x51, 0x82, 0x28, 0xca, 0xfa, 0xfd, 0x9e, 0xb2, 0x32, 0x9f, 0x2e, 0xa8,
+    0x8e, 0x25, 0xcd, 0xb0, 0xc2, 0x59, 0x8a, 0xd6, 0x5b, 0x7b, 0xff, 0x56, 0x18, 0xae, 0x2a, 0x18,
+    0xd2, 0x9e, 0x99, 0xc1, 0x12, 0xf5, 0x76, 0x4c, 0x8a, 0xd1, 0xf9, 0x96, 0xba, 0x97, 0xfc, 0xf6,
+    0x65, 0xe6, 0xf3, 0x6a, 0x2d, 0x82, 0x80, 0x19, 0x59, 0x41, 0x9a, 0x0d, 0x5d, 0x7d, 0x1d, 0x59,
+    0x7a, 0x55, 0xe0, 0x3b, 0x4b, 0x24, 0x30, 0x8f, 0xab, 0x5f, 0x4e, 0x4f, 0x0f, 0x25, 0x5d, 0x11,
+    0x6d, 0xcc, 0xba, 0x9c, 0xc6, 0xa1, 0x73, 0xe1, 0xac, 0x18, 0x3c, 0xe8, 0xff, 0xee, 0x25, 0x2f,
+    0xba, 0x47, 0x75, 0x9f, 0x4f, 0x6a, 0x97, 0x4c, 0xe4, 0xa5, 0xef, 0xc9, 0xb1, 0x6c, 0xed, 0xfc
+};
+
+static const unsigned char pkt2510_1[108] = {
+    0x66, 0x80, 0x00, 0x00, 0x00, 0x34, 0x2c, 0x38, 0x20, 0x01, 0x20, 0x61, 0x20, 0x00, 0x00, 0x1d,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x01, 0x20, 0x61, 0x20, 0x40, 0x90, 0x53,
+    0x07, 0x09, 0x05, 0x6b, 0x52, 0xfa, 0x05, 0xdd, 0x32, 0x00, 0x05, 0x78, 0x67, 0xa1, 0xfe, 0x64,
+    0x9c, 0x19, 0xe0, 0x15, 0xfe, 0x43, 0x1e, 0x06, 0xe6, 0x9f, 0xb8, 0x96, 0x12, 0x58, 0x77, 0xfc,
+    0xa3, 0x84, 0x78, 0xac, 0x60, 0xa5, 0x78, 0x10, 0xfd, 0x7e, 0x39, 0xd1, 0x85, 0xee, 0xc3, 0xb5,
+    0x0d, 0x47, 0x2a, 0x79, 0x30, 0x67, 0x6d, 0x9d, 0xc7, 0xcd, 0x65, 0x3b
+};
+
+
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+static kal_uint8 ipc_ut_invalid_len_ip_packet[IPC_INVALID_MAX_PKT_LEN];
+#endif
+
+#define UT_ASSERT ASSERT
+
+/*------------------------------------------------------------------------------
+ * Private Helper macros
+ *
+ * IPCore log level = {1, 2, 3, etc}
+ * level = 1   => use fake printf
+ * level = 2   => open utILOG utDLOG utELOG
+ * level = 3   => open utILOG utELOG
+ * level = etc => no log
+ *----------------------------------------------------------------------------*/
+#define IPC_UT_ERR_PREFIX __FILE__ ":" __LINE__ ": "
+
+#define ipc_ut_log(_fmts, ...) \
+        _ipc_ut_log("%s():%d " _fmts "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+
+#ifdef __unix__
+#define utELOG(_fmts, ...) \
+        kal_sprintf(p_ret_err_str, "%s:%d: " _fmts, __FILE__, __LINE__, ##__VA_ARGS__); \
+        _ipc_ut_log("[FAILED] %s():%d - " _fmts "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+        UT_ASSERT(KAL_FALSE);
+#else
+#define utELOG(_fmts, ...) \
+        _ipc_ut_log("[FAILED] %s():%d - " _fmts "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+        UT_ASSERT(KAL_FALSE);
+#endif
+
+#define utILOG ipc_ut_log
+#define utDLOG ipc_ut_log
+
+#if IPC_UT_LOG_LV == 1
+    extern int fake_print(const char *fmt, ...);
+    #define _ipc_ut_log fake_print
+#elif IPC_UT_LOG_LV == 2
+    #define _ipc_ut_log printf
+#elif IPC_UT_LOG_LV == 3
+    #define _ipc_ut_log printf
+    #undef utDLOG
+    #define utDLOG
+#else
+    #define _ipc_ut_log
+#endif
+
+#define IPC_UT_PASS() utILOG("\r\n===================================>PASSED\r\n")
+
+#ifdef __SE7_SD8_AUTO_UT__
+    #undef  UT_ASSERT
+    #define UT_ASSERT(args) \
+        { \
+            if (!(args)) { \
+                ipc_ut_log("Assert failed !!! (%s)", #args); \
+            } \
+        }
+    #undef  IPC_UT_PASS()
+    #define IPC_UT_PASS()
+#endif
+
+/*------------------------------------------------------------------------------
+ * Private functions.
+ *----------------------------------------------------------------------------*/
+void ipc_ut_msg_reset(void * latest_local_param_p, kal_uint32 latest_local_param_size, void * latest_peer_buff_p, kal_uint32 latest_peer_buff_size);
+void ipc_ut_init(void);
+
+void ipc_ut_ul_filter_callback(void *context, kal_int32 filter_id, qbm_gpd *head_gpd, qbm_gpd *tail_gpd, kal_uint32 length);
+void ipc_ut_dl_filter_callback(void *context, kal_int32 filter_id, qbm_gpd *head_gpd, qbm_gpd *tail_gpd, kal_uint32 length);
+void ipc_ut_ul_filter_with_info_callback(ipc_filter_info_t *info_p, void *context, kal_int32 filter_id, qbm_gpd *head_gpd, qbm_gpd *tail_gpd, kal_uint32 length);
+void ipc_ut_dl_filter_with_info_callback(ipc_filter_info_t *info_p, void *context, kal_int32 filter_id, qbm_gpd *head_gpd, qbm_gpd *tail_gpd, kal_uint32 length);
+kal_bool ipc_ut_ul_filter_registration(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz);
+kal_bool ipc_ut_dl_filter_registration(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz);
+void ipc_ut_reset_ul_info(void);
+void ipc_ut_reset_ul_filter_info(void);
+void ipc_ut_reset_dl_filter_info(void);
+void ipc_ut_reset_dl_callback_info(void);
+kal_bool ipc_ut_ul_reload(void *context);
+kal_bool ipc_ut_dl_callback(void *context, ipc_io_request_t *ior);
+kal_int32 ipc_ut_check_netif(ipc_netif_t *netif, ipc_ut_netif_t *net);
+kal_int32 ipc_ut_check_session(ipc_session_t *session, ipc_ut_netif_t *net);
+void ipc_ut_prepare_ul_gpd_list(kal_bool allValidIpPkt, kal_uint32 ipv4_cnt, kal_uint32 dhcpv4_idx, kal_uint32 ipv6_cnt, kal_uint32 dhcpv6_idx, qbm_gpd **head_gpd, qbm_gpd **tail_gpd, ipc_io_request_t **ior);
+void ipc_ut_prepare_dl_gpd_list(kal_uint32 ipv4_cnt, kal_uint32 dhcpv4_idx, kal_bool dnsv4_only, kal_bool v4hdr_exist, kal_uint32 ipv6_cnt, kal_uint32 dhcpv6_idx, kal_bool dnsv6_only, kal_bool v6hdr_exist, kal_uint32 additional_bd_cnt, kal_uint32 align_offset, qbm_gpd **head_gpd, qbm_gpd **tail_gpd, kal_uint16 *ipv4_invalid_packet_len, kal_uint16 *ipv6_invalid_packet_len, kal_bool spd_enable, kal_bool spd_igr_bit_enable, ipc_ut_spd_position_e spd_position);
+void ipc_ut_free_gpd_list(qbm_gpd *head_gpd, qbm_gpd *tail_gpd);
+kal_uint32 ipc_ut_gpd_list_count(qbm_gpd *head_gpd, qbm_gpd *tail_gpd);
+kal_uint32 ipc_ut_non_igr_meta_count(kal_uint32 start_idx, kal_uint32 end_idx, LHIF_QUEUE_TYPE q_type);
+kal_uint32 ipc_ut_spd_payload_count(qbm_gpd *head_gpd, qbm_gpd *tail_gpd);
+void ipc_ut_install_ul_filters(kal_bool callback_with_info, kal_bool with_callback, kal_uint32 ipv4_filter_cnt, kal_uint32 ipv6_filter_cnt, kal_bool with_wildcard, kal_bool with_bwm, kal_uint8 matched_filter_idx_v4, kal_uint8 matched_filter_idx_v6, kal_uint32 good_netif_id);
+void ipc_ut_install_dl_filters(kal_bool callback_with_info, kal_bool with_callback, kal_uint32 ipv4_filter_cnt, kal_uint32 ipv6_filter_cnt, kal_uint8 matched_filter_idx_v4, kal_uint8 matched_filter_idx_v6, kal_uint32 netif_id);
+void ipc_ut_uninstall_ul_filters(kal_uint32 ipv4_filter_cnt, kal_uint32 ipv6_filter_cnt, kal_bool with_wildcard, kal_bool with_bwm);
+void ipc_ut_uninstall_dl_filters(kal_uint32 ipv4_filter_cnt, kal_uint32 ipv6_filter_cnt);
+#if defined(__MTK_TARGET__)
+kal_bool ipc_ut_struct(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz);
+#endif
+
+void ipc_ut_msg_reset(void * latest_local_param_p,
+                      kal_uint32 latest_local_param_size,
+                      void * latest_peer_buff_p,
+                      kal_uint32 latest_peer_buff_size) {
+    kal_mem_set(&ipc_ut_msg_sent, 0, sizeof(ipc_ut_msg_sent));
+    ipc_latest_local_param_p = latest_local_param_p;
+    ipc_latest_local_param_size = latest_local_param_size;
+    ipc_latest_peer_buff_p = latest_peer_buff_p;
+    ipc_latest_peer_buff_size = latest_peer_buff_size;
+}
+
+void ipc_ut_init_meta(void) {
+    kal_uint32 idx;
+    kal_uint8 i;
+    static kal_bool is_first_init = KAL_TRUE;
+
+    if (is_first_init) {
+        kal_mem_set(ipc_ut_meta_queues, 0, sizeof(ipc_ut_meta_queue_t));
+        is_first_init = KAL_FALSE;
+    }
+
+    for (i = 0; i < IPC_UT_META_QUEUE_NUM_MAX; i++) {
+        switch (i) {
+            case IPC_UT_LHIF_META_AP0:
+                kal_mem_set(ipc_ut_meta_tbl_s, 0, sizeof(ipc_ut_meta_tbl_s)*IPC_UT_META_TABLE_SIZE);
+                for (idx = 0; idx < IPC_UT_META_TABLE_SIZE; idx++) {
+                    ipc_ut_meta_tbl_s[idx].vrb_addr = ipc_ut_meta_ring_buf_s[idx];
+                }
+                ipc_ut_meta_queues[i].base_addr = (kal_uint8*)ipc_ut_meta_tbl_s;
+                ipc_ut_meta_queues[i].type_idx = i;
+                break;
+            case IPC_UT_IPF_DL_0:
+                kal_mem_set(ipc_ut_dl_meta_tbl_s, 0, sizeof(ipc_ut_dl_meta_tbl_s)*IPC_UT_META_TABLE_SIZE);
+                for (idx = 0; idx < IPC_UT_META_TABLE_SIZE; idx++) {
+                    ipc_ut_dl_meta_tbl_s[idx].addr = (kal_uint32)ipc_ut_meta_ring_buf_s[idx];
+                }
+                ipc_ut_meta_queues[i].base_addr = (kal_uint8*)ipc_ut_dl_meta_tbl_s;
+                ipc_ut_meta_queues[i].type_idx = i;
+                break;
+            default:
+                UT_ASSERT(0);
+                break;
+        }
+    }
+}
+
+void ipc_ut_init_spd(void) {
+    //qbm_reg_cbk_peek_before_free(QBM_TYPE_HIF_DL_SPD, NULL);
+}
+
+void ipc_ut_init(void) {
+    // init for ut case
+    ipc_ut_init_meta();
+    ipc_ut_init_spd();
+
+    // reset message
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+
+    // disabled DPFM
+    ipc_ut_dpfm_is_activated_g = KAL_FALSE;
+}
+
+void ipc_ut_ul_filter_callback(void *context,
+                               kal_int32 filter_id,
+                               qbm_gpd *head_gpd,
+                               qbm_gpd *tail_gpd,
+                               kal_uint32 length) {
+    ipc_ut_ul_filter_with_info_callback(NULL, context, filter_id, head_gpd, tail_gpd, length);
+}
+
+void ipc_ut_dl_filter_callback(void *context,
+                               kal_int32 filter_id,
+                               qbm_gpd *head_gpd,
+                               qbm_gpd *tail_gpd,
+                               kal_uint32 length) {
+    ipc_ut_dl_filter_with_info_callback(NULL, context, filter_id, head_gpd, tail_gpd, length);
+}
+
+void ipc_ut_ul_filter_with_info_callback(ipc_filter_info_t *info_p,
+                                         void *context,
+                                         kal_int32 filter_id,
+                                         qbm_gpd *head_gpd,
+                                         qbm_gpd *tail_gpd,
+                                         kal_uint32 length) {
+    if (info_p) {
+        kal_mem_cpy(&ipc_ut_ul_filter_info, info_p, sizeof(ipc_filter_info_t));
+    } else {
+        kal_mem_set(&ipc_ut_ul_filter_info, 0, sizeof(ipc_filter_info_t));
+        ipc_ut_ul_filter_info.ip_id = -1;
+        ipc_ut_ul_filter_info.ebi = -1;
+    }
+
+    ipc_ut_ul_filter_id = filter_id;
+    ipc_ut_ul_filter_gpd_cnt += ipc_ut_gpd_list_count(head_gpd, tail_gpd);
+
+
+    if (NULL == ipc_ut_ul_head_gpd) {
+        ipc_ut_ul_head_gpd = head_gpd;
+    }
+
+    if (ipc_ut_ul_tail_gpd) {
+        QBM_DES_SET_NEXT(ipc_ut_ul_tail_gpd, head_gpd);
+    }
+    ipc_ut_ul_tail_gpd = tail_gpd;
+}
+
+void ipc_ut_dl_filter_with_info_callback(ipc_filter_info_t *info_p,
+                                         void *context,
+                                         kal_int32 filter_id,
+                                         qbm_gpd *head_gpd,
+                                         qbm_gpd *tail_gpd,
+                                         kal_uint32 length) {
+    if (info_p) {
+        kal_mem_cpy(&ipc_ut_dl_filter_info, info_p, sizeof(ipc_filter_info_t));
+        ((upcm_dlvr_dl_info_t *)QBM_DES_GET_SW_CTRL_FIELD(head_gpd))->ebi = 0;
+    } else {
+        kal_mem_set(&ipc_ut_dl_filter_info, 0, sizeof(ipc_filter_info_t));
+        ipc_ut_dl_filter_info.ip_id = -1;
+    }
+
+    ipc_ut_dl_filter_id = filter_id;
+    ipc_ut_dl_filter_gpd_cnt += ipc_ut_gpd_list_count(head_gpd, tail_gpd);
+    ipc_ut_dl_filter_spd_payload_cnt += ipc_ut_spd_payload_count(head_gpd, tail_gpd);
+
+    if (NULL == ipc_ut_dl_head_gpd) {
+        ipc_ut_dl_head_gpd = head_gpd;
+    }
+
+    if (ipc_ut_dl_tail_gpd) {
+        QBM_DES_SET_NEXT(ipc_ut_dl_tail_gpd, head_gpd);
+    }
+    ipc_ut_dl_tail_gpd = tail_gpd;
+}
+
+kal_bool ipc_ut_ul_filter_registration(void *p_param,
+                                       kal_char *p_ret_err_str,
+                                       kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32              callback_with_info = {0};
+    kal_uint32              idx = 0;
+    ipc_ut_filter_info_t   *info = NULL;
+    ipc_filter_rules_t     *rules = NULL;
+    ipc_filter_rules_t      invalid_rules = {0};
+    kal_int32               filter_id = 0;
+    ipc_filter_ntfy_ctxt_t  ntfy_ctxt = {0};
+
+    /* init before test */
+    ipc_ut_init();
+
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++) {
+        /*
+         * Negative cases for filter registration:
+         * 1. Register without callback function.
+         * 2. invalid rules.
+         */
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->valid_fields = IPC_FILTER_BY_SRC_IPV4;
+        kal_mem_set(&ntfy_ctxt, 0, sizeof(ipc_filter_ntfy_ctxt_t));
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_NG != ipc_ut_get_error()) {
+            utELOG("register a filter without callback function shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->valid_fields = 0;
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register an invalid UL filter is shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->valid_fields = IPC_FILTER_BY_SRC_IPV6;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register a IPv4 filter with invalid rules shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV6;
+        rules->valid_fields = IPC_FILTER_BY_SRC_IPV4;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register a IPv6 filter with invalid rules shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_MIXED;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register a IPv4v6 filter with invalid rules shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->valid_fields = IPC_FILTER_BY_PROTOCOL;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register a IPv4 filter with invalid protocol type shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->valid_fields = IPC_FILTER_BY_EBI;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register an EBI rule to uplink filter shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->valid_fields = IPC_FILTER_BY_PDN_ID;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register a PDN ID rule to uplink filter shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * Positive cases for filter registration:
+         */
+        kal_mem_set(ipc_ut_info_set, 0, sizeof(ipc_ut_info_set));
+        for (idx = 0; idx < IPC_MAX_FILTER_CNT; idx++) {
+            info = &ipc_ut_info_set[idx];
+            ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+            rules = &info->rules;
+            kal_mem_set(rules, 0, sizeof(*rules));
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_DST_PORT);
+            rules->ip_type = IPC_IP_TYPE_IPV4;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 3344+idx;
+            rules->dst_port = 5566;
+
+            ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+            ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+            ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+            ntfy_ctxt.p_ntfy_args = (void *)info;
+
+            if (idx < (IPC_MAX_FILTER_CNT / 2)) {
+                if (callback_with_info == 0) {
+                    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+                    info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+                } else {
+                    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+                    info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+                }
+            } else {
+                if (callback_with_info == 0) {
+                    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM;
+                    info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+                } else {
+                    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO;
+                    info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+                }
+            }
+            if (0 > info->filter_id || IPC_UT_NO_ERROR != ipc_ut_get_error()) {
+                utELOG("failed to register a valid filter!\r\n");
+                return KAL_FALSE;
+            }
+        }
+
+        /*
+         * Negative cases for filter registration:
+         * 3. all filters are busy.
+         */
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                IPC_FILTER_BY_SRC_PORT |
+                                IPC_FILTER_BY_DST_PORT);
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->protocol = IPC_HDR_PROT_UDP;
+        rules->src_port = 67;
+        rules->dst_port = 66;
+        rules->valid_fields = IPC_FILTER_BY_PROTOCOL;
+
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+        ntfy_ctxt.p_ntfy_args = NULL;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_NG != ipc_ut_get_error()) {
+            utELOG("register a filter while all filters are busy shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * Negative case for filter deregisteration:
+         * 1. invalid filter id in invalid range.
+         */
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        ipc_dereg_filter(IPC_MAX_FILTER_CNT);
+        if (IPC_UT_DEREGISTER_FILTER_WITH_INVALID_ID != ipc_ut_get_error()) {
+            utELOG("deregister a invalid filter shall get a fail resule!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        ipc_dereg_filter(-1);
+        if (IPC_UT_DEREGISTER_FILTER_WITH_INVALID_ID != ipc_ut_get_error()) {
+            utELOG("deregister a invalid filter shall get a fail resule!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * Positive case for filter deregisteration.
+         */
+        for (idx = 0; idx < IPC_MAX_FILTER_CNT; idx++) {
+            info = &ipc_ut_info_set[idx];
+            ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+            ipc_dereg_filter(info->filter_id);
+            if (IPC_UT_NO_ERROR != ipc_ut_get_error()) {
+                utELOG("failed to deregister a valid filter!\r\n");
+                return KAL_FALSE;
+            }
+
+            /*
+             * Negative case for filter deregisteration:
+             * 2. filter unregistered.
+             */
+            UT_ASSERT(KAL_FALSE == ipc_dereg_filter(info->filter_id));
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_filter_registration(void *p_param,
+                                       kal_char *p_ret_err_str,
+                                       kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32              callback_with_info = {0};
+    kal_uint32              idx = 0;
+    ipc_ut_filter_info_t   *info = NULL;
+    ipc_filter_rules_t     *rules = NULL;
+    ipc_filter_rules_t      invalid_rules = {0};
+    kal_int32               filter_id = 0;
+    ipc_filter_ntfy_ctxt_t  ntfy_ctxt = {0};
+
+    /* init before test */
+    ipc_ut_init();
+
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++) {
+        /*
+         * Negative cases for filter registration:
+         * 1. Register without callback function.
+         * 2. invalid rules.
+         */
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->pdn_id = IPC_UT_PDN_ID;
+        rules->valid_fields = IPC_FILTER_BY_SRC_IPV4 | IPC_FILTER_BY_PDN_ID;
+        kal_mem_set(&ntfy_ctxt, 0, sizeof(ipc_filter_ntfy_ctxt_t));
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_NG != ipc_ut_get_error()) {
+            utELOG("register a filter without callback function shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->valid_fields = 0;
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_dl_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_dl_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register an invalid DL filter is shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->pdn_id = IPC_UT_PDN_ID;
+        rules->valid_fields = IPC_FILTER_BY_SRC_IPV6 | IPC_FILTER_BY_PDN_ID;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register a IPv4 filter with invalid rules shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV6;
+        rules->pdn_id = IPC_UT_PDN_ID;
+        rules->valid_fields = IPC_FILTER_BY_SRC_IPV4 | IPC_FILTER_BY_PDN_ID;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register a IPv6 filter with invalid rules shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_MIXED;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register a IPv4v6 filter with invalid rules shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->pdn_id = IPC_UT_PDN_ID;
+        rules->valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_PDN_ID;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if (0 <= filter_id ||
+            IPC_UT_REGISTER_FILTER_VALIDATE_FAIL != ipc_ut_get_error()) {
+            utELOG("register a IPv4 filter with invalid protocol type shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * Positive cases for filter registration:
+         */
+        kal_mem_set(ipc_ut_info_set, 0, sizeof(ipc_ut_info_set));
+        for (idx = 0; idx < IPC_MAX_FILTER_CNT; idx++) {
+            info = &ipc_ut_info_set[idx];
+            ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+            rules = &info->rules;
+            kal_mem_set(rules, 0, sizeof(*rules));
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_DST_PORT |
+                                   IPC_FILTER_BY_PDN_ID);
+            rules->ip_type = IPC_IP_TYPE_IPV4;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 3344+idx;
+            rules->dst_port = 5566;
+            rules->pdn_id = IPC_UT_PDN_ID;
+            if (idx < (IPC_MAX_FILTER_CNT / 2)) {
+                if (callback_with_info == 0) {
+                    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+                    info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+                } else {
+                    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+                    info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+                }
+            } else {
+                if (callback_with_info == 0) {
+                    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM;
+                    info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+                } else {
+                    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO;
+                    info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+                }
+            }
+            if (0 > info->filter_id || IPC_UT_NO_ERROR != ipc_ut_get_error()) {
+                utELOG("failed to register a valid filter!\r\n");
+                return KAL_FALSE;
+            }
+        }
+
+        /*
+         * Negative cases for filter registration:
+         * 3. all filters are busy.
+         */
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        rules = &invalid_rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                IPC_FILTER_BY_SRC_PORT |
+                                IPC_FILTER_BY_DST_PORT);
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->protocol = IPC_HDR_PROT_UDP;
+        rules->src_port = 67;
+        rules->dst_port = 66;
+        rules->pdn_id = IPC_UT_PDN_ID;
+        rules->valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_PDN_ID;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        if ((0 <= filter_id) ||
+            (IPC_UT_REGISTER_FILTER_NG != ipc_ut_get_error())) {
+            utELOG("register a filter while all filters are busy shall get a negetive filter_id in return!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * Negative case for filter deregisteration:
+         * 1. invalid filter id in invalid range.
+         */
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        ipc_dereg_filter(IPC_MAX_FILTER_CNT);
+        if (IPC_UT_DEREGISTER_FILTER_WITH_INVALID_ID != ipc_ut_get_error()) {
+            utELOG("deregister a invalid filter shall get a fail resule!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        ipc_dereg_filter(-1);
+        if (IPC_UT_DEREGISTER_FILTER_WITH_INVALID_ID != ipc_ut_get_error()) {
+            utELOG("deregister a invalid filter shall get a fail resule!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * Positive case for filter deregisteration.
+         */
+        for (idx = 0; idx < IPC_MAX_FILTER_CNT; idx++) {
+            info = &ipc_ut_info_set[idx];
+            ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+            ipc_dereg_filter(info->filter_id);
+            if (IPC_UT_NO_ERROR != ipc_ut_get_error()) {
+                utELOG("failed to deregister a valid filter!\r\n");
+                return KAL_FALSE;
+            }
+
+            /*
+             * Negative case for filter deregisteration:
+             * 2. filter unregistered.
+             */
+            UT_ASSERT(KAL_FALSE == ipc_dereg_filter(info->filter_id));
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ul_reload(void *context)
+{
+    ipc_ut_netif_t *net = (ipc_ut_netif_t *)context;
+
+    net->ul_reload_called = KAL_TRUE;
+    return net->need_retry;
+}
+
+void ipc_ut_reset_dl_callback_info(void)
+{
+    ipc_ut_dl_callback_gpd_cnt = 0;
+    ipc_ut_dl_callback_spd_payload_cnt = 0;
+    ipc_ut_dl_callback_did_cnt = 0;
+    ipc_ut_dl_callback_did_pkt_cnt = 0;
+    ipc_ut_dl_callback_did_dpfm_pkt_cnt = 0;
+    ipc_ut_dl_callback_did_dpfm_cnt = 0;
+    ipc_ut_dl_meta_buf_free_num_s = 0;
+}
+
+kal_bool ipc_ut_dl_callback(void *context, ipc_io_request_t *ior)
+{
+    UT_ASSERT(NULL != ior);
+
+    /*
+     * Calculate total GPD count put into callback function
+     */
+    {
+        ipc_io_request_t *ior_p = NULL;
+        ipc_io_request_t *next_ior = NULL;
+
+        for (ior_p = ior; ior_p; ior_p = next_ior) {
+            next_ior = ior_p->next_request;
+            if (ior_p->first_gpd && ior_p->last_gpd) {
+                ipc_ut_dl_callback_gpd_cnt += ipc_ut_gpd_list_count(ior_p->first_gpd, ior_p->last_gpd);
+                ipc_ut_dl_callback_spd_payload_cnt += ipc_ut_spd_payload_count(ior_p->first_gpd, ior_p->last_gpd);
+            }
+        }
+    }
+
+    /*
+     * Destroy whole IOR
+     */
+    ipc_dest_ior(ior);
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_callback_did(void *context, upcm_did *did)
+{
+    UT_ASSERT(NULL != did);
+
+    ipc_ut_dl_callback_did_cnt ++;
+    ipc_ut_dl_callback_did_pkt_cnt += UPCM_DID_GET_PKT_NUM(did);
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_callback_did_ra(void *context, upcm_did *did)
+{
+    kal_uint8 *p_data = NULL;
+    upcm_did_si *sit = NULL;
+    kal_uint32 i = 0;
+    kal_uint32 pkt_count = 0;
+    kal_int32 comp_result = 0;
+
+    UT_ASSERT(NULL != did);
+
+    ipc_ut_dl_callback_did_cnt ++;
+    ipc_ut_dl_callback_did_pkt_cnt += UPCM_DID_GET_PKT_NUM(did);
+    pkt_count = UPCM_DID_GET_PKT_NUM(did);
+    UT_ASSERT(1 == pkt_count);
+
+    /* Check if packet content is RA */
+    sit = UPCM_DID_GET_SIT_PTR(did);
+    p_data = UPCM_DID_SI_GET_DATAPTR(sit);
+    UT_ASSERT(sizeof(g_ipc_ut_icmpv6_ra_pkt) == UPCM_DID_SI_GET_LEN(sit));
+    comp_result = kal_mem_cmp(p_data, g_ipc_ut_icmpv6_ra_pkt, sizeof(g_ipc_ut_icmpv6_ra_pkt));
+    UT_ASSERT(0 == comp_result);
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_callback_did_dpfm(void *context, upcm_did *did)
+{
+    UT_ASSERT(NULL != did);
+
+    ipc_ut_dl_callback_did_dpfm_cnt ++;
+    ipc_ut_dl_callback_did_dpfm_pkt_cnt += UPCM_DID_GET_PKT_NUM(did);
+
+    return KAL_TRUE;
+}
+
+kal_int32 ipc_ut_check_netif(ipc_netif_t *netif, ipc_ut_netif_t *net)
+{
+    kal_uint32 error_code = 0;
+
+    if (netif) {
+        do {
+            if (net->handle != netif) {
+                error_code = -2;
+                break;
+            }
+
+            if (kal_mem_cmp(&net->conf, &netif->config, sizeof(ipc_conf_t))) {
+                error_code = -3;
+                break;
+            }
+        } while (0);
+        IPC_R_UNLOCK_OBJECT(netif, ipc_spinlock_g);
+    } else {
+        error_code = -1;
+    }
+
+    return error_code;
+}
+
+kal_int32 ipc_ut_check_session(ipc_session_t *session, ipc_ut_netif_t *net)
+{
+    kal_uint32 error_code = 0;
+    kal_uint32 ip_id = 0;
+    ipc_session_t *tmp_session = NULL;
+
+    if (session) {
+        do {
+            if (net->session[net->ip_type] != session) {
+                error_code = -2;
+                break;
+            }
+
+            if (net->pdn_id != session->context) {
+                error_code = -3;
+                break;
+            }
+
+            if (net->ip_type != session->type) {
+                error_code = -4;
+                break;
+            }
+
+            if (net->handle != session->netif) {
+                error_code = -5;
+                break;
+            }
+
+            ip_id = ipc_get_ip_id(net->handle);
+            if (session->ip_id != ip_id) {
+                error_code = -6;
+                break;
+            }
+
+            tmp_session = ipc_find_session_by_ip_id(ip_id,
+                                                    ((IPC_IP_TYPE_MIXED == session->type) ? IPC_IP_TYPE_IPV4 : session->type));
+            if (tmp_session) {
+                if (ip_id != tmp_session->ip_id) {
+                    error_code = -7;
+                    IPC_R_UNLOCK_OBJECT(tmp_session, ipc_spinlock_g);
+                    break;
+                }
+                if (session != tmp_session) {
+                    error_code = -8;
+                    IPC_R_UNLOCK_OBJECT(tmp_session, ipc_spinlock_g);
+                    break;
+                }
+                IPC_R_UNLOCK_OBJECT(tmp_session, ipc_spinlock_g);
+            }
+        } while (0);
+
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+    } else {
+        error_code = -1;
+    }
+
+    return error_code;
+}
+
+void ipc_ut_reset_ul_filter_info(void)
+{
+    kal_mem_set(&ipc_ut_ul_filter_info, 0, sizeof(ipc_filter_info_t));
+    ipc_ut_ul_filter_info.ip_id = -1;
+    ipc_ut_ul_filter_info.ebi = -1;
+    ipc_ut_ul_filter_id = -1;
+    ipc_ut_ul_filter_gpd_cnt = 0;
+}
+
+void ipc_ut_reset_dl_filter_info(void)
+{
+    kal_mem_set(&ipc_ut_dl_filter_info, 0, sizeof(ipc_filter_info_t));
+    ipc_ut_dl_filter_info.ip_id = -1;
+    ipc_ut_dl_filter_info.ebi = -1;
+    ipc_ut_dl_filter_id = -1;
+    ipc_ut_dl_filter_gpd_cnt = 0;
+    ipc_ut_dl_filter_expect_gpd_cnt = 0;
+    ipc_ut_dl_filter_spd_payload_cnt = 0;
+}
+
+void ipc_ut_reset_did(upcm_did *did)
+{
+    upcm_did_si *sit = UPCM_DID_GET_SIT_PTR(did);
+    kal_uint32 did_idx;
+
+    did_idx = did - ipc_ut_did_tbl_s;
+    kal_mem_set(&(did->sit), 0, sizeof(upcm_did_si) * UPCM_DID_MAX_SIT_ENT_NUM);
+}
+
+kal_uint32 ipc_ut_alloc_did(kal_uint32 request_num,
+                            upcm_did **p_did_head,
+                            upcm_did **p_did_tail) {
+#if 1
+    kal_uint32  alloc_num;
+    upcm_did   *did;
+    upcm_did   *prev_did = NULL;
+    upcm_did   *next_did;
+    kal_bool    end_of_list;
+
+    alloc_num = upcm_did_alloc_q(request_num, p_did_head, p_did_tail);
+
+    end_of_list = KAL_FALSE;
+    for (did = *p_did_head; did && !end_of_list; did = next_did) {
+        next_did = UPCM_DID_GET_NEXT(did);
+        end_of_list = (did == *p_did_tail);
+        ipc_ut_reset_did(did);
+
+        if (prev_did) {
+            UPCM_DID_SET_NEXT(prev_did, did);
+        }
+        prev_did = did;
+    }
+
+    return alloc_num;
+#else
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+}
+
+void ipc_ut_reset_meta(kal_uint32 start_idx,
+                       kal_uint32 end_idx,
+                       LHIF_QUEUE_TYPE q_type) {
+    kal_uint32 i = start_idx;
+
+
+    while (i != end_idx) {
+        switch (q_type) {
+            case IPC_UT_LHIF_META_AP0:
+                kal_mem_set(&ipc_ut_meta_tbl_s[i], 0, sizeof(lhif_meta_tbl_t));
+                ipc_ut_meta_tbl_s[i].vrb_addr = ipc_ut_meta_ring_buf_s[i];
+                break;
+            case IPC_UT_IPF_DL_0:
+                kal_mem_set(&ipc_ut_dl_meta_tbl_s[i], 0, sizeof(ipf_dl_meta));
+                ipc_ut_dl_meta_tbl_s[i].addr = (kal_uint32)ipc_ut_meta_ring_buf_s[i];
+                break;
+            default:
+                UT_ASSERT(0);
+                break;
+        }
+        i ++;
+        if (i == IPC_UT_META_TABLE_SIZE) {
+            i = 0;
+        }
+    }
+}
+
+kal_uint32 ipc_ut_alloc_meta(
+        ipc_ut_meta_type_e  q_type,
+        kal_uint32          request_num,
+        kal_uint32         *p_head_idx,
+        kal_uint32         *p_tail_idx) {
+    kal_uint32 alloc_num, used_num, remain_num;
+
+    kal_uint8 write_idx, read_idx;
+
+    write_idx = ipc_ut_meta_queues[q_type].write_idx;
+    read_idx = ipc_ut_meta_queues[q_type].read_idx;
+
+    used_num = (write_idx >= read_idx)
+                    ? (write_idx - read_idx) :
+                      (IPC_UT_META_TABLE_SIZE - read_idx + write_idx);
+    remain_num = IPC_UT_META_TABLE_SIZE - used_num - 1;
+    alloc_num = (request_num > remain_num) ? remain_num : request_num;
+
+    *p_head_idx = write_idx;
+    write_idx += alloc_num;
+    if (write_idx >= IPC_UT_META_TABLE_SIZE) {
+        write_idx -= IPC_UT_META_TABLE_SIZE;
+    }
+    *p_tail_idx = write_idx;
+
+    ipc_ut_meta_queues[q_type].write_idx = write_idx;
+
+    ipc_ut_reset_meta(*p_head_idx, *p_tail_idx, q_type);
+
+    return alloc_num;
+}
+
+void ipc_ut_meta_read_done(kal_uint32 start_idx,
+                           kal_uint32 end_idx,
+                           LHIF_QUEUE_TYPE q_type) {
+    kal_uint32 used_num, free_num;
+    kal_uint8 write_idx, read_idx;
+
+    write_idx = ipc_ut_meta_queues[IPC_UT_LHIF_META_AP0].write_idx;
+    read_idx = ipc_ut_meta_queues[IPC_UT_LHIF_META_AP0].read_idx;
+
+    UT_ASSERT(LHIF_HWQ_AP_UL_Q0 == q_type);
+    UT_ASSERT(start_idx == read_idx);
+
+    used_num = (write_idx >= read_idx)
+                    ? (write_idx - read_idx) :
+                      (IPC_UT_META_TABLE_SIZE - read_idx + write_idx);
+    free_num = (end_idx > start_idx) ? (end_idx - start_idx) : (IPC_UT_META_TABLE_SIZE - start_idx + end_idx);
+
+    UT_ASSERT(free_num <= used_num);
+
+    ipc_ut_meta_queues[IPC_UT_LHIF_META_AP0].read_idx = end_idx;
+}
+
+void ipc_ut_release_ipf_meta_entry(kal_uint16 rel_num, kal_uint32 ipf_meta_q_type) {
+    kal_uint32 used_num;
+    kal_uint8 write_idx, read_idx;
+
+    write_idx = ipc_ut_meta_queues[IPC_UT_IPF_DL_0].write_idx;
+    read_idx = ipc_ut_meta_queues[IPC_UT_IPF_DL_0].read_idx;
+
+    used_num = (write_idx >= read_idx)
+                    ? (write_idx - read_idx) :
+                      (IPC_UT_META_TABLE_SIZE - read_idx + write_idx);
+
+    UT_ASSERT(rel_num <= used_num);
+
+    ipc_ut_meta_queues[IPC_UT_IPF_DL_0].read_idx = ((read_idx + rel_num)>=IPC_UT_META_TABLE_SIZE)
+                                                        ?(read_idx+rel_num-IPC_UT_META_TABLE_SIZE):(read_idx+rel_num);
+}
+
+kal_bool ipc_ut_query_meta_table(kal_uint32 **base_addr, kal_uint16 *size, LHIF_QUEUE_TYPE queue_type) {
+    *base_addr = (kal_uint32 *)ipc_ut_meta_tbl_s;
+    *size = IPC_UT_META_TABLE_SIZE;
+
+    return KAL_TRUE;
+}
+
+void ipc_ut_fill_ipf_ul_meta_content(
+        lhif_meta_tbl_t *meta,
+        kal_uint8 idx,
+        kal_bool is_ipv6,
+        kal_uint8 proto_idx,
+        kal_uint8 test_stage,
+        kal_bool is_meta_mr,
+        kal_uint32 dhcp_idx) {
+    kal_bool is_pn_match;
+
+    if ( (IPC_UT_STAGE_BEFORE_BINDING == test_stage) || (IPC_UT_STAGE_UNBINDING == test_stage)) {
+        is_pn_match = KAL_FALSE;
+    }
+    else {
+        is_pn_match = KAL_TRUE;
+    }
+
+    if (is_pn_match && ((idx % 2) == 0)) {
+        meta->protocol_idx = proto_idx;
+        meta->pdn = IPC_UT_PDN_ID;
+    }
+
+    meta->ip = is_ipv6;
+
+    if(is_ipv6){
+        meta->match_index = IPC_UT_META_MATCH_IDX+1;
+    }
+    else{
+        meta->match_index = IPC_UT_META_MATCH_IDX;
+    }
+
+    if(KAL_FALSE == is_meta_mr){
+        if(dhcp_idx == idx){
+            meta->mr = IPC_HPC_MR_UNKNOWN;
+            meta->match_index = 0;
+        }else{
+            switch (idx % IPC_HPC_MR_MAX) {
+                case 0:
+                    meta->mr = IPC_HPC_MR_UNKNOWN;
+                    meta->match_index = 0;
+                    break;
+                case 1:
+                    meta->mr = IPC_HPC_MR_NEW;
+                    break;
+                case 2:
+                    /* MR_MATCH should be after MR_NEW*/
+                    meta->mr = IPC_HPC_MR_MATCH;
+                    break;
+                default:
+                // default is unknown
+                meta->mr = IPC_HPC_MR_UNKNOWN;
+                meta->match_index = 0;
+                break;
+            }
+        }
+    }else{
+        switch (idx % IPC_HPC_MR_MAX) {
+            case 0:
+                meta->mr = IPC_HPC_MR_UNKNOWN;
+                meta->match_index = 0;
+                break;
+            case 1:
+                meta->mr = IPC_HPC_MR_NEW;
+                break;
+            case 2:
+                /* MR_MATCH should be after MR_NEW*/
+                meta->mr = IPC_HPC_MR_MATCH;
+                break;
+            case 3:
+                meta->mr = IPC_HPC_MR_DPFM_MATCH;
+                break;
+            case 4:
+                meta->mr = IPC_HPC_MR_DPFM_MATCH_BUT_NO_NAT;
+                break;
+            case 5:
+                meta->mr = IPC_HPC_MR_DPFM_DEL_CMD_MATCH;
+                meta->match_index = 0;
+                break;
+            case 6:
+                meta->mr = IPC_HPC_MR_DPFM_DEL_CMD_MISS;
+                meta->match_index = 0;
+                break;
+            case 7:
+                meta->mr = IPC_HPC_MR_DPFM_ADD_CMD;
+                meta->match_index = 0;
+                break;
+            default:
+                // default is unknown
+                meta->mr = IPC_HPC_MR_UNKNOWN;
+                meta->match_index = 0;
+                break;
+        }
+    }
+}
+
+void ipc_ut_prepare_ul_meta_list_dpfm(
+        kal_bool allMatchIpPkt,
+        kal_uint32 ipv4_cnt,
+        kal_uint32 ipv6_cnt,
+        kal_uint32 *p_head_idx,
+        kal_uint32 *p_tail_idx,
+        LHIF_QUEUE_TYPE *q_type,
+        kal_uint32 netif_id,
+        kal_uint8 proto_idx,
+        kal_uint8 test_stage) {
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx;
+    kal_uint32          curr_meta_idx;
+    lhif_meta_tbl_t    *curr_meta;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          netif_id_prefix = (netif_id & 0xFFFFFF00);
+    kal_uint8           sequence = 0;
+
+    if (total_cnt != ipc_ut_alloc_meta(
+                        IPC_UT_LHIF_META_AP0, //LHIF_HWQ_AP_UL_Q0,
+                        total_cnt,
+                        p_head_idx,
+                        p_tail_idx)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+    *q_type = LHIF_HWQ_AP_UL_Q0;
+    curr_meta_idx = *p_head_idx;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        curr_meta = &ipc_ut_meta_tbl_s[curr_meta_idx];
+        curr_meta->net_type = ((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS;
+        curr_meta->channel_id = netif_id & 0x0000001F;
+
+        if(KAL_TRUE == allMatchIpPkt){
+            packet_buf = ipc_ut_ipv4_dhcp_ul_packet;
+            packet_len = sizeof(ipc_ut_ipv4_dhcp_ul_packet);
+        } else {
+            packet_buf = ipc_ut_ipv4_dns_packet;
+            packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+        }
+
+        kal_mem_cpy(curr_meta->vrb_addr, packet_buf, packet_len);
+        curr_meta->length = packet_len;
+
+#if defined(__IPF_SUPPORT__)
+        // Fill IPF meta entry
+        ipc_ut_fill_ipf_ul_meta_content(curr_meta, idx, KAL_FALSE, proto_idx, test_stage, KAL_TRUE, 0);
+#endif
+
+        //assign sequence
+        curr_meta->psn = sequence;
+        sequence ++;
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        curr_meta = &ipc_ut_meta_tbl_s[curr_meta_idx];
+        curr_meta->net_type = ((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS;
+        curr_meta->channel_id = netif_id & 0x0000001F;
+
+        if(KAL_TRUE == allMatchIpPkt){
+            packet_buf = ipc_ut_ipv6_ext0_dhcp_ul_packet;
+            packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_ul_packet);
+        } else {
+            packet_buf = ipc_ut_ipv6_mdns_packet;
+            packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+        }
+
+        kal_mem_cpy(curr_meta->vrb_addr, packet_buf, packet_len);
+        curr_meta->length = packet_len;
+
+#if defined(__IPF_SUPPORT__)
+       // Fill IPF meta entry
+       ipc_ut_fill_ipf_ul_meta_content(curr_meta, idx, KAL_TRUE, proto_idx, test_stage, KAL_TRUE, 0);
+#endif
+
+        //assign sequence
+        curr_meta->psn = sequence;
+        sequence ++;
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+}
+
+
+void ipc_ut_prepare_ul_meta_list(
+        kal_bool allValidIpPkt,
+        kal_uint32 ipv4_cnt,
+        kal_uint32 dhcpv4_idx,
+        kal_uint32 ipv6_cnt,
+        kal_uint32 dhcpv6_idx,
+        kal_uint32 *p_head_idx,
+        kal_uint32 *p_tail_idx,
+        LHIF_QUEUE_TYPE *q_type,
+        kal_uint32 netif_id,
+        kal_uint8 proto_idx,
+        kal_uint8 test_stage) {
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx;
+    kal_uint32          curr_meta_idx;
+    lhif_meta_tbl_t    *curr_meta;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          netif_id_prefix = (netif_id & 0xFFFFFF00);
+    kal_uint8           sequence = 0;
+
+    if (total_cnt != ipc_ut_alloc_meta(
+                        IPC_UT_LHIF_META_AP0, //LHIF_HWQ_AP_UL_Q0,
+                        total_cnt,
+                        p_head_idx,
+                        p_tail_idx)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+    *q_type = LHIF_HWQ_AP_UL_Q0;
+    curr_meta_idx = *p_head_idx;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        curr_meta = &ipc_ut_meta_tbl_s[curr_meta_idx];
+        curr_meta->net_type = ((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS;
+        curr_meta->channel_id = netif_id & 0x0000001F;
+
+        if (idx == dhcpv4_idx) {
+            packet_buf = ipc_ut_ipv4_dhcp_ul_packet;
+            packet_len = sizeof(ipc_ut_ipv4_dhcp_ul_packet);
+        } else {
+            /* Other packets */
+            switch (idx % 6) {
+            case 0:
+                if (KAL_TRUE == allValidIpPkt) {
+                    packet_buf = ipc_ut_ipv4_dns_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                } else {
+                    packet_buf = ipc_ut_non_ip_packet;
+                    packet_len = sizeof(ipc_ut_non_ip_packet);
+                }
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv4_incomplete_ip_header_packet);
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv4_incomplete_udp_header_packet;
+                packet_len = sizeof(ipc_ut_ipv4_incomplete_udp_header_packet);
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv4_frag0_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag0_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv4_frag1_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag1_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+            }
+        }
+
+        kal_mem_cpy(curr_meta->vrb_addr, packet_buf, packet_len);
+        curr_meta->length = packet_len;
+
+#if defined(__IPF_SUPPORT__)
+        // Fill IPF meta entry
+        ipc_ut_fill_ipf_ul_meta_content(curr_meta, idx, KAL_FALSE, proto_idx, test_stage, KAL_FALSE, dhcpv4_idx);
+#endif
+
+        //assign sequence
+        curr_meta->psn = sequence;
+        sequence ++;
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        curr_meta = &ipc_ut_meta_tbl_s[curr_meta_idx];
+        curr_meta->net_type = ((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS;
+        curr_meta->channel_id = netif_id & 0x0000001F;
+
+        if (idx == dhcpv6_idx) {
+            switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv6_ext0_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_ul_packet);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_ext1_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_ext1_dhcp_ul_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_dhcp_ul_packet);
+            }
+        } else {
+            /* Other packets */
+            switch (idx % 9) {
+            case 0:
+                if (KAL_TRUE == allValidIpPkt) {
+                    packet_buf = ipc_ut_ipv6_mdns_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                } else {
+                    packet_buf = ipc_ut_non_ip_packet;
+                    packet_len = sizeof(ipc_ut_non_ip_packet);
+                }
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ip_header_packet);
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv6_incomplete_hop_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_hop_packet);
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv6_incomplete_ah_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ah_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv6_unknown_ext_packet;
+                packet_len = sizeof(ipc_ut_ipv6_unknown_ext_packet);
+                break;
+            case 5:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv4enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv4enc_packet);
+                break;
+            case 6:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv6enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv6enc_packet);
+                break;
+            case 7:
+                if (ipv6_cnt <= 10) {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag0_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag0_packet);
+                } else {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag1_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag1_packet);
+                }
+                break;
+            case 8:
+                packet_buf = ipc_ut_ipv6_frag_packet;
+                packet_len = sizeof(ipc_ut_ipv6_frag_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_mdns_packet;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                break;
+            }
+        }
+
+        kal_mem_cpy(curr_meta->vrb_addr, packet_buf, packet_len);
+        curr_meta->length = packet_len;
+
+#if defined(__IPF_SUPPORT__)
+       // Fill IPF meta entry
+       ipc_ut_fill_ipf_ul_meta_content(curr_meta, idx, KAL_TRUE, proto_idx, test_stage, KAL_FALSE, dhcpv6_idx);
+#endif
+
+        //assign sequence
+        curr_meta->psn = sequence;
+        sequence ++;
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+}
+
+
+void ipc_ut_prepare_dl_meta_list(kal_bool allValidIpPkt,
+                                 kal_uint32 ipv4_cnt,
+                                 kal_uint32 dhcpv4_idx,
+                                 kal_uint32 ipv6_cnt,
+                                 kal_uint32 dhcpv6_idx,
+                                 kal_uint32 *p_head_idx,
+                                 kal_uint32 *p_tail_idx,
+                                 ipfc_dl_filter_queue_type *q_type,
+                                 kal_uint32 netif_id,
+                                 kal_uint8 match_result)
+{
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx;
+    kal_uint32          curr_meta_idx;
+    ipf_dl_meta         *curr_meta;
+    kal_uint8           *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          netif_id_prefix = (netif_id & 0xFFFFFF00);
+
+    if (total_cnt != ipc_ut_alloc_meta(
+                        IPC_UT_IPF_DL_0, //LHIF_HWQ_AP_UL_Q0,
+                        total_cnt,
+                        p_head_idx,
+                        p_tail_idx)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+    *q_type = IPFC_META_QUEUE_DL;
+    curr_meta_idx = *p_head_idx;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+        curr_meta->channel_id = ((((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS) <<8 )
+                            |(netif_id & 0x000000FF) ;
+
+        if (idx == dhcpv4_idx) {
+            packet_buf = ipc_ut_ipv4_dhcp_packet;
+            packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+            ipc_ut_dl_filter_expect_gpd_cnt++;
+        } else {
+            switch (idx) {
+            case 0:
+                if (ipv4_cnt > 4) {
+                    if ((ipv4_cnt%2) == 0) {
+                        packet_buf = ipc_ut_ipv4_dhcp_packet;
+                        packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                        ipc_ut_dl_filter_expect_gpd_cnt++;
+                    } else {
+                        packet_buf = ipc_ut_non_ip_packet;
+                        packet_len = sizeof(ipc_ut_non_ip_packet);
+                    }
+                }
+                else {
+                    packet_buf = ipc_ut_non_ip_packet;
+                    packet_len = sizeof(ipc_ut_non_ip_packet);
+                }
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv4_incomplete_ip_header_packet);
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv4_incomplete_udp_header_packet;
+                packet_len = sizeof(ipc_ut_ipv4_incomplete_udp_header_packet);
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv4_frag0_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag0_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv4_frag1_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag1_packet);
+                break;
+            default:
+                if ((idx%3) == 0) {
+                    packet_buf = ipc_ut_ipv4_dns_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                } else {
+                    packet_buf = ipc_ut_ipv4_dhcp_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                    ipc_ut_dl_filter_expect_gpd_cnt++;
+                }
+                break;
+            }
+        }
+
+        kal_mem_cpy((kal_uint8*)curr_meta->addr, packet_buf, packet_len);
+        curr_meta->len = packet_len;
+
+        // Fill IP type
+        curr_meta->ip = 0;
+
+        // Fill Match index (don't care value)
+        // we assgin the same value as ip type. it will be reused for querey filter id.
+        curr_meta->match_idx = 0;
+
+        curr_meta->mr = (match_result & 0x07);
+
+        curr_meta->pdn_sim_id = IPC_UT_PDN_ID;
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+        curr_meta->channel_id = ((((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS) <<8 )
+                            |(netif_id & 0x000000FF) ;
+
+
+        if (idx == dhcpv6_idx) {
+            switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv6_ext0_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_packet);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_ext1_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv6_ext1_dhcp_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv6_dhcp_packet);
+            }
+        } else {
+            switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_non_ip_packet;
+                packet_len = sizeof(ipc_ut_non_ip_packet);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ip_header_packet);
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv6_incomplete_hop_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_hop_packet);
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv6_incomplete_ah_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ah_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv6_unknown_ext_packet;
+                packet_len = sizeof(ipc_ut_ipv6_unknown_ext_packet);
+                break;
+            case 5:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv4enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv4enc_packet);
+                break;
+            case 6:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv6enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv6enc_packet);
+                break;
+            case 7:
+                if (ipv6_cnt <= 10) {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag0_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag0_packet);
+                } else {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag1_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag1_packet);
+                }
+                break;
+            case 8:
+                packet_buf = ipc_ut_ipv6_frag_packet;
+                packet_len = sizeof(ipc_ut_ipv6_frag_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_mdns_packet;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                break;
+            }
+        }
+
+        kal_mem_cpy((kal_uint8*)curr_meta->addr, packet_buf, packet_len);
+        curr_meta->len = packet_len;
+
+        // Fill IP type
+        curr_meta->ip = 1;
+
+        // Fill Match index (don't care value)
+        // we assgin the same value as ip type. it will be reused for querey filter id.
+        curr_meta->match_idx = 1;
+
+        curr_meta->mr = (match_result & 0x07);
+
+        curr_meta->pdn_sim_id = IPC_UT_PDN_ID;
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+}
+
+void ipc_ut_prepare_dl_did_list(
+        kal_uint32 ipv4_cnt,
+        kal_uint32 dhcpv4_idx,
+        kal_bool   dnsv4_only,
+        kal_bool   v4hdr_exist,
+        kal_uint32 ipv6_cnt,
+        kal_uint32 dhcpv6_idx,
+        kal_bool   dnsv6_only,
+        kal_bool   v6hdr_exist,
+        kal_uint32 additional_bd_cnt,
+        kal_uint32 align_offset,
+        upcm_did   **did_head,
+        upcm_did   **did_tail,
+        kal_uint16 *ipv4_invalid_packet_len,
+        kal_uint16 *ipv6_invalid_packet_len,
+        kal_uint32 did_cnt,
+        kal_bool    did_igr_enable) {
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx;
+    upcm_did           *curr_did;
+    upcm_did_si        *curr_sit;
+    upcm_did_si        *curr_si;
+    kal_uint32          curr_si_idx;
+    kal_uint32          pkt_start_si_idx;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          pkt_num;
+    kal_uint32          seg_num;
+
+    if (did_cnt != ipc_ut_alloc_did(
+                        did_cnt,
+                        did_head,
+                        did_tail)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did   *next_did;
+        kal_bool    end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (   curr_did = *did_head ;
+                curr_did && (end_of_list == KAL_FALSE) ;
+                curr_did = next_did) {
+            kal_uint32      i;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si    *si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+
+
+    /* Set SIT to the first SIT in DID for data configuration */
+    curr_did = *did_head;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        if (KAL_TRUE == dnsv4_only) {
+            if (KAL_TRUE == v4hdr_exist) {
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+            } else {
+                kal_uint32 offset;
+
+                /* Shift data pointer to reserve headroom */
+                offset = IPC_HDR_V4_GET_IHL(ipc_ut_ipv4_dns_packet) + IPC_HDR_UDP_HEADER_SIZE;
+
+                UPCM_DID_SI_SET_OFFSET(curr_si, UPCM_DID_SI_GET_OFFSET(curr_si) + offset);
+
+                packet_buf = ipc_ut_ipv4_dns_packet + offset;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet) - offset;
+            }
+        } else {
+            if (idx == dhcpv4_idx) {
+                packet_buf = ipc_ut_ipv4_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                ipc_ut_dl_filter_expect_gpd_cnt++;
+            } else {
+                switch (idx) {
+                case 0:
+                    if (ipv4_cnt > 4) {
+                        if ((ipv4_cnt%2) == 0) {
+                            packet_buf = ipc_ut_ipv4_dhcp_packet;
+                            packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                            ipc_ut_dl_filter_expect_gpd_cnt++;
+                        } else {
+                            packet_buf = ipc_ut_non_ip_packet;
+                            packet_len = sizeof(ipc_ut_non_ip_packet);
+                        }
+                    }
+                    else {
+                        packet_buf = ipc_ut_non_ip_packet;
+                        packet_len = sizeof(ipc_ut_non_ip_packet);
+                    }
+                    break;
+                case 1:
+                    packet_buf = ipc_ut_ipv4_incomplete_ip_header_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_incomplete_ip_header_packet);
+                    break;
+                case 2:
+                    packet_buf = ipc_ut_ipv4_incomplete_udp_header_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_incomplete_udp_header_packet);
+                    break;
+                case 3:
+                    packet_buf = ipc_ut_ipv4_frag0_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_frag0_packet);
+                    break;
+                case 4:
+                    packet_buf = ipc_ut_ipv4_frag1_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_frag1_packet);
+                    break;
+                default:
+                    if ((idx%3) == 0) {
+                        packet_buf = ipc_ut_ipv4_dns_packet;
+                        packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                    } else {
+                        packet_buf = ipc_ut_ipv4_dhcp_packet;
+                        packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                        ipc_ut_dl_filter_expect_gpd_cnt++;
+                    }
+                    break;
+                }
+            }
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        // invalid len packet
+        if (ipv4_invalid_packet_len) {
+            if (ipv4_invalid_packet_len[idx] > packet_len) {
+//                 kal_mem_cpy(ipc_ut_invalid_len_ip_packet, packet_buf, packet_len);
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv4_invalid_packet_len[idx]>IPC_INVALID_MAX_PKT_LEN)?IPC_INVALID_MAX_PKT_LEN:ipv4_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+#if 1
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt ++;
+            }
+        }
+#endif
+        if ( (did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx]) ) {
+            kal_uint32      i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num --;
+            }
+        } else {
+            pkt_num ++;
+        }
+    }
+
+    if (ipv4_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        if (KAL_TRUE == dnsv6_only) {
+            if (KAL_TRUE == v6hdr_exist) {
+                packet_buf = ipc_ut_ipv6_mdns_packet;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+            } else {
+                kal_uint32 offset;
+
+                /* Shift data pointer to reserve headroom */
+                offset = IPC_HDR_V6_HEADER_SIZE + IPC_HDR_UDP_HEADER_SIZE;
+
+                UPCM_DID_SI_SET_OFFSET(curr_si, UPCM_DID_SI_GET_OFFSET(curr_si) + offset);
+
+                packet_buf = ipc_ut_ipv6_mdns_packet + offset;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet) - offset;
+            }
+        } else {
+            if (idx == dhcpv6_idx) {
+                switch (idx) {
+                case 0:
+                    packet_buf = ipc_ut_ipv6_ext0_dhcp_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_packet);
+                    break;
+                case 1:
+                    packet_buf = ipc_ut_ipv6_ext1_dhcp_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ext1_dhcp_packet);
+                    break;
+                default:
+                    packet_buf = ipc_ut_ipv6_dhcp_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_dhcp_packet);
+                }
+            } else {
+                switch (idx) {
+                case 0:
+                    packet_buf = ipc_ut_non_ip_packet;
+                    packet_len = sizeof(ipc_ut_non_ip_packet);
+                    break;
+                case 1:
+                    packet_buf = ipc_ut_ipv6_incomplete_ip_header_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_ip_header_packet);
+                    break;
+                case 2:
+                    packet_buf = ipc_ut_ipv6_incomplete_hop_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_hop_packet);
+                    break;
+                case 3:
+                    packet_buf = ipc_ut_ipv6_incomplete_ah_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_ah_packet);
+                    break;
+                case 4:
+                    packet_buf = ipc_ut_ipv6_unknown_ext_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_unknown_ext_packet);
+                    break;
+                case 5:
+                    packet_buf = ipc_ut_ipv6_incomplete_ipv4enc_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv4enc_packet);
+                    break;
+                case 6:
+                    packet_buf = ipc_ut_ipv6_incomplete_ipv6enc_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv6enc_packet);
+                    break;
+                case 7:
+                    if (ipv6_cnt <= 10) {
+                        packet_buf = ipc_ut_ipv6_ipv4enc_frag0_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag0_packet);
+                    } else {
+                        packet_buf = ipc_ut_ipv6_ipv4enc_frag1_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag1_packet);
+                    }
+                    break;
+                case 8:
+                    packet_buf = ipc_ut_ipv6_frag_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_frag_packet);
+                    break;
+                default:
+                    packet_buf = ipc_ut_ipv6_mdns_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                    break;
+                }
+            }
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        // invalid len packet
+        if (ipv6_invalid_packet_len) {
+            if (ipv6_invalid_packet_len[idx] > packet_len) {
+//                 kal_mem_cpy(ipc_ut_invalid_len_ip_packet, packet_buf, packet_len);
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv6_invalid_packet_len[idx]>IPC_INVALID_MAX_PKT_LEN)?IPC_INVALID_MAX_PKT_LEN:ipv6_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+#if 1
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt ++;
+            }
+        }
+#endif
+        if ( (did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx]) ) {
+            kal_uint32      i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num --;
+            }
+        } else {
+            pkt_num ++;
+        }
+    }
+
+    if (ipv6_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+}
+
+void ipc_ut_prepare_pfm_fin_ack_dl_did_list(kal_uint32 ipv4_cnt,
+                                            kal_uint32 dhcpv4_idx,
+                                            kal_bool dnsv4_only,
+                                            kal_bool v4hdr_exist,
+                                            kal_uint32 ipv6_cnt,
+                                            kal_uint32 dhcpv6_idx,
+                                            kal_bool dnsv6_only,
+                                            kal_bool v6hdr_exist,
+                                            kal_uint32 additional_bd_cnt,
+                                            kal_uint32 align_offset,
+                                            upcm_did **did_head,
+                                            upcm_did **did_tail,
+                                            kal_uint16 *ipv4_invalid_packet_len,
+                                            kal_uint16 *ipv6_invalid_packet_len,
+                                            kal_uint32 did_cnt,
+                                            kal_bool did_igr_enable) {
+    kal_uint32 total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32 idx;
+    upcm_did *curr_did;
+    upcm_did_si *curr_sit;
+    upcm_did_si *curr_si;
+    kal_uint32 curr_si_idx;
+    kal_uint32 pkt_start_si_idx;
+    kal_uint8 *packet_buf;
+    kal_uint32 packet_len;
+    kal_uint32 pkt_num;
+    kal_uint32 seg_num;
+
+    if (did_cnt != ipc_ut_alloc_did(did_cnt, did_head, did_tail)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did *next_did;
+        kal_bool end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (curr_did = *did_head; curr_did && (end_of_list == KAL_FALSE);
+                curr_did = next_did) {
+            kal_uint32 i;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si *si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+
+    /* Set SIT to the first SIT in DID for data configuration */
+    curr_did = *did_head;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        if (KAL_TRUE == dnsv4_only) {
+            if (KAL_TRUE == v4hdr_exist) {
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+            } else {
+                kal_uint32 offset;
+
+                /* Shift data pointer to reserve headroom */
+                offset = IPC_HDR_V4_GET_IHL(ipc_ut_ipv4_dns_packet) + IPC_HDR_UDP_HEADER_SIZE;
+
+                UPCM_DID_SI_SET_OFFSET(curr_si, UPCM_DID_SI_GET_OFFSET(curr_si) + offset);
+
+                packet_buf = ipc_ut_ipv4_dns_packet + offset;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet) - offset;
+            }
+        } else {
+            if (idx == dhcpv4_idx) {
+                packet_buf = ipc_ut_ipv4_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                ipc_ut_dl_filter_expect_gpd_cnt++;
+            } else {
+                switch (idx) {
+                    case 0:
+                        if (ipv4_cnt > 4) {
+                            if ((ipv4_cnt % 2) == 0) {
+                                packet_buf = ipc_ut_ipv4_dhcp_packet;
+                                packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                                ipc_ut_dl_filter_expect_gpd_cnt++;
+                            } else {
+                                packet_buf = ipc_ut_non_ip_packet;
+                                packet_len = sizeof(ipc_ut_non_ip_packet);
+                            }
+                        } else {
+                            packet_buf = ipc_ut_ipv4_tcp_fin_ack_packet;
+                            packet_len = sizeof(ipc_ut_ipv4_tcp_fin_ack_packet);
+                            UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                            ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                        }
+                        break;
+                    case 1:
+                        packet_buf = ipc_ut_ipv4_tcp_fin_ack_packet;
+                        packet_len = sizeof(ipc_ut_ipv4_tcp_fin_ack_packet);
+                        UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                        ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                        break;
+                    case 2:
+                        packet_buf = ipc_ut_ipv4_tcp_fin_ack_packet_2;
+                        packet_len = sizeof(ipc_ut_ipv4_tcp_fin_ack_packet_2);
+                        UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                        ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                        break;
+                    case 3:
+                        packet_buf = ipc_ut_ipv4_frag0_packet;
+                        packet_len = sizeof(ipc_ut_ipv4_frag0_packet);
+                        break;
+                    case 4:
+                        packet_buf = ipc_ut_ipv4_tcp_fin_ack_packet_2;
+                        packet_len = sizeof(ipc_ut_ipv4_tcp_fin_ack_packet_2);
+                        UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                        ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                        break;
+                    default:
+                        if ((idx % 3) == 0) {
+                            packet_buf = ipc_ut_ipv4_dns_packet;
+                            packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                        } else {
+                            packet_buf = ipc_ut_ipv4_dhcp_packet;
+                            packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                            ipc_ut_dl_filter_expect_gpd_cnt++;
+                        }
+                        break;
+                }
+            }
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        if (ipv4_invalid_packet_len) {
+            if (ipv4_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv4_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv4_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+#if 1
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) { /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else { /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt++;
+            }
+        }
+#endif
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv4_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        if (KAL_TRUE == dnsv6_only) {
+            if (KAL_TRUE == v6hdr_exist) {
+                packet_buf = ipc_ut_ipv6_mdns_packet;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+            } else {
+                kal_uint32 offset;
+
+                /* Shift data pointer to reserve headroom */
+                offset = IPC_HDR_V6_HEADER_SIZE + IPC_HDR_UDP_HEADER_SIZE;
+
+                UPCM_DID_SI_SET_OFFSET(curr_si, UPCM_DID_SI_GET_OFFSET(curr_si) + offset);
+
+                packet_buf = ipc_ut_ipv6_mdns_packet + offset;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet) - offset;
+            }
+        } else {
+            if (idx == dhcpv6_idx) {
+                switch (idx) {
+                    case 0:
+                        packet_buf = ipc_ut_ipv6_ext0_dhcp_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_packet);
+                        break;
+                    case 1:
+                        packet_buf = ipc_ut_ipv6_ext1_dhcp_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_ext1_dhcp_packet);
+                        break;
+                    default:
+                        packet_buf = ipc_ut_ipv6_dhcp_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_dhcp_packet);
+                }
+            } else {
+                switch (idx) {
+                    case 0:
+                        packet_buf = ipc_ut_ipv6_tcp_fin_ack_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_tcp_fin_ack_packet);
+                        UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                        ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                        break;
+                    case 1:
+                        packet_buf = ipc_ut_ipv6_tcp_fin_ack_packet_2;
+                        packet_len = sizeof(ipc_ut_ipv6_tcp_fin_ack_packet_2);
+                        UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                        ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                        break;
+                    case 2:
+                        packet_buf = ipc_ut_ipv6_tcp_fin_ack_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_tcp_fin_ack_packet);
+                        UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                        ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                        break;
+                    case 3:
+                        packet_buf = ipc_ut_ipv6_tcp_fin_ack_packet_2;
+                        packet_len = sizeof(ipc_ut_ipv6_tcp_fin_ack_packet_2);
+                        UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                        ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                        break;
+                    case 4:
+                        packet_buf = ipc_ut_ipv6_unknown_ext_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_unknown_ext_packet);
+                        break;
+                    case 5:
+                        packet_buf = ipc_ut_ipv6_incomplete_ipv4enc_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv4enc_packet);
+                        break;
+                    case 6:
+                        packet_buf = ipc_ut_ipv6_incomplete_ipv6enc_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv6enc_packet);
+                        break;
+                    case 7:
+                        if (ipv6_cnt <= 10) {
+                            packet_buf = ipc_ut_ipv6_ipv4enc_frag0_packet;
+                            packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag0_packet);
+                        } else {
+                            packet_buf = ipc_ut_ipv6_ipv4enc_frag1_packet;
+                            packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag1_packet);
+                        }
+                        break;
+                    case 8:
+                        packet_buf = ipc_ut_ipv6_frag_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_frag_packet);
+                        break;
+                    default:
+                        packet_buf = ipc_ut_ipv6_mdns_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                        break;
+                }
+            }
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        // invalid len packet
+        if (ipv6_invalid_packet_len) {
+            if (ipv6_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv6_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv6_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) { /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else { /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt++;
+            }
+        }
+
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv6_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+}
+
+void ipc_ut_prepare_ul_gpd_list(kal_bool allValidIpPkt,
+                                kal_uint32 ipv4_cnt,
+                                kal_uint32 dhcpv4_idx,
+                                kal_uint32 ipv6_cnt,
+                                kal_uint32 dhcpv6_idx,
+                                qbm_gpd **head_gpd,
+                                qbm_gpd **tail_gpd,
+                                ipc_io_request_t **ior)
+{
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx = 0;
+    qbm_gpd            *curr_gpd = NULL;
+    qbm_gpd            *bd = NULL;
+    kal_uint8          *packet_buf = NULL;
+    kal_uint32          packet_len = 0;
+
+    ipc_ut_ul_head_gpd = ipc_ut_ul_tail_gpd = NULL;
+    if (ior) {*ior = NULL;}
+
+    if (total_cnt != qbmt_alloc_q(QBM_TYPE_NET_UL, total_cnt, (void **)(head_gpd), (void **)(tail_gpd))) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+    curr_gpd = *head_gpd;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        bd = QBM_DES_GET_DATAPTR(curr_gpd);
+
+        if (idx == dhcpv4_idx) {
+            packet_buf = ipc_ut_ipv4_dhcp_ul_packet;
+            packet_len = sizeof(ipc_ut_ipv4_dhcp_ul_packet);
+        } else {
+            /* Other packets */
+            switch (idx % 6) {
+            case 0:
+                if (KAL_TRUE == allValidIpPkt) {
+                    packet_buf = ipc_ut_ipv4_dns_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                } else {
+                    packet_buf = ipc_ut_non_ip_packet;
+                    packet_len = sizeof(ipc_ut_non_ip_packet);
+                }
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv4_incomplete_ip_header_packet);
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv4_incomplete_udp_header_packet;
+                packet_len = sizeof(ipc_ut_ipv4_incomplete_udp_header_packet);
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv4_frag0_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag0_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv4_frag1_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag1_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+            }
+        }
+
+        kal_mem_cpy(QBM_DES_GET_DATAPTR(bd), packet_buf, packet_len);
+        QBM_DES_SET_DATALEN(bd, packet_len);
+        QBM_DES_SET_DATALEN(curr_gpd, packet_len);
+
+        curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+    }
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        bd = QBM_DES_GET_DATAPTR(curr_gpd);
+
+        if (idx == dhcpv6_idx) {
+            switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv6_ext0_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_ul_packet);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_ext1_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_ext1_dhcp_ul_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_dhcp_ul_packet);
+            }
+        } else {
+            /* Other packets */
+            switch (idx % 9) {
+            case 0:
+                if (KAL_TRUE == allValidIpPkt) {
+                    packet_buf = ipc_ut_ipv6_mdns_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                } else {
+                    packet_buf = ipc_ut_non_ip_packet;
+                    packet_len = sizeof(ipc_ut_non_ip_packet);
+                }
+            case 1:
+                packet_buf = ipc_ut_ipv6_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ip_header_packet);
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv6_incomplete_hop_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_hop_packet);
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv6_incomplete_ah_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ah_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv6_unknown_ext_packet;
+                packet_len = sizeof(ipc_ut_ipv6_unknown_ext_packet);
+                break;
+            case 5:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv4enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv4enc_packet);
+                break;
+            case 6:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv6enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv6enc_packet);
+                break;
+            case 7:
+                if (ipv6_cnt <= 10) {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag0_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag0_packet);
+                } else {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag1_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag1_packet);
+                }
+                break;
+            case 8:
+                packet_buf = ipc_ut_ipv6_frag_packet;
+                packet_len = sizeof(ipc_ut_ipv6_frag_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_mdns_packet;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                break;
+            }
+        }
+        kal_mem_cpy(QBM_DES_GET_DATAPTR(bd), packet_buf, packet_len);
+        QBM_DES_SET_DATALEN(bd, packet_len);
+        QBM_DES_SET_DATALEN(curr_gpd, packet_len);
+
+        curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+    }
+
+
+    if (ior && head_gpd && *head_gpd) {
+        *ior = (ipc_io_request_t *)QBM_DES_GET_SW_CTRL_FIELD(*head_gpd);
+        (*ior)->next_request = NULL;
+        (*ior)->first_gpd = *head_gpd;
+        (*ior)->last_gpd = *tail_gpd;
+        (*ior)->ip_type =   (ipv4_cnt==0) ? IPC_IP_TYPE_IPV6:
+                            (ipv6_cnt==0) ? IPC_IP_TYPE_IPV4:
+                                            IPC_IP_TYPE_MIXED;
+        (*ior)->qos_priority = 0;
+        (*ior)->data_path_type = 0;
+        (*ior)->reserved = 0;
+    }
+}
+
+void ipc_ut_prepare_dl_gpd_list(
+        kal_uint32 ipv4_cnt,
+        kal_uint32 dhcpv4_idx,
+        kal_bool   dnsv4_only,
+        kal_bool   v4hdr_exist,
+        kal_uint32 ipv6_cnt,
+        kal_uint32 dhcpv6_idx,
+        kal_bool   dnsv6_only,
+        kal_bool   v6hdr_exist,
+        kal_uint32 additional_bd_cnt,
+        kal_uint32 align_offset,
+        qbm_gpd **head_gpd,
+        qbm_gpd **tail_gpd,
+        kal_uint16 *ipv4_invalid_packet_len,
+        kal_uint16 *ipv6_invalid_packet_len,
+        /* Insert one SPD into the GPD list. Note that the total packet num should be less than 30. */
+        kal_bool   spd_enable,
+        kal_bool   spd_igr_bit_enable,
+        ipc_ut_spd_position_e   spd_position) {
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx = 0;
+    qbm_gpd            *curr_gpd = NULL;
+    qbm_gpd            *bd = NULL;
+    qbm_gpd            *head_bd = NULL;
+    qbm_gpd            *tail_bd = NULL;
+    kal_uint8          *packet_buf = NULL;
+    kal_uint32          packet_len = 0;
+
+    /* SPD related */
+    qbm_spd            *spd = NULL;
+    qbm_spd_pi         *p_spd_pi = NULL;
+    qbm_spd_pie        *p_spd_pie = NULL;
+    qbm_spd_pie        *p_prev_spd_pie = NULL;
+    kal_uint8          *p_payload = NULL;
+    kal_uint32          payload_len = 0;
+    kal_uint32          total_data_len = 0;
+    kal_uint32          igr_payload_cnt = 0;
+    /* for setting spd position, which will be inserted after the last ipv4 packet. */
+    qbm_gpd            *middle_gpd = NULL;
+
+    ipc_ut_dl_head_gpd = ipc_ut_dl_tail_gpd = NULL;
+
+    if (total_cnt != qbmt_alloc_q(
+                        QBM_TYPE_NET_DL,
+                        total_cnt,
+                        (void **)(head_gpd),
+                        (void **)(tail_gpd))) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    if (spd_enable) {
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+        /* 1st packet should not be used! */
+        p_spd_pie = QBM_SPD_PI_GET_FIRST_PIE(p_spd_pi);
+        for (idx = 0; idx < QBM_SPD_MAX_PKTNUM; idx++) {
+            QBM_SPD_PIE_SET_PAYLOAD_LEN(p_spd_pie, 0);
+            QBM_SPD_PIE_SET_PAYLOAD_LEN(p_spd_pie, 0);
+            QBM_SPD_PIE_CLR_IGR(p_spd_pie);
+            QBM_SPD_PIE_CLR_EOL(p_spd_pie);
+            if (idx != (QBM_SPD_MAX_PKTNUM - 1)) {
+                p_spd_pie = QBM_SPD_PIE_NEXT(p_spd_pie);
+            }
+        }
+
+        /* Reset: point the SPD related ptrs to the second payload. */
+        p_spd_pie = QBM_SPD_PI_GET_FIRST_PIE(p_spd_pi);
+        p_prev_spd_pie = NULL;
+        p_payload = QBM_DES_GET_DATAPTR(spd);
+        payload_len = 0;
+    }
+
+
+    /* Append BD list */
+    if (additional_bd_cnt && total_cnt) {
+        qbm_gpd     *next_gpd;
+        kal_bool    end_of_gpd_list;
+        if ((total_cnt * additional_bd_cnt) != qbmt_alloc_q(
+                                                QBM_TYPE_TBD,
+                                                (total_cnt * additional_bd_cnt),
+                                                (void**)&head_bd,
+                                                (void**)&tail_bd)) {
+            UT_ASSERT(KAL_FALSE);
+            return;
+        }
+
+        next_gpd = NULL;
+        end_of_gpd_list = KAL_FALSE;
+        for (   curr_gpd = *head_gpd ;
+                curr_gpd && (end_of_gpd_list == KAL_FALSE) ;
+                curr_gpd = next_gpd) {
+            kal_uint32 additional_bd_idx;
+
+            next_gpd = QBM_DES_GET_NEXT(curr_gpd);
+            end_of_gpd_list = (curr_gpd == *tail_gpd)?KAL_TRUE:KAL_FALSE;
+
+            bd = QBM_DES_GET_DATAPTR(curr_gpd);
+
+            for (   additional_bd_idx = 0 ;
+                    additional_bd_idx < additional_bd_cnt ;
+                    additional_bd_idx ++) {
+                qbm_gpd *added_bd;
+
+                /* Remove BD from BD list */
+                UT_ASSERT(NULL != head_bd);
+                added_bd = head_bd;
+                head_bd = QBM_DES_GET_NEXT(head_bd);
+
+                /* Add BD to tail of curr_gpd BD list */
+                QBM_DES_SET_NEXT(bd, added_bd);
+                QBM_DES_CLR_EOL(bd);
+                QBM_DES_SET_NEXT(added_bd, NULL);
+                QBM_DES_SET_EOL(added_bd);
+                bd = added_bd;  /* For next BD append */
+            }
+        }
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        qbm_gpd     *next_gpd;
+        kal_bool    end_of_gpd_list;
+
+        next_gpd = NULL;
+        end_of_gpd_list = KAL_FALSE;
+        for (   curr_gpd = *head_gpd ;
+                curr_gpd && (end_of_gpd_list == KAL_FALSE) ;
+                curr_gpd = next_gpd) {
+            bd = QBM_DES_GET_DATAPTR(curr_gpd);
+
+            while (bd) {
+                QBM_DES_SET_DATAPTR(bd, ((kal_uint8*)QBM_DES_GET_DATAPTR(bd)) + (align_offset % 4));
+                qbm_cal_set_checksum((kal_uint8 *)bd);
+
+                if (QBM_DES_GET_EOL(bd)) {break;}
+                bd = QBM_DES_GET_NEXT(bd);
+            }
+        }
+    }
+
+
+    /* Set GPD to GPD list head for data configuration */
+    curr_gpd = *head_gpd;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        bd = QBM_DES_GET_DATAPTR(curr_gpd);
+
+        if (KAL_TRUE == dnsv4_only) {
+            if (KAL_TRUE == v4hdr_exist) {
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+            } else {
+                kal_uint8 * data_ptr;
+                kal_uint32 offset;
+
+                /* Shift data pointer to reserve headroom */
+                offset = IPC_HDR_V4_GET_IHL(ipc_ut_ipv4_dns_packet) + IPC_HDR_UDP_HEADER_SIZE;
+
+                data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(bd);
+                QBM_DES_SET_DATAPTR(bd, data_ptr+offset);
+
+                /* set bd checksum */
+                qbm_cal_set_checksum((kal_uint8 *)bd);
+
+                packet_buf = ipc_ut_ipv4_dns_packet + offset;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet) - offset;
+            }
+        } else {
+            if (idx == dhcpv4_idx) {
+                packet_buf = ipc_ut_ipv4_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                ipc_ut_dl_filter_expect_gpd_cnt++;
+            } else {
+                switch (idx) {
+                case 0:
+                    if (ipv4_cnt > 4) {
+                        if ((ipv4_cnt%2) == 0) {
+                            packet_buf = ipc_ut_ipv4_dhcp_packet;
+                            packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                            ipc_ut_dl_filter_expect_gpd_cnt++;
+                        } else {
+                    packet_buf = ipc_ut_non_ip_packet;
+                    packet_len = sizeof(ipc_ut_non_ip_packet);
+                        }
+                    }
+                    else {
+                        packet_buf = ipc_ut_non_ip_packet;
+                        packet_len = sizeof(ipc_ut_non_ip_packet);
+                    }
+                    break;
+                case 1:
+                    packet_buf = ipc_ut_ipv4_incomplete_ip_header_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_incomplete_ip_header_packet);
+                    break;
+                case 2:
+                    packet_buf = ipc_ut_ipv4_incomplete_udp_header_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_incomplete_udp_header_packet);
+                    break;
+                case 3:
+                    packet_buf = ipc_ut_ipv4_frag0_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_frag0_packet);
+                    break;
+                case 4:
+                    packet_buf = ipc_ut_ipv4_frag1_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_frag1_packet);
+                    break;
+                default:
+                    if ((idx%3) == 0) {
+                        packet_buf = ipc_ut_ipv4_dns_packet;
+                        packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                    } else {
+                        packet_buf = ipc_ut_ipv4_dhcp_packet;
+                        packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                        ipc_ut_dl_filter_expect_gpd_cnt++;
+                    }
+                    break;
+                }
+            }
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        // invalid len packet
+        if (ipv4_invalid_packet_len) {
+            if (ipv4_invalid_packet_len[idx] > packet_len) {
+                kal_mem_cpy(ipc_ut_invalid_len_ip_packet, packet_buf, packet_len);
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv4_invalid_packet_len[idx]>IPC_INVALID_MAX_PKT_LEN)?IPC_INVALID_MAX_PKT_LEN:ipv4_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (QBM_DES_GET_EOL(bd)) {   /* Latest BD : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else {   /* Non latest BD : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                }
+
+                if (cont_loop_cnt == 0) {
+                    kal_mem_cpy(QBM_DES_GET_DATAPTR(bd), packet_buf + copied_len, current_copy_len);
+                } else {   /* For non-first BD, no buffer is allocated and we need to set its buffer to static template */
+                    QBM_DES_SET_DATAPTR(bd, packet_buf + copied_len);
+                }
+                QBM_DES_SET_DATALEN(bd, current_copy_len);
+                copied_len += current_copy_len;
+
+                /* Get next BD in list */
+                bd = QBM_DES_GET_NEXT(bd);
+
+                cont_loop_cnt ++;
+            }
+
+            QBM_DES_SET_DATALEN(curr_gpd, packet_len);
+        }
+
+        if (spd_enable) {
+            kal_mem_cpy(p_payload, packet_buf, packet_len);
+            payload_len = packet_len;
+            UT_ASSERT(total_data_len < IPC_UT_SPD_RING_BUFFER_SIZE);
+
+            QBM_SPD_PIE_SET_PAYLOAD_LEN(p_spd_pie, payload_len);
+
+            if ( (spd_igr_bit_enable) && (1 == ipc_ut_spd_packet_igr_s[idx]) ) {
+                QBM_SPD_PIE_SET_IGR(p_spd_pie);
+                igr_payload_cnt++;
+            } else {
+                total_data_len += payload_len;
+                p_prev_spd_pie = p_spd_pie;
+            }
+            if (idx == (ipv4_cnt - 1)) {
+                /* The last packet of ipv4 */
+                middle_gpd = curr_gpd;
+            }
+            p_payload = QBM_SPD_PAYLOAD_NEXT(p_payload, payload_len);
+            p_spd_pie = QBM_SPD_PIE_NEXT(p_spd_pie);
+        }
+
+        curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+    }
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        bd = QBM_DES_GET_DATAPTR(curr_gpd);
+
+        if (KAL_TRUE == dnsv6_only) {
+            if (KAL_TRUE == v6hdr_exist) {
+                packet_buf = ipc_ut_ipv6_mdns_packet;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+            } else {
+                kal_uint8 * data_ptr;
+                kal_uint32 offset;
+
+                /* Shift data pointer to reserve headroom */
+                offset = IPC_HDR_V6_HEADER_SIZE + IPC_HDR_UDP_HEADER_SIZE;
+
+                data_ptr = (kal_uint8*)QBM_DES_GET_DATAPTR(bd);
+                QBM_DES_SET_DATAPTR(bd, data_ptr+offset);
+
+                /* set bd checksum */
+                qbm_cal_set_checksum((kal_uint8 *)bd);
+
+                packet_buf = ipc_ut_ipv6_mdns_packet + offset;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet) - offset;
+            }
+        } else {
+            if (idx == dhcpv6_idx) {
+                switch (idx) {
+                case 0:
+                    packet_buf = ipc_ut_ipv6_ext0_dhcp_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_packet);
+                    break;
+                case 1:
+                    packet_buf = ipc_ut_ipv6_ext1_dhcp_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ext1_dhcp_packet);
+                    break;
+                default:
+                    packet_buf = ipc_ut_ipv6_dhcp_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_dhcp_packet);
+                }
+            } else {
+                switch (idx) {
+                case 0:
+                    packet_buf = ipc_ut_non_ip_packet;
+                    packet_len = sizeof(ipc_ut_non_ip_packet);
+                    break;
+                case 1:
+                    packet_buf = ipc_ut_ipv6_incomplete_ip_header_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_ip_header_packet);
+                    break;
+                case 2:
+                    packet_buf = ipc_ut_ipv6_incomplete_hop_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_hop_packet);
+                    break;
+                case 3:
+                    packet_buf = ipc_ut_ipv6_incomplete_ah_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_ah_packet);
+                    break;
+                case 4:
+                    packet_buf = ipc_ut_ipv6_unknown_ext_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_unknown_ext_packet);
+                    break;
+                case 5:
+                    packet_buf = ipc_ut_ipv6_incomplete_ipv4enc_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv4enc_packet);
+                    break;
+                case 6:
+                    packet_buf = ipc_ut_ipv6_incomplete_ipv6enc_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv6enc_packet);
+                    break;
+                case 7:
+                    if (ipv6_cnt <= 10) {
+                        packet_buf = ipc_ut_ipv6_ipv4enc_frag0_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag0_packet);
+                    } else {
+                        packet_buf = ipc_ut_ipv6_ipv4enc_frag1_packet;
+                        packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag1_packet);
+                    }
+                    break;
+                case 8:
+                    packet_buf = ipc_ut_ipv6_frag_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_frag_packet);
+                    break;
+                default:
+                    packet_buf = ipc_ut_ipv6_mdns_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                    break;
+                }
+            }
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        // invalid len packet
+        if (ipv6_invalid_packet_len) {
+            if (ipv6_invalid_packet_len[idx] > packet_len) {
+                kal_mem_cpy(ipc_ut_invalid_len_ip_packet, packet_buf, packet_len);
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv6_invalid_packet_len[idx]>IPC_INVALID_MAX_PKT_LEN)?IPC_INVALID_MAX_PKT_LEN:ipv6_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (QBM_DES_GET_EOL(bd)) {   /* Latest BD : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else {   /* Non latest BD : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                }
+
+                if (cont_loop_cnt == 0) {
+                    kal_mem_cpy(QBM_DES_GET_DATAPTR(bd), packet_buf + copied_len, current_copy_len);
+                } else {   /* For non-first BD, no buffer is allocated and we need to set its buffer to static template */
+                    QBM_DES_SET_DATAPTR(bd, packet_buf + copied_len);
+                }
+                QBM_DES_SET_DATALEN(bd, current_copy_len);
+                copied_len += current_copy_len;
+
+                /* Get next BD in list */
+                bd = QBM_DES_GET_NEXT(bd);
+
+                cont_loop_cnt ++;
+            }
+
+            QBM_DES_SET_DATALEN(curr_gpd, packet_len);
+        }
+
+        if (spd_enable) {
+            kal_mem_cpy(p_payload, packet_buf, packet_len);
+            payload_len = packet_len;
+            UT_ASSERT(total_data_len < IPC_UT_SPD_RING_BUFFER_SIZE);
+
+            QBM_SPD_PIE_SET_PAYLOAD_LEN(p_spd_pie, payload_len);
+
+            if ((spd_igr_bit_enable) && (1 == ipc_ut_spd_packet_igr_s[idx + ipv4_cnt])) {
+                QBM_SPD_PIE_SET_IGR(p_spd_pie);
+                igr_payload_cnt++;
+            } else {
+                total_data_len += payload_len;
+                p_prev_spd_pie = p_spd_pie;
+            }
+            if (idx != (ipv6_cnt - 1)) {
+                p_payload = QBM_SPD_PAYLOAD_NEXT(p_payload, payload_len);
+                p_spd_pie = QBM_SPD_PIE_NEXT(p_spd_pie);
+            }
+        }
+
+        curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+    }
+
+    if (spd_enable) {
+        if (igr_payload_cnt == total_cnt) {
+            /* All SPD payloads has been ignored. */
+            qbmt_dest_q(spd, spd);
+        } else {
+            if (QBM_SPD_PIE_GET_IGR(p_spd_pie)) {
+                if (p_prev_spd_pie) {
+                    QBM_SPD_PIE_SET_EOL(p_prev_spd_pie);
+                    QBM_SPD_PI_SET_PKTNUM(p_spd_pi, total_cnt - 1);
+                } else {
+                    UT_ASSERT(KAL_FALSE);
+                }
+            } else {
+                QBM_SPD_PIE_SET_EOL(p_spd_pie);
+                QBM_SPD_PI_SET_PKTNUM(p_spd_pi, total_cnt);
+            }
+            QBM_DES_SET_DATALEN(spd, total_data_len);
+
+            switch (spd_position) {
+                case IPC_UT_SPD_AT_THE_HEAD_OF_LIST:
+                    QBM_DES_SET_NEXT(spd, *head_gpd);
+                    *head_gpd = (qbm_gpd *)spd;
+                    break;
+                case IPC_UT_SPD_AT_THE_END_OF_LIST:
+                    QBM_DES_SET_NEXT(*tail_gpd, spd);
+                    *tail_gpd = (qbm_gpd *)spd;
+                    break;
+                case IPC_UT_SPD_IN_THE_MIDDLE_OF_LIST:
+                    if (NULL == middle_gpd) {
+                        middle_gpd = *head_gpd;
+                    }
+                    QBM_DES_SET_NEXT(spd, QBM_DES_GET_NEXT(middle_gpd));
+                    QBM_DES_SET_NEXT(middle_gpd, spd);
+                    if (*tail_gpd == middle_gpd) {
+                        *tail_gpd = (qbm_gpd *)spd;
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    if (head_gpd && *head_gpd) {
+        ((upcm_dlvr_dl_info_t *)QBM_DES_GET_SW_CTRL_FIELD(*head_gpd))->ebi = IPC_UT_DL_EBI;
+    }
+}
+
+void ipc_ut_prepare_garbage_filter_dl_gpd_list(
+        kal_uint32 ipv4_cnt,
+        kal_uint32 synv4_idx,
+        kal_uint32 ipv6_cnt,
+        kal_uint32 synv6_idx,
+        qbm_gpd **head_gpd,
+        qbm_gpd **tail_gpd) {
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx;
+    qbm_gpd            *curr_gpd;
+    qbm_gpd            *bd;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+
+    ipc_ut_dl_head_gpd = ipc_ut_dl_tail_gpd = NULL;
+
+    if (total_cnt != qbmt_alloc_q(
+                        QBM_TYPE_NET_DL,
+                        total_cnt,
+                        (void **)(head_gpd),
+                        (void **)(tail_gpd))) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    if (head_gpd && *head_gpd) {
+        ((upcm_dlvr_dl_info_t *)QBM_DES_GET_SW_CTRL_FIELD(*head_gpd))->ebi = IPC_UT_DL_EBI;
+    }
+
+    /* Set GPD to GPD list head for data configuration */
+    curr_gpd = *head_gpd;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        bd = QBM_DES_GET_DATAPTR(curr_gpd);
+
+        if (idx == synv4_idx) {
+            packet_buf = ipc_ut_ipv4_tcp_syn_packet;
+            packet_len = sizeof(ipc_ut_ipv4_tcp_syn_packet);
+        } else {
+            switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv4_tcp_ack_packet;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_ack_packet);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_tcp_syn_packet_2;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_syn_packet_2);
+                ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                break;
+            default:
+                packet_buf = ipc_ut_ipv4_tcp_syn_packet_2;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_syn_packet_2);
+                ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt++;
+                break;
+            }
+        }
+
+        {
+            kal_mem_cpy(QBM_DES_GET_DATAPTR(bd), packet_buf, packet_len);
+            QBM_DES_SET_DATALEN(bd, packet_len);
+            QBM_DES_SET_DATALEN(curr_gpd, packet_len);
+        }
+
+        curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+    }
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        bd = QBM_DES_GET_DATAPTR(curr_gpd);
+
+        if (idx == synv6_idx) {
+            packet_buf = ipc_ut_ipv6_tcp_syn_packet;
+            packet_len = sizeof(ipc_ut_ipv6_tcp_syn_packet);
+        } else {
+            switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv6_tcp_ack_packet;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_ack_packet);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_tcp_syn_packet_2;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_syn_packet_2);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_tcp_syn_packet_2;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_syn_packet_2);
+                break;
+            }
+        }
+
+        {
+            kal_mem_cpy(QBM_DES_GET_DATAPTR(bd), packet_buf, packet_len);
+            QBM_DES_SET_DATALEN(bd, packet_len);
+            QBM_DES_SET_DATALEN(curr_gpd, packet_len);
+        }
+
+        curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+    }
+}
+
+
+void ipc_fragment_ut_dl_filter_callback(void *context,
+                               kal_int32 filter_id,
+                               qbm_gpd *head_gpd,
+                               qbm_gpd *tail_gpd,
+                               kal_uint32 length) {
+    qbmt_dest_q(head_gpd, tail_gpd);
+}
+
+
+void ipc_ut_prepare_fragments_and_send(kal_uint32 pdn_id, kal_uint8 proto_idx) {
+    upcm_did *did_p = NULL;
+    upcm_did_si *sit_p = NULL;
+    ipc_filter_rules_t rules = {0};
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+    kal_uint32 filter_id = IPC_INVALID_FILTER_ID;
+    kal_uint32 buff_count = 0, remain_count = 0;
+
+    buff_count = upcm_did_get_buff_remain_num() + 
+        qbm_get_buff_remain_num(QBM_TYPE_TGPD) + qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+    rules.priority = 3;
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_PDN_ID | IPC_FILTER_BY_SPI;
+    rules.features = IPC_FILTER_FEATURE_FRAG;
+    rules.pdn_id = pdn_id;
+    rules.protocol = IPC_HDR_PROT_ESP;
+    rules.spi = 0x481fde70;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_fragment_ut_dl_filter_callback;
+    ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+    filter_id = ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt);
+
+    did_p = upcm_did_alloc_one();
+    sit_p = UPCM_DID_GET_SIT_PTR(did_p);
+    UPCM_DID_SET_NEXT(did_p, NULL);
+    
+    kal_mem_set(sit_p, 0, sizeof(upcm_did_si));
+    UPCM_DID_SI_SET_LEN(sit_p, sizeof(pkt2508_1));
+    UPCM_DID_SI_SET_DATAPTR(sit_p, ((void*)pkt2508_1));
+    UPCM_DID_SI_SET_EOL(sit_p);
+    sit_p++;
+    kal_mem_set(sit_p, 0, sizeof(upcm_did_si));
+    UPCM_DID_SI_SET_LEN(sit_p, sizeof(pkt2509_1));
+    UPCM_DID_SI_SET_DATAPTR(sit_p, ((void*)pkt2509_1));
+    UPCM_DID_SI_SET_EOL(sit_p);
+    sit_p++;
+    kal_mem_set(sit_p, 0, sizeof(upcm_did_si));
+    UPCM_DID_SI_SET_LEN(sit_p, sizeof(pkt2510_1));
+    UPCM_DID_SI_SET_DATAPTR(sit_p, ((void*)pkt2510_1));
+    UPCM_DID_SI_SET_EOL(sit_p);
+
+    UPCM_DID_SET_PKT_NUM(did_p, 3);
+    UPCM_DID_SET_SEG_NUM(did_p, 3);
+
+    ipc_on_did_downlink_multiple_ps(pdn_id, did_p, did_p, proto_idx);
+    ipc_dereg_filter(filter_id);
+
+    remain_count = upcm_did_get_buff_remain_num() + 
+        qbm_get_buff_remain_num(QBM_TYPE_TGPD) + qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+    ASSERT(remain_count == buff_count);
+}
+
+
+void ipc_ut_free_gpd_list(qbm_gpd *head_gpd, qbm_gpd *tail_gpd) {
+    if (head_gpd) {
+        qbmt_dest_q(head_gpd, tail_gpd);
+    }
+    if (ipc_ut_ul_tail_gpd) {
+        qbmt_dest_q(ipc_ut_ul_head_gpd, ipc_ut_ul_tail_gpd);
+    }
+    ipc_ut_ul_head_gpd = ipc_ut_ul_tail_gpd = NULL;
+
+    if (ipc_ut_dl_tail_gpd) {
+        qbmt_dest_q(ipc_ut_dl_head_gpd, ipc_ut_dl_tail_gpd);
+    }
+    ipc_ut_dl_head_gpd = ipc_ut_dl_tail_gpd = NULL;
+}
+
+kal_uint32 ipc_ut_gpd_list_count(qbm_gpd *head_gpd, qbm_gpd *tail_gpd) {
+    qbm_gpd    *curr_gpd;
+    kal_uint32  cnt = 0;
+    kal_bool    eol = (NULL == head_gpd || NULL == tail_gpd);
+
+    for (curr_gpd = head_gpd; !eol; curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd)) {
+        eol = (curr_gpd == tail_gpd);
+        cnt++;
+    }
+
+    return cnt;
+}
+
+kal_uint32 ipc_ut_non_igr_meta_count(kal_uint32 start_idx, kal_uint32 end_idx, LHIF_QUEUE_TYPE q_type) {
+    kal_uint32  curr_idx = start_idx;
+    kal_uint32  cnt = 0;
+    g_ipc_ut_igr_meta_cnt = 0;
+    g_ipc_ut_received_ignore_ea_cnt = 0;
+
+    UT_ASSERT(LHIF_HWQ_AP_UL_Q0 == q_type);
+
+    while (curr_idx != end_idx) {
+        if (!ipc_ut_meta_tbl_s[curr_idx].ignore) {
+            cnt ++;
+        }
+
+        if (ipc_ut_meta_tbl_s[curr_idx].ignore) {
+            g_ipc_ut_igr_meta_cnt++;
+            if (ipc_ut_meta_tbl_s[curr_idx].ea) {
+                g_ipc_ut_received_ignore_ea_cnt++;
+            }
+        }
+
+        curr_idx ++;
+        if (curr_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_idx = 0;
+        }
+    }
+
+    return cnt;
+}
+
+kal_uint32 ipc_ut_spd_payload_count(qbm_gpd *head_gpd, qbm_gpd *tail_gpd) {
+    qbm_gpd    *curr_gpd;
+    kal_uint32  cnt = 0;
+    kal_bool    eol = (NULL == head_gpd || NULL == tail_gpd);
+    qbm_spd    *spd;
+    qbm_spd_pi *p_spd_pi;
+    qbm_spd_pie *p_spd_pie;
+    kal_uint8   i;
+    kal_uint16  packet_num = 0;
+
+    for (curr_gpd = head_gpd; !eol; curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd)) {
+        eol = (curr_gpd == tail_gpd);
+        if (0 != QBM_DES_GET_PDT(curr_gpd)) {
+            /* It's SPD! */
+            spd = QBM_GET_SPD_PTR(curr_gpd);
+            p_spd_pi = QBM_SPD_GET_PI(spd);
+            p_spd_pie = QBM_SPD_PI_GET_FIRST_PIE(p_spd_pi);
+            packet_num = QBM_SPD_PI_GET_PKTNUM(p_spd_pi);
+            for (i = 0; i < packet_num; i++) {
+                if ( QBM_SPD_PIE_GET_IGR(p_spd_pie) && QBM_SPD_PIE_GET_EOL(p_spd_pie) ) {
+                    UT_ASSERT(KAL_FALSE);
+                }
+                if (!QBM_SPD_PIE_GET_IGR(p_spd_pie)) {
+                    cnt++;
+                }
+                if (QBM_SPD_PIE_GET_EOL(p_spd_pie)) {
+                    /* end of packet list */
+                    break;
+                } else {
+                    p_spd_pie = QBM_SPD_PIE_NEXT(p_spd_pie);
+                }
+            }
+            if (!QBM_SPD_PIE_GET_EOL(p_spd_pie)) {
+                UT_ASSERT(KAL_FALSE);
+            }
+        }
+    }
+
+    return cnt;
+}
+
+void ipc_ut_install_ul_filters(kal_bool callback_with_info,
+                               kal_bool with_callback,
+                               kal_uint32 ipv4_filter_cnt,
+                               kal_uint32 ipv6_filter_cnt,
+                               kal_bool with_wildcard,
+                               kal_bool with_bwm,
+                               kal_uint8 matched_filter_idx_v4,
+                               kal_uint8 matched_filter_idx_v6,
+                               kal_uint32 good_netif_id)
+{
+    kal_uint32 idx = 0;
+    ipc_ut_filter_info_t *info = NULL;
+    ipc_filter_rules_t *rules = NULL;
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    if (ipv4_filter_cnt > (IPC_MAX_FILTER_CNT >> 1)) {
+        ipv4_filter_cnt = (IPC_MAX_FILTER_CNT >> 1);
+    }
+    if (ipv6_filter_cnt > (IPC_MAX_FILTER_CNT >> 1)) {
+        ipv6_filter_cnt = (IPC_MAX_FILTER_CNT >> 1);
+    }
+
+    for (idx = 0; idx < ipv4_filter_cnt; idx++) {
+        info = &ipc_ut_info_set[idx];
+
+        rules = &info->rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        if (matched_filter_idx_v4 == idx) {
+            /*
+             * IPv4 DHCP.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_DST_PORT |
+                                   IPC_FILTER_BY_SRC_IPV4 |
+                                   IPC_FILTER_BY_DST_IPV4 |
+                                   IPC_FILTER_BY_NETIF_ID);
+            rules->netif_id = good_netif_id;
+            rules->ip_type = IPC_IP_TYPE_IPV4;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 68;
+            rules->dst_port = 67;
+            IPC_CP_V4_ADDR(rules->src_ipv4.addr8, ipc_ut_ipv4_dhcp_ul_packet + 12);
+            IPC_CP_V4_ADDR(rules->dst_ipv4.addr8, ipc_ut_ipv4_dhcp_ul_packet + 16);
+        } else if (0 == idx) {
+            /*
+             * IPv4 wrong Netif.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_NETIF_ID);
+            rules->netif_id = IPC_UT_BAD_NETIF_ID;
+            rules->ip_type = IPC_IP_TYPE_IPV4;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 7890;
+        } else {
+            /*
+             * IPv4 non-DHCP.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT);
+            rules->ip_type = IPC_IP_TYPE_IPV4;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 7890;
+        }
+
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+
+        if (with_callback) {
+            if (callback_with_info == 0) {
+                ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+                info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+            } else {
+                ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+                info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+            }
+        } else {
+            if (callback_with_info == 0) {
+                ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM;
+                info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+            } else {
+                ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO;
+                info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+            }
+        }
+
+        UT_ASSERT(idx == info->filter_id);
+    }
+
+    for (idx = 0; idx < ipv6_filter_cnt; idx++) {
+        info = &ipc_ut_info_set[ipv4_filter_cnt + idx];
+
+        rules = &info->rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        if (matched_filter_idx_v6 == idx) {
+            /*
+             * IPv6 DHCP.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_DST_PORT |
+                                   IPC_FILTER_BY_SRC_IPV6 |
+                                   IPC_FILTER_BY_DST_IPV6 |
+                                   IPC_FILTER_BY_NETIF_ID);
+            rules->netif_id = good_netif_id;
+            rules->ip_type = IPC_IP_TYPE_IPV6;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 546;
+            rules->dst_port = 547;
+            IPC_CP_V6_ADDR(rules->src_ipv6.addr8, ipc_ut_ipv6_dhcp_ul_packet + 8);
+            IPC_CP_V6_ADDR(rules->dst_ipv6.addr8, ipc_ut_ipv6_dhcp_ul_packet + 24);
+        } else if (0 == idx) {
+            /*
+             * IPv6 wrong Netif.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_NETIF_ID);
+            rules->netif_id = IPC_UT_BAD_NETIF_ID;
+            rules->ip_type = IPC_IP_TYPE_IPV6;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->dst_port = 9876;
+        } else {
+            /*
+             * IPv6 non-DHCP.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_DST_PORT);
+            rules->ip_type = IPC_IP_TYPE_IPV6;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->dst_port = 9876;
+        }
+
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        UT_ASSERT(ipv4_filter_cnt + idx == info->filter_id);
+    }
+
+    if (with_wildcard) {
+        info = &ipc_ut_info_set[ipv4_filter_cnt + ipv6_filter_cnt];
+
+        rules = &info->rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+
+        rules->features = IPC_FILTER_FEATURE_WC;
+        rules->priority = IPC_UT_MID_PRIORITY;
+
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        UT_ASSERT(ipv4_filter_cnt + ipv6_filter_cnt == info->filter_id);
+    }
+
+    if (with_bwm) {
+        /*
+         * IPv4 DHCP Bypass When Matched filter.
+         */
+        info = &ipc_ut_info_set[
+                ipv4_filter_cnt + ipv6_filter_cnt + (with_wildcard) ? 1 : 0];
+
+        rules = &info->rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+
+        rules->features = IPC_FILTER_FEATURE_BWM;
+        rules->priority = IPC_UT_HIGH_PRIORITY;
+        rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                               IPC_FILTER_BY_SRC_PORT |
+                               IPC_FILTER_BY_DST_PORT |
+                               IPC_FILTER_BY_SRC_IPV4 |
+                               IPC_FILTER_BY_DST_IPV4 |
+                               IPC_FILTER_BY_NETIF_ID);
+        rules->netif_id = good_netif_id;
+        rules->ip_type = IPC_IP_TYPE_IPV4;
+        rules->protocol = IPC_HDR_PROT_UDP;
+        rules->src_port = 68;
+        rules->dst_port = 67;
+        IPC_CP_V4_ADDR(rules->src_ipv4.addr8, ipc_ut_ipv4_dhcp_ul_packet + 12);
+        IPC_CP_V4_ADDR(rules->dst_ipv4.addr8, ipc_ut_ipv4_dhcp_ul_packet + 16);
+
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        UT_ASSERT(ipv4_filter_cnt + ipv6_filter_cnt + (with_wildcard)?1:0 == info->filter_id);
+
+        /*
+         * IPv6 DHCP Bypass When Matched filter.
+         */
+        info = &ipc_ut_info_set[
+                ipv4_filter_cnt + ipv6_filter_cnt + 1 + (with_wildcard) ? 1 : 0];
+
+        rules = &info->rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+
+        rules->features = IPC_FILTER_FEATURE_BWM;
+        rules->priority = IPC_UT_HIGH_PRIORITY;
+        rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                               IPC_FILTER_BY_SRC_PORT |
+                               IPC_FILTER_BY_DST_PORT |
+                               IPC_FILTER_BY_SRC_IPV6 |
+                               IPC_FILTER_BY_DST_IPV6 |
+                               IPC_FILTER_BY_NETIF_ID);
+        rules->netif_id = good_netif_id;
+        rules->ip_type = IPC_IP_TYPE_IPV6;
+        rules->protocol = IPC_HDR_PROT_UDP;
+        rules->src_port = 546;
+        rules->dst_port = 547;
+        IPC_CP_V6_ADDR(rules->src_ipv6.addr8, ipc_ut_ipv6_dhcp_ul_packet + 8);
+        IPC_CP_V6_ADDR(rules->dst_ipv6.addr8, ipc_ut_ipv6_dhcp_ul_packet + 24);
+
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+
+        if (callback_with_info == 0) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        UT_ASSERT(ipv4_filter_cnt + ipv6_filter_cnt + 1 + (with_wildcard)?1:0 == info->filter_id);
+    }
+}
+
+void ipc_ut_uninstall_ul_filters(kal_uint32 ipv4_filter_cnt,
+                                 kal_uint32 ipv6_filter_cnt,
+                                 kal_bool with_wildcard,
+                                 kal_bool with_bwm)
+{
+    kal_uint32 idx = 0;
+    kal_uint32 filter_cnt = ipv4_filter_cnt + ipv6_filter_cnt + (
+            (with_wildcard) ? 1 : 0) + ((with_bwm) ? 2 : 0);
+
+    for (idx = 0; idx < filter_cnt; idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        ipc_dereg_filter(idx);
+
+        UT_ASSERT(IPC_UT_NO_ERROR == ipc_ut_get_error());
+    }
+}
+
+void ipc_ut_install_netif_filter(kal_uint32 netif_id) {
+    ipc_ut_filter_info_t *info = NULL;
+    ipc_filter_rules_t *rules = NULL;
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    info = &ipc_ut_info_set[0];
+    rules = &info->rules;
+    kal_mem_set(rules, 0, sizeof(*rules));
+    rules->priority = IPC_UT_LOW_PRIORITY;
+    rules->valid_fields = IPC_FILTER_BY_NETIF_ID | IPC_FILTER_BY_PROTOCOL;
+    rules->netif_id = netif_id;
+    rules->protocol = IPC_HDR_PROT_UDP;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_dl_filter_callback;
+    ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_dl_filter_with_info_callback;
+    ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+    ntfy_ctxt.p_ntfy_args = (void *)info;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+    info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+}
+
+void ipc_ut_uninstall_netif_filter(void) {
+    ipc_ut_filter_info_t *info = NULL;
+    info = &ipc_ut_info_set[0];
+    ipc_deregister_dl_filter(info->filter_id);
+}
+
+void ipc_ut_install_dl_filters(kal_bool callback_with_info,
+                               kal_bool with_callback,
+                               kal_uint32 ipv4_filter_cnt,
+                               kal_uint32 ipv6_filter_cnt,
+                               kal_uint8 matched_filter_idx_v4,
+                               kal_uint8 matched_filter_idx_v6,
+                               kal_uint32 netif_id)
+{
+    kal_uint32 idx = 0;
+    ipc_ut_filter_info_t *info = NULL;
+    ipc_filter_rules_t *rules = NULL;
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    if (ipv4_filter_cnt > (IPC_MAX_FILTER_CNT >> 1)) {
+        ipv4_filter_cnt = (IPC_MAX_FILTER_CNT >> 1);
+    }
+    if (ipv6_filter_cnt > (IPC_MAX_FILTER_CNT >> 1)) {
+        ipv6_filter_cnt = (IPC_MAX_FILTER_CNT >> 1);
+    }
+
+    for (idx = 0; idx < ipv4_filter_cnt; idx++) {
+        info = &ipc_ut_info_set[idx];
+
+        rules = &info->rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        if (matched_filter_idx_v4 == idx) {
+            /*
+             * IPv4 DHCP.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_DST_PORT |
+                                   IPC_FILTER_BY_SRC_IPV4 |
+                                   IPC_FILTER_BY_DST_IPV4 |
+                                   IPC_FILTER_BY_PDN_ID |
+                                   IPC_FILTER_BY_EBI |
+                                   IPC_FILTER_BY_NETIF_ID);
+
+            rules->netif_id = netif_id;
+            rules->pdn_id = IPC_UT_PDN_ID;
+            rules->ebi = IPC_UT_DL_EBI;
+            rules->ip_type = IPC_IP_TYPE_IPV4;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 67;
+            rules->dst_port = 68;
+            IPC_CP_V4_ADDR(rules->src_ipv4.addr8, ipc_ut_ipv4_dhcp_packet + 12);
+            IPC_CP_V4_ADDR(rules->dst_ipv4.addr8, ipc_ut_ipv4_dhcp_packet + 16);
+        } else if (0 == idx) {
+            /*
+             * IPv4 wrong Netif.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_NETIF_ID |
+                                   IPC_FILTER_BY_PDN_ID);
+            rules->netif_id = IPC_UT_BAD_NETIF_ID;
+            rules->ip_type = IPC_IP_TYPE_IPV4;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 7890;
+            rules->pdn_id = IPC_UT_PDN_ID;
+        } else {
+            /*
+             * IPv4 non-DHCP.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_PDN_ID);
+            rules->ip_type = IPC_IP_TYPE_IPV4;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 7890;
+            rules->pdn_id = IPC_UT_PDN_ID;
+        }
+
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_dl_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_dl_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+        ntfy_ctxt.p_ntfy_args = (void *)info;
+
+        if (with_callback) {
+            if (callback_with_info) {
+                ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+                info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+            } else {
+                ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+                info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+            }
+        } else {
+            if (callback_with_info) {
+                ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO;
+                info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+            } else {
+                ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM;
+                info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+            }
+        }
+        UT_ASSERT(idx == info->filter_id);
+    }
+
+    for (idx = 0; idx < ipv6_filter_cnt; idx++) {
+        info = &ipc_ut_info_set[ipv4_filter_cnt + idx];
+
+        rules = &info->rules;
+        kal_mem_set(rules, 0, sizeof(*rules));
+        if (matched_filter_idx_v6 == idx) {
+            /*
+             * IPv6 DHCP.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_DST_PORT |
+                                   IPC_FILTER_BY_SRC_IPV6 |
+                                   IPC_FILTER_BY_DST_IPV6 |
+                                   IPC_FILTER_BY_PDN_ID |
+                                   IPC_FILTER_BY_EBI |
+                                   IPC_FILTER_BY_NETIF_ID);
+            rules->netif_id = netif_id;
+            rules->pdn_id = IPC_UT_PDN_ID;
+            rules->ebi = IPC_UT_DL_EBI;
+            rules->ip_type = IPC_IP_TYPE_IPV6;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->src_port = 546;
+            rules->dst_port = 547;
+            IPC_CP_V6_ADDR(rules->src_ipv6.addr8, ipc_ut_ipv6_dhcp_packet + 8);
+            IPC_CP_V6_ADDR(rules->dst_ipv6.addr8, ipc_ut_ipv6_dhcp_packet + 24);
+        } else if (0 == idx) {
+            /*
+             * IPv6 wrong Netif.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_DST_PORT |
+                                   IPC_FILTER_BY_NETIF_ID |
+                                   IPC_FILTER_BY_PDN_ID);
+            rules->netif_id = IPC_UT_BAD_NETIF_ID;
+            rules->ip_type = IPC_IP_TYPE_IPV6;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->dst_port = 9876;
+            rules->pdn_id = IPC_UT_PDN_ID;
+        } else {
+            /*
+             * IPv6 non-DHCP.
+             */
+            rules->priority = IPC_UT_LOW_PRIORITY;
+            rules->valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_DST_PORT |
+                                   IPC_FILTER_BY_PDN_ID);
+            rules->ip_type = IPC_IP_TYPE_IPV6;
+            rules->protocol = IPC_HDR_PROT_UDP;
+            rules->dst_port = 9876;
+            rules->pdn_id = IPC_UT_PDN_ID;
+        }
+
+        ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_dl_filter_callback;
+        ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_dl_filter_with_info_callback;
+        ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+        ntfy_ctxt.p_ntfy_args = (void *)info;
+
+        if (callback_with_info) {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+            info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        } else {
+            ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+            info->filter_id = ipc_reg_filter(DL_DIRECT, rules, &ntfy_ctxt);
+        }
+
+        UT_ASSERT(ipv4_filter_cnt + idx == info->filter_id);
+    }
+}
+
+void ipc_ut_uninstall_dl_filters(kal_uint32 ipv4_filter_cnt, kal_uint32 ipv6_filter_cnt) {
+    kal_uint32  idx;
+    kal_uint32  filter_cnt = ipv4_filter_cnt + ipv6_filter_cnt;
+
+    for (idx = 0; idx < filter_cnt; idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        ipc_deregister_dl_filter(idx);
+
+        UT_ASSERT(IPC_UT_NO_ERROR == ipc_ut_get_error());
+    }
+}
+
+void ipc_ut_ntfy_callback(ipc_ntfy_param_t *param) {
+    kal_int32 ntfy_param_idx;
+    kal_int32 ntfy_info_idx;
+
+    /* Check for redundant parameter */
+    for ( ntfy_param_idx = 0 ; ntfy_param_idx < ipc_ut_ntfy_param.count ; ntfy_param_idx ++ ) {
+        if (0 == kal_mem_cmp(&(ipc_ut_ntfy_param.params[ntfy_param_idx]), param, sizeof(ipc_ntfy_param_t))) {   /* Duplicated entry found : impossible */
+            UT_ASSERT(KAL_FALSE);
+            return;
+        }
+    }
+
+    /* Validate the callback parameter */
+    for ( ntfy_info_idx = 0 ; ntfy_info_idx < IPC_MAX_NTFY_CNT ; ntfy_info_idx ++ ) {
+        if (    (KAL_TRUE == ipc_ut_ntfy_info.ntfy_valid[ntfy_info_idx]) &&
+                (param->context == (void*)(ipc_ut_ntfy_info.ntfy_context[ntfy_info_idx])) &&
+                (param->ntfy_id == ipc_ut_ntfy_info.ntfy_id[ntfy_info_idx]) ) {   /* Record the notification */
+            UT_ASSERT(ipc_ut_ntfy_param.count < IPC_UT_NTFY_PARAM_MAX_COUNT);
+            kal_mem_cpy(&(ipc_ut_ntfy_param.params[ipc_ut_ntfy_param.count]), param, sizeof(ipc_ntfy_param_t));
+            ipc_ut_ntfy_param.count ++;
+
+            return;
+        }
+    }
+
+    /* No entry is found : fail case */
+    UT_ASSERT(KAL_FALSE);
+}
+
+void ipc_ut_ntfy_reset_param(void) {
+    kal_mem_set(&ipc_ut_ntfy_param, 0, sizeof(ipc_ut_ntfy_param));
+}
+
+void ipc_ut_ntfy_reset_info(void) {
+    kal_mem_set(&ipc_ut_ntfy_info, 0, sizeof(ipc_ut_ntfy_info));
+}
+
+kal_bool ipc_ut_ntfy_registration(kal_int32 register_cnt) {
+    kal_int32 idx;
+
+    for ( idx = 0 ; idx < register_cnt ; idx ++ ) {
+        kal_int32 ntfy_id;
+        kal_int32 ntfy_info_idx;
+
+        if (IPC_MAX_NTFY_CNT > ipc_ut_ntfy_info.count) {
+            kal_bool added;
+
+            added = KAL_FALSE;
+            for ( ntfy_info_idx = 0 ; ntfy_info_idx < IPC_MAX_NTFY_CNT ; ntfy_info_idx ++ ) {
+                if ((KAL_FALSE == added) &&
+                    (KAL_FALSE == ipc_ut_ntfy_info.ntfy_valid[ntfy_info_idx]) /* Find invalid(NULL) entry to register */) {
+                    ntfy_id = ipc_register_ntfy(ipc_ut_ntfy_callback, (void*)ntfy_info_idx);
+
+                    /* Should success */
+                    if ( 0 > ntfy_id ) {
+                        goto err;
+                    }
+
+                    /* record the notification ID */
+                    UT_ASSERT(ipc_ut_ntfy_info.count < IPC_MAX_NTFY_CNT);
+                    ipc_ut_ntfy_info.ntfy_valid[ntfy_info_idx] = KAL_TRUE;
+                    ipc_ut_ntfy_info.ntfy_context[ntfy_info_idx] = ntfy_info_idx;
+                    ipc_ut_ntfy_info.ntfy_id[ntfy_info_idx] = ntfy_id;
+                    ipc_ut_ntfy_info.count ++;
+
+                    added = KAL_TRUE;
+                }
+            }
+        } else {
+            ntfy_id = ipc_register_ntfy(ipc_ut_ntfy_callback, (void*)0x12345678);
+
+            /* Should fail */
+            if ( 0 <= ntfy_id ) {
+                goto err;
+            }
+        }
+    }
+
+    return KAL_TRUE;
+
+err:
+    return KAL_FALSE;
+}
+
+kal_bool ipc_ut_ntfy_deregistration(kal_bool deregister_all, kal_int32 deregister_cnt, kal_int32 *remaining_cnt) {
+    kal_int32 total_deregister_cnt;
+    kal_int32 deregistered_cnt;
+    kal_int32 total_skip_count;
+    kal_int32 start_idx;
+
+    if (KAL_TRUE == deregister_all) {   /* Deregister ALL entries */
+        total_deregister_cnt = ipc_ut_ntfy_info.count;
+        total_skip_count = 0;
+    } else {   /* Deregister specific count entries */
+        total_deregister_cnt = deregister_cnt;
+        total_skip_count = 1;
+    }
+
+
+    deregistered_cnt = 0;
+    start_idx = 0;
+
+    while ((deregistered_cnt < total_deregister_cnt) && (ipc_ut_ntfy_info.count > 0)) {
+        kal_int32 ntfy_info_idx;
+        kal_bool deregistered;
+        kal_int32 skip_count;
+
+        deregistered = KAL_FALSE;
+        skip_count = total_skip_count;
+        ntfy_info_idx = start_idx;
+
+        while (KAL_FALSE == deregistered) {
+            /* Find valid entry to deregister */
+            if (KAL_TRUE == ipc_ut_ntfy_info.ntfy_valid[ntfy_info_idx]) {
+                if (0 < skip_count) /* Skip valid entry if skip count > 0 */ {
+                    skip_count --;
+                } else {   /* actually deregister entry */
+                    ipc_deregister_ntfy(ipc_ut_ntfy_info.ntfy_id[ntfy_info_idx]);
+
+                    ipc_ut_ntfy_info.ntfy_valid[ntfy_info_idx] = KAL_FALSE;
+                    ipc_ut_ntfy_info.count --;
+                    deregistered_cnt ++;
+                    deregistered = KAL_TRUE;
+                }
+            }
+
+            /* Next entry */
+            if (ntfy_info_idx == IPC_MAX_NTFY_CNT) {
+                ntfy_info_idx = 0;
+            } else {
+                ntfy_info_idx ++;
+            }
+        }
+
+        start_idx = ntfy_info_idx;
+    }
+
+    if (remaining_cnt) {*remaining_cnt = ipc_ut_ntfy_info.count;}
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ntfy_chk_param(ipc_ntfy_type_e ntfy_type, kal_int32 netif_id, kal_int32 ip_id, kal_int32 ntfy_cnt) {
+    kal_int32 match_cnt;
+    kal_int32 idx;
+
+    match_cnt = 0;
+
+    for ( idx = 0 ; idx < ipc_ut_ntfy_param.count ; idx ++ ) {
+        if (ipc_ut_ntfy_param.params[idx].ntfy_type != ntfy_type)   {continue;}
+        if (ipc_ut_ntfy_param.params[idx].netif_id != netif_id)     {continue;}
+        if (ipc_ut_ntfy_param.params[idx].ip_id != ip_id)           {continue;}
+        match_cnt ++;
+    }
+
+    return (match_cnt == ntfy_cnt)?KAL_TRUE:KAL_FALSE;
+}
+
+/*------------------------------------------------------------------------------
+ * public functions.
+ *----------------------------------------------------------------------------*/
+kal_bool ipc_ut_msg_chk(module_type _src_mod_id, module_type _dest_mod_id, sap_type _sap_id, msg_type _msg_id, kal_int32 _trigger_cnt);
+
+kal_bool ipc_ut_msg_chk(
+    module_type _src_mod_id,
+    module_type _dest_mod_id,
+    sap_type _sap_id,
+    msg_type _msg_id,
+    kal_int32 _trigger_cnt /* <0 means 'DONT CHECK' */) {
+
+    if ((_trigger_cnt >= 0) && (_trigger_cnt != ipc_ut_msg_sent._trigger_cnt)) {
+        goto err;
+    }
+
+    if (_trigger_cnt != 0) {    /* Don't check trigger count and expected trigger count > 0 */
+        if (kal_mem_cmp(&(ipc_ut_msg_sent._src_mod_id),&(_src_mod_id), sizeof(module_type))) {
+            goto err;
+        }
+
+        if (kal_mem_cmp(&(ipc_ut_msg_sent._dest_mod_id),&(_dest_mod_id), sizeof(module_type))) {
+            goto err;
+        }
+
+        if (kal_mem_cmp(&(ipc_ut_msg_sent._sap_id),&(_sap_id), sizeof(sap_type))) {
+            goto err;
+        }
+
+        if (kal_mem_cmp(&(ipc_ut_msg_sent._msg_id),&(_msg_id), sizeof(msg_type))) {
+            goto err;
+        }
+    }
+
+    return KAL_TRUE;
+err:
+    return KAL_FALSE;
+}
+
+kal_bool ipc_ut_msg_send6(module_type _src_mod_id,
+                          module_type _dest_mod_id,
+                          sap_type _sap_id,
+                          msg_type _msg_id,
+                          local_para_struct *_local_para_ptr,
+                          peer_buff_struct *_peer_buff_ptr)
+{
+    ipc_ut_msg_sent._trigger_cnt ++;
+
+    kal_mem_cpy(&(ipc_ut_msg_sent._src_mod_id),&(_src_mod_id), sizeof(module_type));
+    kal_mem_cpy(&(ipc_ut_msg_sent._dest_mod_id),&(_dest_mod_id), sizeof(module_type));
+
+    kal_mem_cpy(&(ipc_ut_msg_sent._sap_id),&(_sap_id), sizeof(sap_type));
+    kal_mem_cpy(&(ipc_ut_msg_sent._msg_id),&(_msg_id), sizeof(msg_type));
+
+    /* copy pointer only for UT verification and free local parameter and peer buffer */
+    kal_mem_cpy(&(ipc_ut_msg_sent._local_para_ptr), &(_local_para_ptr), sizeof(local_para_struct *));
+    kal_mem_cpy(&(ipc_ut_msg_sent._peer_buff_ptr), &(_peer_buff_ptr), sizeof(peer_buff_struct *));
+
+    if (_local_para_ptr) {
+        if (ipc_latest_local_param_p) {
+            kal_mem_cpy(ipc_latest_local_param_p, _local_para_ptr, ipc_latest_local_param_size);
+        }
+
+        free_local_para((local_para_struct *)_local_para_ptr);
+    }
+
+    if (_peer_buff_ptr) {
+        if (ipc_latest_peer_buff_p) {
+            kal_mem_cpy(ipc_latest_peer_buff_p, _peer_buff_ptr, ipc_latest_peer_buff_size);
+        }
+
+        free_peer_buff((peer_buff_struct *)_peer_buff_ptr);
+    }
+
+    return KAL_TRUE;
+}
+
+void ipc_ut_on_ul_packet_filtered_req(void *req_ptr) {
+    ipc_packet_filtered_req_t   *req = (ipc_packet_filtered_req_t *)req_ptr;
+
+    ipc_ut_ul_filter_callback(
+        req->context,
+        req->filter_id,
+        (qbm_gpd *)req->head_gpd,
+        (qbm_gpd *)req->tail_gpd,
+        req->length);
+}
+
+void ipc_ut_on_dl_packet_filtered_req(void *req_ptr) {
+    ipc_packet_filtered_req_t   *req = (ipc_packet_filtered_req_t *)req_ptr;
+
+    ipc_ut_dl_filter_callback(
+        req->context,
+        req->filter_id,
+        (qbm_gpd *)req->head_gpd,
+        (qbm_gpd *)req->tail_gpd,
+        req->length);
+}
+
+void ipc_ut_on_ul_packet_filtered_with_info_req(void *req_ptr) {
+    ipc_packet_filtered_with_info_req_t *req = (ipc_packet_filtered_with_info_req_t *)req_ptr;
+
+    ipc_ut_ul_filter_with_info_callback(
+        &(req->info),
+        req->context,
+        req->filter_id,
+        (qbm_gpd *)req->head_gpd,
+        (qbm_gpd *)req->tail_gpd,
+        req->length);
+}
+
+void ipc_ut_on_dl_packet_filtered_with_info_req(void *req_ptr) {
+    ipc_packet_filtered_with_info_req_t *req = (ipc_packet_filtered_with_info_req_t *)req_ptr;
+
+    ipc_ut_dl_filter_with_info_callback(
+        &(req->info),
+        req->context,
+        req->filter_id,
+        (qbm_gpd *)req->head_gpd,
+        (qbm_gpd *)req->tail_gpd,
+        req->length);
+}
+
+
+void ipc_ut_reset_ul_info(void) {
+    ipc_ut_ul_pdn_id = 0;
+    ipc_ut_ul_gpd_cnt = 0;
+    ipc_ut_ul_meta_cnt = 0;
+    ipc_ut_ul_meta_non_igr_cnt = 0;
+    ipc_ut_ul_proto_idx = IPC_UT_INVALID_UL_PROTO_IDX;
+}
+
+void ipc_ut_rcv_ul_sdu(ip_type_e ip_type, kal_uint32 pdn_id, qbm_gpd *p_head, qbm_gpd *p_tail, kal_uint8 proto_idx) {
+    UT_ASSERT(NULL != p_head);
+    UT_ASSERT(NULL != p_tail);
+
+    ipc_ut_ul_pdn_id = pdn_id;
+    ipc_ut_ul_gpd_cnt += ipc_ut_gpd_list_count(p_head, p_tail);
+
+    /* Drop GPD list */
+    qbmt_dest_q(p_head, p_tail);
+
+    if (proto_idx != ipc_ut_ul_proto_idx) {
+        if (IPC_UT_INVALID_UL_PROTO_IDX == ipc_ut_ul_proto_idx) {
+            ipc_ut_ul_proto_idx = proto_idx;
+        } else if (1 == proto_idx) {
+            /* Do nothing */
+        } else {
+            utDLOG("unexpected SIM idx\r\n");
+            UT_ASSERT(KAL_FALSE);
+        }
+    }
+}
+
+void ipc_ut_rcv_ul_sdu_by_ebi(kal_uint32 ebi, qbm_gpd *p_head, qbm_gpd *p_tail, kal_uint8 proto_idx) {
+    if (IPC_UT_UL_EBI == ebi) {
+        if (ipc_ut_ul_ebi_tail_gpd) {
+            QBM_DES_SET_NEXT(ipc_ut_ul_ebi_tail_gpd, p_head);
+            ipc_ut_ul_ebi_tail_gpd = p_tail;
+        } else {
+            ipc_ut_ul_ebi_head_gpd = p_head;
+            ipc_ut_ul_ebi_tail_gpd = p_tail;
+        }
+    } else {
+        qbmt_dest_q(p_head, p_tail);
+        utDLOG("unexpected EBI\r\n");
+        UT_ASSERT(KAL_FALSE);
+    }
+    if (proto_idx != ipc_ut_ul_proto_idx) {
+        if (IPC_UT_INVALID_UL_PROTO_IDX == ipc_ut_ul_proto_idx) {
+            ipc_ut_ul_proto_idx = proto_idx;
+        } else {
+            qbmt_dest_q(p_head, p_tail);
+            utDLOG("unexpected SIM idx\r\n");
+            UT_ASSERT(KAL_FALSE);
+        }
+    }
+    g_received_cnt += ipc_ut_gpd_list_count(p_head, p_tail);
+}
+
+void ipc_ut_reg_cbk_notify_tick_source(upcm_nofify_lte_tick_f pf_notify) {
+    /* Do nothing in UT */
+}
+
+void ipc_ut_reg_cbk_dlvr_dl_sdu(upcm_dlvr_dl_sdu_93_f pf_dlvr_sdu) {
+    /* Do nothing in UT */
+}
+
+void ipc_ut_rcv_ul_sdu_meta(kal_uint32 start_idx, kal_uint32 end_idx, LHIF_QUEUE_TYPE q_type) {
+    kal_uint32  i = start_idx;
+    kal_int16   proto_idx = IPC_UT_INVALID_UL_PROTO_IDX;
+
+    while (i != end_idx) {
+        if (!ipc_ut_meta_tbl_s[i].ignore ) {
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+            if(ipc_ut_meta_tbl_s[i].mr != IPC_HPC_MR_DPFM_ADD_CMD){
+                proto_idx = ipc_ut_meta_tbl_s[i].protocol_idx;
+                ipc_ut_ul_pdn_id = ipc_ut_meta_tbl_s[i].pdn;
+            }
+#else
+            proto_idx = ipc_ut_meta_tbl_s[i].protocol_idx;
+            ipc_ut_ul_pdn_id = ipc_ut_meta_tbl_s[i].pdn;
+#endif
+        }
+
+        i ++;
+        if (i == IPC_UT_META_TABLE_SIZE) {
+            i = 0;
+        }
+    }
+    ipc_ut_ul_meta_cnt += (end_idx > start_idx) ? (end_idx - start_idx) : (IPC_UT_META_TABLE_SIZE - start_idx + end_idx);
+    ipc_ut_ul_meta_non_igr_cnt += ipc_ut_non_igr_meta_count(start_idx, end_idx, q_type);
+    UT_ASSERT(ipc_ut_ul_meta_cnt == (ipc_ut_ul_meta_non_igr_cnt + g_ipc_ut_igr_meta_cnt));
+
+    /* Free meta list */
+    ipc_ut_meta_read_done(start_idx, end_idx, q_type);
+
+    if (proto_idx != ipc_ut_ul_proto_idx) {
+        if (IPC_UT_INVALID_UL_PROTO_IDX == ipc_ut_ul_proto_idx) {
+            ipc_ut_ul_proto_idx = proto_idx;
+        } else {
+            utDLOG("unexpected SIM idx\r\n");
+            UT_ASSERT(KAL_FALSE);
+        }
+    }
+}
+
+kal_bool ipc_ut_dpfm_check_route(kal_bool uplink, kal_uint8 ip_type, ipc_pkt_des_t *pkt_des, kal_uint32 in_netif_id, kal_uint32 *out_netif_id) {
+    ipc_packet_info_t *packet_info;
+    kal_bool matched = KAL_TRUE;
+    lhif_meta_tbl_t *ul_meta;
+    ipf_dl_meta *dl_meta;
+
+    UT_ASSERT((NULL != pkt_des) && (NULL !=out_netif_id));
+
+    packet_info = pkt_des->packet_info;
+
+    if ( pkt_des->des_type == IPC_PKT_DES_TYPE_META)
+    {
+        if (uplink) {
+            ul_meta = pkt_des->meta;
+            if (IPC_HPC_MR_DPFM_MATCH == ul_meta->mr) {
+                goto _match;
+            }
+        } else {
+            dl_meta = pkt_des->ipf_meta;
+            if (IPC_IPF_MR_DPFM_MATCH == dl_meta->mr) {
+                goto _match;
+            }
+        }
+    }
+
+    matched &= (IPC_INVALID_NETIF_ID != in_netif_id);
+    matched &= (IPC_IP_TYPE_IPV4 == ip_type || IPC_IP_TYPE_IPV6 == ip_type);
+
+    if (IPC_IP_TYPE_IPV4 == ip_type) {
+        if (uplink) {
+            matched &= (IPC_PORT_BOOTPC == packet_info->src_port);
+            matched &= (IPC_PORT_BOOTPS == packet_info->dst_port);
+        } else {
+            matched &= (IPC_PORT_BOOTPS == packet_info->src_port);
+            matched &= (IPC_PORT_BOOTPC == packet_info->dst_port);
+        }
+    } else {
+        /* IPV6 */
+        if (uplink) {
+            matched &= (IPC_UT_IPV6_DPFM_SRC_PORT == packet_info->src_port);
+            matched &= (IPC_UT_IPV6_DPFM_DST_PORT == packet_info->dst_port);
+        } else {
+            matched &= (IPC_UT_IPV6_DPFM_SRC_PORT == packet_info->src_port);
+            matched &= (IPC_UT_IPV6_DPFM_DST_PORT == packet_info->dst_port);
+        }
+    }
+    matched &= (IPC_HDR_PROT_UDP == packet_info->protocol);
+
+_match:
+    if (matched) {
+        *out_netif_id = (uplink) ? IPC_UT_LHIF_NETID_START : IPC_UT_DPFM_NETID_START;
+    }
+
+    return matched;
+}
+
+kal_bool ipc_ut_dpfm_is_activated(void)
+{
+    return ipc_ut_dpfm_is_activated_g;
+}
+
+/*------------------------------------------------------------------------------
+ * test case functions.
+ *----------------------------------------------------------------------------*/
+
+#if defined(__MTK_TARGET__)
+kal_bool ipc_ut_struct(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    // init before test
+    ipc_ut_init();
+
+    if (sizeof(ipc_io_request_t) % 4 != 0) {
+        utELOG("ipc_io_request_t size is not multiple of 4-bte!\r\n");
+        return KAL_FALSE;
+    }
+    if (sizeof(ipc_conf_t) % 4 != 0) {
+        utELOG("ipc_conf_t size is not multiple of 4-bte!\r\n");
+        return KAL_FALSE;
+    }
+    if (sizeof(ipc_filter_rules_t) % 4 != 0) {
+        utELOG("ipc_filter_rules_t size is not multiple of 4-bte!\r\n");
+        return KAL_FALSE;
+    }
+    if (sizeof(ipc_link_req_t) % 4 != 0) {
+        utELOG("ipc_link_req_t size is not multiple of 4-bte!\r\n");
+        return KAL_FALSE;
+    }
+    if (sizeof(ipc_packet_filtered_req_t) % 4 != 0) {
+        utELOG("ipc_packet_filtered_req_t size is not multiple of 4-bte!\r\n");
+        return KAL_FALSE;
+    }
+
+    if (sizeof(ipc_netif_t) % 4 != 0) {
+        utELOG("ipc_netif_t size is not multiple of 4-bte!\r\n");
+        return KAL_FALSE;
+    }
+    if (sizeof(ipc_session_t) % 4 != 0) {
+        utELOG("ipc_session_t size is not multiple of 4-bte!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+#endif
+
+kal_bool ipc_ut_helper_macro(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    static kal_uint8 in_buf[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
+    static kal_uint8 out_buf[40];
+
+    // init before test
+    ipc_ut_init();
+
+    if (IPC_NE_GET_2B(in_buf)    != 0x1122 ||
+        IPC_NE_GET_2B(in_buf+1)  != 0x2233 ) {
+        utELOG("IPC_NE_GET_2B() failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    kal_mem_set(out_buf, 0, sizeof(out_buf));
+    IPC_NE_SET_2B(out_buf, 0x1122);
+    IPC_NE_SET_2B(out_buf+5, 0x6677);
+    if (kal_mem_cmp(in_buf, out_buf, 2) ||
+        kal_mem_cmp(in_buf+5, out_buf+5, 2)) {
+        utELOG("IPC_NE_SET_2B() failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    if (IPC_NE_GET_4B(in_buf)    != 0x11223344 ||
+        IPC_NE_GET_4B(in_buf+1)  != 0x22334455 ||
+        IPC_NE_GET_4B(in_buf+2)  != 0x33445566 ||
+        IPC_NE_GET_4B(in_buf+3)  != 0x44556677) {
+        utELOG("IPC_NE_GET_4B() failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    kal_mem_set(out_buf, 0, sizeof(out_buf));
+    IPC_NE_SET_4B(out_buf, 0x11223344);
+    if (kal_mem_cmp(in_buf, out_buf, 4)) {
+        utELOG("IPC_NE_SET_4B() offset 0 failed!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_set(out_buf, 0, sizeof(out_buf));
+    IPC_NE_SET_4B(out_buf+1, 0x22334455);
+    if (kal_mem_cmp(in_buf+1, out_buf+1, 4)) {
+        utELOG("IPC_NE_SET_4B() offset 1 failed!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_set(out_buf, 0, sizeof(out_buf));
+    IPC_NE_SET_4B(out_buf+2, 0x33445566);
+    if (kal_mem_cmp(in_buf+2, out_buf+2, 4)) {
+        utELOG("IPC_NE_SET_4B() offset 2 failed!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_set(out_buf, 0, sizeof(out_buf));
+    IPC_NE_SET_4B(out_buf+3, 0x44556677);
+    if (kal_mem_cmp(in_buf+3, out_buf+3, 4)) {
+        utELOG("IPC_NE_SET_4B() offset 3 failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * IPv4
+     */
+    if (!IPC_HDR_IS_V4(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_IS_V4() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (20 != IPC_HDR_V4_GET_IHL(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_GET_IHL() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x01 != IPC_HDR_V4_GET_DSCP(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_GET_DSCP() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x015f != IPC_HDR_V4_GET_TOTAL_LENGTH(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_GET_TOTAL_LENGTH() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x5f54 != IPC_HDR_V4_GET_IDENTITY(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_GET_IDENTITY() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0 != IPC_HDR_V4_GET_FLAGS(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_GET_FLAGS() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0 != IPC_HDR_V4_IS_MF(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_IS_MF() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0 != IPC_HDR_V4_GET_FRAG_OFFSET(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_GET_FRAG_OFFSET() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0 != IPC_HDR_V4_IS_FRAG(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_IS_FRAG() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x40 != IPC_HDR_V4_GET_TTL(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_GET_TTL() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x11 != IPC_HDR_V4_GET_PROTOCOL(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_GET_PROTOCOL() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x92c3 != IPC_HDR_V4_GET_HEADER_CHECKSUM(ipc_ut_ipv4_dhcp_packet)) {
+        utELOG("IPC_HDR_V4_GET_HEADER_CHECKSUM() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0xac != *IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_ipv4_dhcp_packet) ||
+        0x16 != *(IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_ipv4_dhcp_packet)+1)) {
+        utELOG("IPC_HDR_V4_GET_SRC_ADDR() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0xac != *IPC_HDR_V4_GET_DST_ADDR(ipc_ut_ipv4_dhcp_packet) ||
+        0x16 != *(IPC_HDR_V4_GET_DST_ADDR(ipc_ut_ipv4_dhcp_packet)+1)) {
+        utELOG("IPC_HDR_V4_GET_DST_ADDR() failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    kal_mem_set(out_buf, 0xff, sizeof(out_buf));
+    IPC_HDR_V4_RESET_VER_IHL_DSCP_ECN(out_buf);
+    IPC_HDR_V4_SET_IHL(out_buf, 24);
+    IPC_HDR_V4_SET_DSCP(out_buf, 0x8);
+    IPC_HDR_V4_SET_TOTAL_LENGTH(out_buf, 0x0123);
+    IPC_HDR_V4_SET_IDENTITY(out_buf, 0x1234);
+    IPC_HDR_V4_SET_FLAGS(out_buf, 0x4);
+    IPC_HDR_V4_SET_FRAG_OFFSET(out_buf, 0x234);
+    IPC_HDR_V4_SET_TTL(out_buf, 0x45);
+    IPC_HDR_V4_SET_PROTOCOL(out_buf, 0x88);
+    IPC_HDR_V4_SET_HEADER_CHECKSUM(out_buf, 0x1234);
+    IPC_HDR_V4_SET_SRC_ADDR(out_buf, IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_ipv4_dhcp_packet));
+    IPC_HDR_V4_SET_DST_ADDR(out_buf, IPC_HDR_V4_GET_DST_ADDR(ipc_ut_ipv4_dhcp_packet));
+
+    if (!IPC_HDR_IS_V4(out_buf)) {
+        utELOG("IPC_HDR_V4_RESET_VER_IHL_DSCP_ECN() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (24 != IPC_HDR_V4_GET_IHL(out_buf)) {
+        utELOG("IPC_HDR_V4_SET_IHL() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x8 != IPC_HDR_V4_GET_DSCP(out_buf)) {
+        utELOG("IPC_HDR_V4_SET_DSCP() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x0123 != IPC_HDR_V4_GET_TOTAL_LENGTH(out_buf)) {
+        utELOG("IPC_HDR_V4_SET_TOTAL_LENGTH() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x1234 != IPC_HDR_V4_GET_IDENTITY(out_buf)) {
+        utELOG("IPC_HDR_V4_SET_IDENTITY() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x4 != IPC_HDR_V4_GET_FLAGS(out_buf)) {
+        utELOG("IPC_HDR_V4_SET_FLAGS() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x234 != IPC_HDR_V4_GET_FRAG_OFFSET(out_buf)) {
+        utELOG("IPC_HDR_V4_SET_FRAG_OFFSET() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x45 != IPC_HDR_V4_GET_TTL(out_buf)) {
+        utELOG("IPC_HDR_V4_SET_TTL() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x88 != IPC_HDR_V4_GET_PROTOCOL(out_buf)) {
+        utELOG("IPC_HDR_V4_SET_PROTOCOL() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x1234 != IPC_HDR_V4_GET_HEADER_CHECKSUM(out_buf)) {
+        utELOG("IPC_HDR_V4_SET_HEADER_CHECKSUM() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (!IPC_EQ_V4_ADDR(IPC_HDR_V4_GET_SRC_ADDR(out_buf), IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_ipv4_dhcp_packet))) {
+        utELOG("IPC_HDR_V4_SET_SRC_ADDR() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (!IPC_EQ_V4_ADDR(IPC_HDR_V4_GET_DST_ADDR(out_buf), IPC_HDR_V4_GET_DST_ADDR(ipc_ut_ipv4_dhcp_packet))) {
+        utELOG("IPC_HDR_V4_SET_DST_ADDR() failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * IPv6
+     */
+    if (!IPC_HDR_IS_V6(ipc_ut_ipv6_dhcp_packet)) {
+        utELOG("IPC_HDR_IS_V6() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0 != IPC_HDR_V6_GET_TC(ipc_ut_ipv6_dhcp_packet)) {
+        utELOG("IPC_HDR_V6_GET_TC() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0 != IPC_HDR_V6_GET_FLOW_LABEL(ipc_ut_ipv6_dhcp_packet)) {
+        utELOG("IPC_HDR_V6_GET_FLOW_LABEL() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x0042 != IPC_HDR_V6_GET_LENGTH(ipc_ut_ipv6_dhcp_packet)) {
+        utELOG("IPC_HDR_V6_GET_LENGTH() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x11 != IPC_HDR_V6_GET_NH_TYPE(ipc_ut_ipv6_dhcp_packet)) {
+        utELOG("IPC_HDR_V6_GET_NH_TYPE() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x01 != IPC_HDR_V6_GET_HOP_LIMIT(ipc_ut_ipv6_dhcp_packet)) {
+        utELOG("IPC_HDR_V6_GET_HOP_LIMIT() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0xfe != *(IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_ipv6_dhcp_packet)) ||
+        0x80 != *(IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_ipv6_dhcp_packet)+1)) {
+        utELOG("IPC_HDR_V6_GET_SRC_ADDR() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0xff != *(IPC_HDR_V6_GET_DST_ADDR(ipc_ut_ipv6_dhcp_packet)) ||
+        0x02 != *(IPC_HDR_V6_GET_DST_ADDR(ipc_ut_ipv6_dhcp_packet)+1)) {
+        utELOG("IPC_HDR_V6_GET_DST_ADDR() failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    kal_mem_set(out_buf, 0, sizeof(out_buf));
+    IPC_HDR_V6_RESET_VER_TC_FL(out_buf);
+    IPC_HDR_V6_SET_TC(out_buf, 0x12);
+    IPC_HDR_V6_SET_FLOW_LABEL(out_buf, 0x34567);
+    IPC_HDR_V6_SET_LENGTH(out_buf, 0x102);
+    IPC_HDR_V6_SET_NH_TYPE(out_buf, 0x06);
+    IPC_HDR_V6_SET_HOP_LIMIT(out_buf, 0xff);
+    IPC_HDR_V6_SET_SRC_ADDR(out_buf, IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_ipv6_dhcp_packet));
+    IPC_HDR_V6_SET_DST_ADDR(out_buf, IPC_HDR_V6_GET_DST_ADDR(ipc_ut_ipv6_dhcp_packet));
+
+    if (!IPC_HDR_IS_V6(out_buf)) {
+        utELOG("IPC_HDR_V6_RESET_VER_TC_FL() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x12 != IPC_HDR_V6_GET_TC(out_buf)) {
+        utELOG("IPC_HDR_V6_SET_TC() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x34567 != IPC_HDR_V6_GET_FLOW_LABEL(out_buf)) {
+        utELOG("IPC_HDR_V6_SET_FLOW_LABEL() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x102 != IPC_HDR_V6_GET_LENGTH(out_buf)) {
+        utELOG("IPC_HDR_V6_SET_LENGTH() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x06 != IPC_HDR_V6_GET_NH_TYPE(out_buf)) {
+        utELOG("IPC_HDR_V6_SET_NH_TYPE() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0xff != IPC_HDR_V6_GET_HOP_LIMIT(out_buf)) {
+        utELOG("IPC_HDR_V6_SET_HOP_LIMIT() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (!IPC_EQ_V6_ADDR(IPC_HDR_V6_GET_SRC_ADDR(out_buf), IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_ipv6_dhcp_packet))) {
+        utELOG("IPC_HDR_V6_SET_SRC_ADDR() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (!IPC_EQ_V6_ADDR(IPC_HDR_V6_GET_DST_ADDR(out_buf), IPC_HDR_V6_GET_DST_ADDR(ipc_ut_ipv6_dhcp_packet))) {
+        utELOG("IPC_HDR_V6_SET_DST_ADDR() failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * UDP
+     */
+    if (0x0043 != IPC_HDR_UDP_GET_SRC_PORT(IPC_HDR_V4_GET_NHPTR(ipc_ut_ipv4_dhcp_packet))) {
+        utELOG("IPC_HDR_UDP_GET_SRC_PORT() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x0044 != IPC_HDR_UDP_GET_DST_PORT(IPC_HDR_V4_GET_NHPTR(ipc_ut_ipv4_dhcp_packet))) {
+        utELOG("IPC_HDR_UDP_GET_DST_PORT() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x014b != IPC_HDR_UDP_GET_LENGTH(IPC_HDR_V4_GET_NHPTR(ipc_ut_ipv4_dhcp_packet))) {
+        utELOG("IPC_HDR_UDP_GET_LENGTH() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0xcf7d != IPC_HDR_UDP_GET_CHECKSUM(IPC_HDR_V4_GET_NHPTR(ipc_ut_ipv4_dhcp_packet))) {
+        utELOG("IPC_HDR_UDP_GET_CHECKSUM() failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    kal_mem_set(out_buf, 0, sizeof(out_buf));
+    IPC_HDR_UDP_SET_SRC_PORT(out_buf, 0x1234);
+    IPC_HDR_UDP_SET_DST_PORT(out_buf, 0x5678);
+    IPC_HDR_UDP_SET_LENGTH(out_buf, 0x9abc);
+    IPC_HDR_UDP_SET_CHECKSUM(out_buf, 0xdef0);
+    if (0x1234 != IPC_HDR_UDP_GET_SRC_PORT(out_buf)) {
+        utELOG("IPC_HDR_UDP_SET_SRC_PORT() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x5678 != IPC_HDR_UDP_GET_DST_PORT(out_buf)) {
+        utELOG("IPC_HDR_UDP_SET_DST_PORT() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0x9abc != IPC_HDR_UDP_GET_LENGTH(out_buf)) {
+        utELOG("IPC_HDR_UDP_SET_LENGTH() failed!\r\n");
+        return KAL_FALSE;
+    }
+    if (0xdef0 != IPC_HDR_UDP_GET_CHECKSUM(out_buf)) {
+        utELOG("IPC_HDR_UDP_SET_CHECKSUM() failed!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_checksum(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32  idx;
+    kal_uint32  length;
+    kal_uint16  checksum;
+
+    // init before test
+    ipc_ut_init();
+
+    length = IPC_HDR_V4_GET_IHL(ipc_ut_ipv4_dns_packet);
+    for (idx = 0; idx < 4; idx++) {
+        kal_mem_set(ipc_ut_checksum_buf_s, 0, sizeof(ipc_ut_checksum_buf_s));
+        kal_mem_cpy(ipc_ut_checksum_buf_s + idx, ipc_ut_ipv4_dns_packet, length);
+
+        checksum = ipc_utils_calc_ipv4_checksum(ipc_ut_checksum_buf_s + idx);
+        if (0 != checksum) {
+            utELOG("ipc_utils_calc_ipv4_checksum(ipc_ut_ipv4_dns_packet) failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    length = sizeof(ipc_ut_ipv4_dns_packet);
+    for (idx = 0; idx < 4; idx++) {
+        kal_mem_set(ipc_ut_checksum_buf_s, 0, sizeof(ipc_ut_checksum_buf_s));
+        kal_mem_cpy(ipc_ut_checksum_buf_s + idx, ipc_ut_ipv4_dns_packet, length);
+
+        checksum = ipc_utils_calc_udp_checksum(
+                        KAL_TRUE,
+                        IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V4_GET_DST_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V4_GET_NHPTR(ipc_ut_checksum_buf_s + idx),
+                        length - IPC_HDR_V4_GET_IHL(ipc_ut_checksum_buf_s + idx));
+        if (0xffff != checksum) {
+            utELOG("ipc_utils_calc_udp_checksum(ipc_ut_ipv4_dns_packet) failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    length = sizeof(ipc_ut_ipv4_dhcp_packet);
+    for (idx = 0; idx < 4; idx++) {
+        kal_mem_set(ipc_ut_checksum_buf_s, 0, sizeof(ipc_ut_checksum_buf_s));
+        kal_mem_cpy(ipc_ut_checksum_buf_s + idx, ipc_ut_ipv4_dhcp_packet, length);
+
+        checksum = ipc_utils_calc_udp_checksum(
+                        KAL_TRUE,
+                        IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V4_GET_DST_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V4_GET_NHPTR(ipc_ut_checksum_buf_s + idx),
+                        length - IPC_HDR_V4_GET_IHL(ipc_ut_checksum_buf_s + idx));
+        if (0xffff != checksum) {
+            utELOG("ipc_utils_calc_udp_checksum(ipc_ut_ipv4_dhcp_packet) failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    length = sizeof(ipc_ut_ipv4_dhcp_ul_packet);
+    for (idx = 0; idx < 4; idx++) {
+        kal_mem_set(ipc_ut_checksum_buf_s, 0, sizeof(ipc_ut_checksum_buf_s));
+        kal_mem_cpy(ipc_ut_checksum_buf_s + idx, ipc_ut_ipv4_dhcp_ul_packet, length);
+
+        checksum = ipc_utils_calc_udp_checksum(
+                        KAL_TRUE,
+                        IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V4_GET_DST_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V4_GET_NHPTR(ipc_ut_checksum_buf_s + idx),
+                        length - IPC_HDR_V4_GET_IHL(ipc_ut_checksum_buf_s + idx));
+        if (0xffff != checksum) {
+            utELOG("ipc_utils_calc_udp_checksum(ipc_ut_ipv4_dhcp_ul_packet) failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    length = sizeof(ipc_ut_ipv6_mdns_packet);
+    for (idx = 0; idx < 4; idx++) {
+        kal_mem_set(ipc_ut_checksum_buf_s, 0, sizeof(ipc_ut_checksum_buf_s));
+        kal_mem_cpy(ipc_ut_checksum_buf_s + idx, ipc_ut_ipv6_mdns_packet, length);
+
+        checksum = ipc_utils_calc_udp_checksum(
+                        KAL_FALSE,
+                        IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V6_GET_DST_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V6_GET_NHPTR(ipc_ut_checksum_buf_s + idx),
+                        length - IPC_HDR_V6_HEADER_SIZE);
+        if (0xffff != checksum) {
+            utELOG("ipc_utils_calc_udp_checksum(ipc_ut_ipv6_mdns_packet) failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    length = sizeof(ipc_ut_ipv6_dhcp_ul_packet);
+    for (idx = 0; idx < 4; idx++) {
+        kal_mem_set(ipc_ut_checksum_buf_s, 0, sizeof(ipc_ut_checksum_buf_s));
+        kal_mem_cpy(ipc_ut_checksum_buf_s + idx, ipc_ut_ipv6_dhcp_ul_packet, length);
+
+        checksum = ipc_utils_calc_udp_checksum(
+                        KAL_FALSE,
+                        IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V6_GET_DST_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V6_GET_NHPTR(ipc_ut_checksum_buf_s + idx),
+                        length - IPC_HDR_V6_HEADER_SIZE);
+        if (0xffff != checksum) {
+            utELOG("ipc_utils_calc_udp_checksum(ipc_ut_ipv6_dhcp_ul_packet) failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+
+    length = sizeof(ipc_ut_ipv6_dhcp_packet);
+    for (idx = 0; idx < 4; idx++) {
+        kal_mem_set(ipc_ut_checksum_buf_s, 0, sizeof(ipc_ut_checksum_buf_s));
+        kal_mem_cpy(ipc_ut_checksum_buf_s + idx, ipc_ut_ipv6_dhcp_packet, length);
+
+        checksum = ipc_utils_calc_udp_checksum(
+                        KAL_FALSE,
+                        IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V6_GET_DST_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V6_GET_NHPTR(ipc_ut_checksum_buf_s + idx),
+                        length - IPC_HDR_V6_HEADER_SIZE);
+        if (0xffff != checksum) {
+            utELOG("ipc_utils_calc_udp_checksum(ipc_ut_ipv6_dhcp_packet) failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    length = sizeof(ipc_ut_ipv6_udp_zero_checksum_packet);
+    for (idx = 0; idx < 4; idx++) {
+        kal_mem_set(ipc_ut_checksum_buf_s, 0, sizeof(ipc_ut_checksum_buf_s));
+        kal_mem_cpy(ipc_ut_checksum_buf_s + idx, ipc_ut_ipv6_udp_zero_checksum_packet, length);
+
+        checksum = ipc_utils_calc_udp_checksum(
+                        KAL_FALSE,
+                        IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V6_GET_DST_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V6_GET_NHPTR(ipc_ut_checksum_buf_s + idx),
+                        length - IPC_HDR_V6_HEADER_SIZE);
+        if (0xffff != checksum) {
+            utELOG("ipc_utils_calc_udp_checksum(ipc_ut_ipv6_udp_zero_checksum_packet) failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    length = sizeof(ipc_ut_ipv4_tcp_syn_packet);
+    for (idx = 0; idx < 4; idx++) {
+        kal_mem_set(ipc_ut_checksum_buf_s, 0, sizeof(ipc_ut_checksum_buf_s));
+        kal_mem_cpy(ipc_ut_checksum_buf_s + idx, ipc_ut_ipv4_tcp_syn_packet, length);
+
+        checksum = ipc_utils_calc_tcp_checksum(
+                        KAL_TRUE,
+                        IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V4_GET_DST_ADDR(ipc_ut_checksum_buf_s + idx),
+                        IPC_HDR_V4_GET_NHPTR(ipc_ut_checksum_buf_s + idx),
+                        length - IPC_HDR_V4_GET_IHL(ipc_ut_checksum_buf_s + idx));
+        if (0 != checksum) {
+            utELOG("ipc_utils_calc_tcp_checksum(ipc_ut_ipv4_tcp_syn_packet) failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_attach(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t   *net;
+    kal_bool          result;
+    kal_uint32        idx;
+
+    utDLOG("net count: %d\r\n", IPC_UT_MAX_NET_CNT);
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_task_reset()) {
+        utELOG("ipc_task_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+        net = &(ipc_ut_nets_s[idx]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+
+        if ((idx & 0x1)) {
+            net->conf.features = IPC_F_DHCP4C;
+        }
+
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+        if (!net->handle) {
+            utELOG("ipc_attach() returns NULL handle!\r\n");
+            return KAL_FALSE;
+        }
+
+        if (((ipc_netif_t *)(net->handle))->config.features != net->conf.features) {
+            utELOG("ipc_attach() returns NULL handle!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_detach(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t     *net;
+    kal_bool            result;
+    kal_uint32          idx;
+
+    // init before test
+    ipc_ut_init();
+
+    for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+        net = &(ipc_ut_nets_s[idx]);
+
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_find_netif(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t   *net;
+    ipc_netif_t        *netif;
+    kal_uint32          idx;
+    kal_uint32          error_code = 0;
+
+    // init before test
+    ipc_ut_init();
+
+    for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+        net = &(ipc_ut_nets_s[idx]);
+
+        netif = ipc_find_netif(net->conf.netif_id);
+        error_code = ipc_ut_check_netif(netif, net);
+        if (error_code) {
+            utELOG("ipc_find_netif() failed!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_new_session(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t   *net;
+    kal_uint32          idx;
+
+    // init before test
+    ipc_ut_init();
+
+    for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+        net = &(ipc_ut_nets_s[idx]);
+
+        net->pdn_id = idx;
+        net->ip_type = IPC_IP_TYPE_MIXED + (idx % 3);
+        net->session[net->ip_type] = ipc_new_session(net->handle, net->pdn_id, net->ip_type, IPC_SESSION_STATE_BIND);
+        if (!net->session[net->ip_type]) {
+            utELOG("ipc_new_session() failed!\r\n");
+            return KAL_FALSE;
+        }
+        if (idx != net->session[net->ip_type]->ip_id) {
+            utELOG("ipc_new_session() ip_id mismatched!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_del_session(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t     *net;
+    kal_uint32          idx;
+
+    // init before test
+    ipc_ut_init();
+
+    for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+        net = &(ipc_ut_nets_s[idx]);
+
+        ipc_del_session(net->session[net->ip_type]);
+        net->session[net->ip_type] = NULL;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_find_session(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t     *net;
+    kal_uint32          idx;
+    ipc_session_t      *session;
+    kal_uint32          error_code = 0;
+    ipc_session_t      *tmp_session;
+
+    // init before test
+    ipc_ut_init();
+
+    tmp_session = ipc_find_session_by_ip_id(IPC_UT_INVALID_IP_ID, IPC_IP_TYPE_IPV4);
+    if (tmp_session) {
+        IPC_R_UNLOCK_OBJECT(tmp_session, ipc_spinlock_g);
+        utELOG("ipc_find_session_by_ip_id() with invalid ip_id shall get nothing in return!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+        net = &(ipc_ut_nets_s[idx]);
+
+        session = ipc_find_session_by_context(net->pdn_id);
+        error_code = ipc_ut_check_session(session, net);
+        if (error_code) {
+            utELOG("ipc_find_session_by_context(): ip_id mismatched!\r\n");
+            return KAL_FALSE;
+        }
+
+        if (IPC_IP_TYPE_MIXED != net->ip_type) {
+            session = ipc_find_session_by_netif(net->handle, net->ip_type);
+            error_code = ipc_ut_check_session(session, net);
+            if (error_code) {
+                utELOG("ipc_find_session_by_netif(): IPC_IP_TYPE_MIXED case mismatched!\r\n");
+                return KAL_FALSE;
+            }
+        } else {
+            session = ipc_find_session_by_netif(net->handle, IPC_IP_TYPE_IPV4);
+            error_code = ipc_ut_check_session(session, net);
+            if (error_code) {
+                utELOG("ipc_find_session_by_netif(): IPC_IP_TYPE_MIXED case mismatched!\r\n");
+                return KAL_FALSE;
+            }
+
+            session = ipc_find_session_by_netif(net->handle, IPC_IP_TYPE_IPV6);
+            error_code = ipc_ut_check_session(session, net);
+            if (error_code) {
+                utELOG("ipc_find_session_by_netif(): IPC_IP_TYPE_MIXED case mismatched!\r\n");
+                return KAL_FALSE;
+            }
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_query_info(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+        kal_uint32        idx;
+        ipc_ut_netif_t   *net;
+        ipcore_upcm_pdn_bind_ind_struct *bind_req;
+        ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+        kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+        kal_bool          result;
+
+        /* init before test */
+        ipc_ut_init();
+
+        /* Reset IPCore before test */
+        if (KAL_TRUE != ipc_reset()) {
+            utELOG("ipc_reset() FAIL!\r\n");
+            return KAL_FALSE;
+        }
+
+        for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+            ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+            /* Before any netif attachment, 0 netif is attached */
+            {
+                ipc_query_info_t cnf_query_info;
+                ipc_query_info_t chk_query_info;
+
+                kal_mem_set(&cnf_query_info, 0, sizeof(ipc_query_info_t));
+                kal_mem_set(&chk_query_info, 0, sizeof(ipc_query_info_t));
+
+                ipc_ut_msg_reset(&cnf_query_info, sizeof(ipc_query_info_t), NULL, 0);
+
+                ipc_on_query_info(MOD_IPCORE, NULL);
+
+                if (ipc_ut_msg_chk(MOD_NIL,
+                                   MOD_IPCORE,
+                                   IPCORE_SAP,
+                                   MSG_ID_IPCORE_QUERY_INFO_CNF,
+                                   1) != KAL_TRUE) {
+                    utELOG("IPCore query reply is failed!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Information to check */
+                chk_query_info.netif.netif_cnt = 0;
+
+                if (kal_mem_cmp(&(chk_query_info.netif), &(cnf_query_info.netif), sizeof(chk_query_info.netif))) {
+                    utELOG("IPCore query reply content is failed!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+
+            /* ipc_attach() */
+            {
+                net = &(ipc_ut_nets_s[0]);
+                kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+                net->conf.module_id = MOD_IPCORE;
+                net->conf.netif_id = IPC_UT_NETID_START + idx;
+                net->conf.ul_reload_context = net;
+                net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+                net->conf.callback_context = net;
+                net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+                net->conf.features = 0;
+                result = ipc_attach(&net->conf, &net->handle);
+                if (!result) {
+                    utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+
+            /* Check status : 1 netif is attached */
+            {
+                ipc_query_info_t cnf_query_info;
+                ipc_query_info_t chk_query_info;
+
+                kal_mem_set(&cnf_query_info, 0, sizeof(ipc_query_info_t));
+                kal_mem_set(&chk_query_info, 0, sizeof(ipc_query_info_t));
+
+                ipc_ut_msg_reset(&cnf_query_info, sizeof(ipc_query_info_t), NULL, 0);
+
+                ipc_on_query_info(MOD_IPCORE, NULL);
+
+                if (ipc_ut_msg_chk(MOD_NIL,
+                                   MOD_IPCORE,
+                                   IPCORE_SAP,
+                                   MSG_ID_IPCORE_QUERY_INFO_CNF,
+                                   1) != KAL_TRUE) {
+                    utELOG("IPCore query reply is failed!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Information to check */
+                chk_query_info.netif.netif_cnt = 1;
+                chk_query_info.netif.list[0].netif_id = net->conf.netif_id;
+
+                if (kal_mem_cmp(&(chk_query_info.netif), &(cnf_query_info.netif), sizeof(chk_query_info.netif))) {
+                    utELOG("IPCore query reply content is failed!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+
+            /* Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address. */
+            bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+            bind_req->network_interface_id = net->conf.netif_id;
+            bind_req->pdn_id = IPC_UT_PDN_ID;
+            bind_req->ip_addr.ip_addr_type = ip_types[idx];
+            ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+            free_local_para((local_para_struct *)bind_req);
+
+            /* Check status : 1 netif is attached */
+            {
+                ipc_query_info_t cnf_query_info;
+                ipc_query_info_t chk_query_info;
+
+                kal_mem_set(&cnf_query_info, 0, sizeof(ipc_query_info_t));
+                kal_mem_set(&chk_query_info, 0, sizeof(ipc_query_info_t));
+
+                ipc_ut_msg_reset(&cnf_query_info, sizeof(ipc_query_info_t), NULL, 0);
+
+                ipc_on_query_info(MOD_IPCORE, NULL);
+
+                if (ipc_ut_msg_chk(MOD_NIL,
+                                   MOD_IPCORE,
+                                   IPCORE_SAP,
+                                   MSG_ID_IPCORE_QUERY_INFO_CNF,
+                                   1) != KAL_TRUE) {
+                    utELOG("IPCore query reply is failed!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Information to check */
+                chk_query_info.netif.netif_cnt = 1;
+                chk_query_info.netif.list[0].netif_id = net->conf.netif_id;
+
+                if (kal_mem_cmp(&(chk_query_info.netif), &(cnf_query_info.netif), sizeof(chk_query_info.netif))) {
+                    utELOG("IPCore query reply content is failed!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+
+            /* PDN deactivation. */
+            deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+            deact_req->pdn_id = IPC_UT_PDN_ID;
+            ipc_on_pdn_unbind((local_para_struct *)deact_req);
+            free_local_para((local_para_struct *)deact_req);
+
+            /* Check status : 1 netif is attached */
+            {
+                ipc_query_info_t cnf_query_info;
+                ipc_query_info_t chk_query_info;
+
+                kal_mem_set(&cnf_query_info, 0, sizeof(ipc_query_info_t));
+                kal_mem_set(&chk_query_info, 0, sizeof(ipc_query_info_t));
+
+                ipc_ut_msg_reset(&cnf_query_info, sizeof(ipc_query_info_t), NULL, 0);
+
+                ipc_on_query_info(MOD_IPCORE, NULL);
+
+                if (ipc_ut_msg_chk(MOD_NIL,
+                                   MOD_IPCORE,
+                                   IPCORE_SAP,
+                                   MSG_ID_IPCORE_QUERY_INFO_CNF,
+                                   1) != KAL_TRUE) {
+                    utELOG("IPCore query reply is failed!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Information to check */
+                chk_query_info.netif.netif_cnt = 1;
+                chk_query_info.netif.list[0].netif_id = net->conf.netif_id;
+
+                if (kal_mem_cmp(&(chk_query_info.netif), &(cnf_query_info.netif), sizeof(chk_query_info.netif))) {
+                    utELOG("IPCore query reply content is failed!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+
+            /* ipc_detach(). */
+            result = ipc_detach(net->handle);
+            if (!result) {
+                utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+                return KAL_FALSE;
+            }
+
+            /* After all netif detach, 0 netif is attached */
+            {
+                ipc_query_info_t cnf_query_info;
+                ipc_query_info_t chk_query_info;
+
+                kal_mem_set(&cnf_query_info, 0, sizeof(ipc_query_info_t));
+                kal_mem_set(&chk_query_info, 0, sizeof(ipc_query_info_t));
+
+                ipc_ut_msg_reset(&cnf_query_info, sizeof(ipc_query_info_t), NULL, 0);
+
+                ipc_on_query_info(MOD_IPCORE, NULL);
+
+                if (ipc_ut_msg_chk(MOD_NIL,
+                                   MOD_IPCORE,
+                                   IPCORE_SAP,
+                                   MSG_ID_IPCORE_QUERY_INFO_CNF,
+                                   1) != KAL_TRUE) {
+                    utELOG("IPCore query reply is failed!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Information to check */
+                chk_query_info.netif.netif_cnt = 0;
+
+                if (kal_mem_cmp(&(chk_query_info.netif), &(cnf_query_info.netif), sizeof(chk_query_info.netif))) {
+                    utELOG("IPCore query reply content is failed!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        IPC_UT_PASS();
+        return KAL_TRUE;
+    }
+
+
+kal_bool ipc_ut_ul_reload_retry(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint64          netif_bit_ids;
+    ipc_ut_netif_t     *net;
+    kal_uint32          idx;
+    kal_uint32          cnt;
+    ipc_netif_t        *netif;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+     * Init value test.
+     */
+    netif_bit_ids = ipc_get_all_netif_ul_reload_retry();
+    if (netif_bit_ids) {
+        utELOG("netif_bit_ids is expected to be zero before testing!\r\n");
+        return KAL_FALSE;
+    }
+    ipc_check_ul_reload_retry();
+
+    /*
+     * UL reload retry succeeded case.
+     */
+    for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+        net = &(ipc_ut_nets_s[idx]);
+        netif = (ipc_netif_t *)(net->handle);
+        net->ul_reload_called = KAL_FALSE;
+
+        ipc_set_netif_ul_reload_retry(net->handle, KAL_TRUE);
+        netif_bit_ids = ipc_get_all_netif_ul_reload_retry();
+        if (netif->bit_id != netif_bit_ids) {
+            utELOG("netif UL reload bit_id(%x) != netif_bit_ids(%x)\r\n", netif->bit_id, netif_bit_ids);
+            return KAL_FALSE;
+        }
+
+        ipc_on_retry_ul_reload();
+        if (KAL_FALSE == net->ul_reload_called) {
+            utELOG("netif UL is not called\r\n");
+            return KAL_FALSE;
+        }
+
+        net->ul_reload_called = KAL_FALSE;
+        ipc_set_netif_ul_reload_retry(net->handle, KAL_FALSE);
+        netif_bit_ids = ipc_get_all_netif_ul_reload_retry();
+        if (0 != netif_bit_ids) {
+            utELOG("netif_bit_ids is expected to be zero!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_on_retry_ul_reload();
+        if (KAL_FALSE != net->ul_reload_called) {
+            utELOG("netif UL shall not called\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    /*
+     * UL reload retry failed case.
+     */
+    for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+        net = &(ipc_ut_nets_s[idx]);
+        netif = (ipc_netif_t *)(net->handle);
+        net->need_retry = KAL_TRUE;
+        net->ul_reload_called = KAL_FALSE;
+
+        ipc_set_netif_ul_reload_retry(net->handle, KAL_TRUE);
+        netif_bit_ids = ipc_get_all_netif_ul_reload_retry();
+        if (0 == (netif_bit_ids & netif->bit_id)) {
+            utELOG("netif_bit_ids(%x) doesn't include bit_id(%x)\r\n", netif_bit_ids, netif->bit_id);
+            return KAL_FALSE;
+        }
+    }
+
+    for (cnt = 0; cnt < 2; cnt++) {
+        ipc_on_retry_ul_reload();
+
+        for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+            net = &(ipc_ut_nets_s[idx]);
+
+            if (KAL_FALSE == net->ul_reload_called) {
+                utELOG("netif UL is not called\r\n");
+                return KAL_FALSE;
+            }
+            net->ul_reload_called = KAL_FALSE;
+        }
+    }
+
+    for (idx = 0; idx < IPC_UT_MAX_NET_CNT; idx++) {
+        net = &(ipc_ut_nets_s[idx]);
+        net->need_retry = KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_poll_source(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    // init before test
+    ipc_ut_init();
+
+    ipc_on_lte_tick_source(KAL_TRUE);
+    ipc_on_lte_tick_source(KAL_FALSE);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_pdn_bind_deact(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+     * IPv4 bind negative test.
+     */
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = IPC_UT_BAD_NETIF_ID;
+    bind_req->pdn_id = IPC_UT_PDN_ID;
+    bind_req->ip_addr.ip_addr_type = IPV4_ADDR_TYPE;
+
+    /* Call PDN bind with bad network interface ID "with" source mod = MOD_IPCORE (To trigger Bind response reply) */
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ipc_on_pdn_bind_top(MOD_IPCORE, (local_para_struct *)bind_req);
+    if (ipc_ut_msg_chk(MOD_IPCORE, MOD_IPCORE, IPCORE_SAP ,MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 1) != KAL_TRUE) {
+        utELOG("Bind response is not received\r\n");
+        return KAL_FALSE;
+    }
+
+    /* Call PDN bind with bad network interface ID "without" source mod = MOD_IPCORE (To forbid Bind response reply) */
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+    if (ipc_ut_msg_chk(MOD_IPCORE, MOD_NIL, IPCORE_SAP ,MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 0) != KAL_TRUE) {
+        utELOG("Bind response is received\r\n");
+        return KAL_FALSE;
+    }
+
+    /* Free bind request */
+    free_local_para((local_para_struct *)bind_req);
+
+    /*
+     * IPv4 deact positive test.
+     */
+    ipc_ut_set_error(IPC_UT_NO_ERROR);
+    deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+    deact_req->pdn_id = IPC_UT_PDN_ID;
+
+    ipc_on_pdn_unbind((local_para_struct *)deact_req);
+    free_local_para((local_para_struct *)deact_req);
+    if (IPC_UT_SESSION_DEACTIVATE_NO_SESSION_FOUND != ipc_ut_get_error()) {
+        utELOG("IPv4 deact postive test returns error(%d)\r\n", ipc_ut_get_error());
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_pdn_ip_info(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_bool  result;
+
+    kal_int32 net_ipid;
+
+    kal_uint8 ipv4_valid[4]     = {192, 168, 0, 1};
+    kal_uint8 ipv4_invalid[4]   = {0, 0, 0, 0};
+    kal_uint8 ipv4_dns_1[4]     = {168, 95, 1, 1};
+    kal_uint8 ipv4_dns_2[4]     = {140, 113, 1, 1};
+    kal_uint8 ipv6_valid[16]    = {0x20, 0x01, 0x0d, 0xd8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
+    kal_uint8 ipv6_invalid[16]  = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    kal_uint8 ipv6_dns_1[16]    = {0x20, 0x01, 0x0d, 0xd8, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+    kal_uint8 ipv6_dns_2[16]    = {0x20, 0x01, 0x0d, 0xd8, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+
+    kal_uint8 ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+
+    kal_uint32  ip_type;
+    kal_uint32  ipv4_is_valid;
+    kal_uint32  ipv6_is_valid;
+    kal_uint32  ipv4_dns_cnt;
+    kal_uint32  ipv6_dns_cnt;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+         * ipc_attach()
+         */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_UT_NETID_START;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+       utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+       return KAL_FALSE;
+    }
+
+    for (ip_type = 0; ip_type < sizeof(ip_types)/sizeof(ip_types[0]); ip_type ++)
+    for (ipv4_is_valid = 0 ; ipv4_is_valid < 2 ; ipv4_is_valid ++)
+    for (ipv6_is_valid = 0 ; ipv6_is_valid < 2 ; ipv6_is_valid ++)
+    for (ipv4_dns_cnt = 0 ; ipv4_dns_cnt <= 2 ; ipv4_dns_cnt ++)
+    for (ipv6_dns_cnt = 0 ; ipv6_dns_cnt <= 2 ; ipv6_dns_cnt ++) {
+        kal_uint32 dns_idx;
+
+       utDLOG("iptype(%d) v4valid(%d) v6valid(%d) v4dns(%d) v6dns(%d)\r\n",
+                       ip_type, ipv4_is_valid, ipv6_is_valid, ipv4_dns_cnt, ipv6_dns_cnt);
+       /*
+             * bind
+             */
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[ip_type];
+
+        kal_mem_cpy(bind_req->ip_addr.ipv4, (ipv4_is_valid)?ipv4_valid:ipv4_invalid, sizeof(bind_req->ip_addr.ipv4));
+        kal_mem_cpy(bind_req->ip_addr.ipv6, (ipv6_is_valid)?ipv6_valid:ipv6_invalid, sizeof(bind_req->ip_addr.ipv6));
+
+        for ( dns_idx = 0 ; dns_idx < ipv4_dns_cnt ; dns_idx ++ ) {
+            bind_req->dns.v4[dns_idx].is_dnsv4_present = KAL_TRUE;
+            kal_mem_cpy(bind_req->dns.v4[dns_idx].dnsv4, (dns_idx == 0)?ipv4_dns_1:ipv4_dns_2, sizeof(bind_req->dns.v4[dns_idx].dnsv4));
+        }
+
+        for ( dns_idx = 0 ; dns_idx < ipv6_dns_cnt ; dns_idx ++ ) {
+            bind_req->dns.v6[dns_idx].is_dnsv6_present = KAL_TRUE;
+            kal_mem_cpy(bind_req->dns.v6[dns_idx].dnsv6, (dns_idx == 0)?ipv6_dns_1:ipv6_dns_2, sizeof(bind_req->dns.v6[dns_idx].dnsv6));
+        }
+
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        net_ipid = ipc_get_ip_id(net->handle);
+
+        /* Check */
+        {
+            kal_uint8 ipv4_chk[4];
+            kal_uint8 ipv4_dns_1_chk[4];
+            kal_uint8 ipv4_dns_2_chk[4];
+            kal_uint8 ipv4_dns_cnt_chk;
+            kal_uint8 ipv6_chk[16];
+            kal_uint8 ipv6_iid_len_chk;
+            kal_uint8 ipv6_dns_1_chk[16];
+            kal_uint8 ipv6_dns_2_chk[16];
+            kal_uint8 ipv6_dns_cnt_chk;
+
+            nmu_get_ip4_ip(net_ipid, ipv4_chk);
+
+            nmu_get_ip4_dns_num(net_ipid, &ipv4_dns_cnt_chk);
+            nmu_get_ip4_dns(net_ipid, 0, ipv4_dns_1_chk);
+            nmu_get_ip4_dns(net_ipid, 1, ipv4_dns_2_chk);
+
+            nmu_get_ip6_iid(net_ipid, ipv6_chk);
+            nmu_get_ip6_iid_len(net_ipid, &ipv6_iid_len_chk);
+            nmu_get_ip6_dns_num(net_ipid, &ipv6_dns_cnt_chk);
+            nmu_get_ip6_dns(net_ipid, 0, ipv6_dns_1_chk);
+            nmu_get_ip6_dns(net_ipid, 1, ipv6_dns_2_chk);
+
+            if ((IPV6_ADDR_TYPE == ip_types[ip_type]) || (IPV4V6_ADDR_TYPE == ip_types[ip_type])) {
+                kal_uint32 idx;
+                if (ipv6_is_valid) {
+                    if (kal_mem_cmp(ipv6_chk, ipv6_valid, sizeof(ipv6_chk))) {
+                        utELOG("IPv6 IID check error!\r\n");
+                        return KAL_FALSE;
+                    }
+                }
+                if (((ipv6_is_valid)?IPV6_VALID_IID_BITS:0) != ipv6_iid_len_chk) {
+                    utELOG("IPv6 IID length check error!\r\n");
+                    return KAL_FALSE;
+                }
+                if (ipv6_dns_cnt_chk != ipv6_dns_cnt) {
+                    utELOG("IPv6 DNS count check error!\r\n");
+                    return KAL_FALSE;
+                }
+
+                for ( idx = 0 ; idx < ipv6_dns_cnt_chk ; idx ++ ) {
+                    if ((idx == 0) && kal_mem_cmp(ipv6_dns_1_chk, ipv6_dns_1, sizeof(ipv6_dns_1_chk))) {
+                        utELOG("IPv6 DNS address 1 check error!\r\n");
+                        return KAL_FALSE;
+                    }
+                    if ((idx == 1) && kal_mem_cmp(ipv6_dns_2_chk, ipv6_dns_2, sizeof(ipv6_dns_2_chk))) {
+                        utELOG("IPv6 DNS address 2 check error!\r\n");
+                        return KAL_FALSE;
+                    }
+                }
+                if (nmu_check_ip6_up(net_ipid) != ((ipv6_is_valid)?KAL_TRUE:KAL_FALSE)) {
+                    utELOG("nmu_check_ip6_up() check error!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+
+            if ((IPV4_ADDR_TYPE == ip_types[ip_type]) || (IPV4V6_ADDR_TYPE == ip_types[ip_type])) {
+                kal_uint32 idx;
+                if (kal_mem_cmp(ipv4_chk, (ipv4_is_valid)?ipv4_valid:ipv4_invalid, sizeof(ipv4_chk))) {
+                    utELOG("IPv4 address check error!\r\n");
+                    return KAL_FALSE;
+                }
+                if (ipv4_dns_cnt_chk != ipv4_dns_cnt) {
+                    utELOG("IPv4 DNS count check error!\r\n");
+                    return KAL_FALSE;
+                }
+
+                for ( idx = 0 ; idx < ipv4_dns_cnt_chk ; idx ++ ) {
+                    if ((idx == 0) && kal_mem_cmp(ipv4_dns_1_chk, ipv4_dns_1, sizeof(ipv4_dns_1_chk))) {
+                        utELOG("IPv4 DNS address 1 check error!\r\n");
+                        return KAL_FALSE;
+                    }
+                    if ((idx == 1) && kal_mem_cmp(ipv4_dns_2_chk, ipv4_dns_2, sizeof(ipv4_dns_2_chk))) {
+                        utELOG("IPv4 DNS address 2 check error!\r\n");
+                        return KAL_FALSE;
+                    }
+                }
+                if (nmu_check_ip4_up(net_ipid) != ((ipv4_is_valid)?KAL_TRUE:KAL_FALSE)) {
+                    utELOG("nmu_check_ip4_up() check error!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /* Detach */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* Check */
+        {
+            if ((IPV6_ADDR_TYPE == ip_types[ip_type]) || (IPV4V6_ADDR_TYPE == ip_types[ip_type])) {
+                if (nmu_check_ip6_up(net_ipid) != KAL_FALSE) {
+                    utELOG("nmu_check_ip6_up() check error!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+
+            if ((IPV4_ADDR_TYPE == ip_types[ip_type]) || (IPV4V6_ADDR_TYPE == ip_types[ip_type])) {
+                if (nmu_check_ip4_up(net_ipid) != KAL_FALSE) {
+                    utELOG("nmu_check_ip4_up() check error!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+    }
+
+    /*
+        * ipc_detach().
+        */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+
+kal_bool ipc_ut_triggered_ul_reload(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool          result;
+
+    // init before test
+    ipc_ut_init();
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /*
+                * ipc_attach()
+                */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = 0;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                *   Request for UL GPD reload before PDN binding : It should success
+                */
+        net->need_retry = KAL_FALSE;
+        net->ul_reload_called = KAL_FALSE;
+        ipc_need_ul_reload(net->handle);
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (KAL_TRUE != net->ul_reload_called) {
+            utELOG("ipc_need_ul_reload() does not call callback!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+                */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        /*
+                *   Request for UL GPD reload : It should success
+                */
+        net->need_retry = KAL_FALSE;
+        net->ul_reload_called = KAL_FALSE;
+        ipc_need_ul_reload(net->handle);
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (KAL_TRUE != net->ul_reload_called) {
+            utELOG("ipc_need_ul_reload() does not call callback!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                * PDN deactivation.
+                */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /*
+                *   Request for UL GPD reload after PDN deactivation : It should success
+                */
+        net->need_retry = KAL_FALSE;
+        net->ul_reload_called = KAL_FALSE;
+        ipc_need_ul_reload(net->handle);
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (KAL_TRUE != net->ul_reload_called) {
+            utELOG("ipc_need_ul_reload() does not call callback!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                * ipc_detach().
+                */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_downlink_wo_dhcp4c(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool          result;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /*
+                * ipc_attach()
+                */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = 0;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+         /*
+                *   Simulate DL traffic to IPCore : Before PDN binding, all GPDs should be silently dropped by IPCore and NO callback is triggered
+                */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+            kal_uint32  alignment;
+            kal_uint32  unite;
+            kal_uint32  spd;
+            kal_uint32  spd_igr_bit;
+            kal_uint32  spd_position;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (spd = 0; spd < 1; spd++)
+            for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+            for (spd_position = 0; spd_position < 3; spd_position++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            (unite == 0)?0:10,
+                                            alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            NULL,
+                                            NULL,
+                                            spd,
+                                            spd_igr_bit,
+                                            spd_position);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink(IPC_UT_PDN_ID, head_gpd, tail_gpd);
+
+                if ( (0 != ipc_ut_dl_callback_gpd_cnt) ||
+                     (0 != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                    utELOG("DL GPD is forwarded before PDN binding! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+                * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+                */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+         /*
+                *   Simulate DL traffic to IPCore : All GPDs should be forward to DL callback regardless of IP types (IPv4/IPv6)
+                */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+            kal_uint32  alignment;
+            kal_uint32  unite;
+            kal_uint32  spd;
+            kal_uint32  spd_igr_bit;
+            kal_uint32  spd_position;
+            kal_uint32  total_cnt;
+            kal_uint32  spd_payload_cnt;
+            kal_uint32  i;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (spd = 0; spd < 1; spd++)
+            for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+            for (spd_position = 0; spd_position < 3; spd_position++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            (unite == 0)?0:10,
+                                            alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            NULL,
+                                            NULL,
+                                            spd,
+                                            spd_igr_bit,
+                                            spd_position);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink(IPC_UT_PDN_ID, head_gpd, tail_gpd);
+
+                if (1 == spd) {
+                    total_cnt = ipv4_cnt + ipv6_cnt + 1/*spd*/;
+                    spd_payload_cnt = ipv4_cnt + ipv6_cnt;
+                    if (1 == spd_igr_bit) {
+                        kal_uint32 igr_payload_cnt = 0;
+                        for (i = 0; i < (ipv4_cnt + ipv6_cnt); i++) {
+                            igr_payload_cnt += ipc_ut_spd_packet_igr_s[i];
+                        }
+                        if ((ipv4_cnt + ipv6_cnt) == igr_payload_cnt) {
+                            /* All SPD's payloads has been ignored. */
+                            total_cnt--;
+                            spd_payload_cnt = 0;
+                        } else {
+                            spd_payload_cnt -= igr_payload_cnt;
+                        }
+                    }
+                } else {
+                    total_cnt = ipv4_cnt + ipv6_cnt;
+                    spd_payload_cnt = 0;
+                }
+
+                if ( (total_cnt != ipc_ut_dl_callback_gpd_cnt) ||
+                     (spd_payload_cnt != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                    utELOG("DL GPD is NOT forwarded to bound handler! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                    ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                    return KAL_FALSE;
+                }
+
+                /* DL callback is correctly called : all GPDs are released */
+            }
+        }
+
+        /*
+                * PDN deactivation.
+                */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+         /*
+                *   Simulate DL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered
+                */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+            kal_uint32  alignment;
+            kal_uint32  unite;
+            kal_uint32  spd;
+            kal_uint32  spd_igr_bit;
+            kal_uint32  spd_position;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (spd = 0; spd < 1; spd++)
+            for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+            for (spd_position = 0; spd_position < 3; spd_position++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            (unite == 0)?0:10,
+                                            alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            NULL,
+                                            NULL,
+                                            spd,
+                                            spd_igr_bit,
+                                            spd_position);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink(IPC_UT_PDN_ID, head_gpd, tail_gpd);
+
+                if ( (0 != ipc_ut_dl_callback_gpd_cnt) ||
+                     (0 != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                    utELOG("DL GPD is forwarded after PDN deactivation! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+                * ipc_detach().
+                */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_downlink_w_dhcp4c(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool          result;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /*
+                * ipc_attach()
+                */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = IPC_F_DHCP4C;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+         /*
+                *   Simulate DL traffic to IPCore : Before PDN binding, all GPDs should be silently dropped by IPCore and NO callback is triggered
+                */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+            kal_uint32  alignment;
+            kal_uint32  unite;
+            kal_uint32  spd;
+            kal_uint32  spd_igr_bit;
+            kal_uint32  spd_position;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (spd = 0; spd < 1; spd++)
+            for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+            for (spd_position = 0; spd_position < 3; spd_position++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+                utDLOG("@ [Before Bind] uni(%d),align(%d),v4_cnt(%d),v6_cnt(%d)\r\n", unite, alignment, ipv4_cnt, ipv6_cnt);
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            (unite == 0)?0:10,
+                                            alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            NULL,
+                                            NULL,
+                                            spd,
+                                            spd_igr_bit,
+                                            spd_position);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink(IPC_UT_PDN_ID, head_gpd, tail_gpd);
+
+                if ( (0 != ipc_ut_dl_callback_gpd_cnt) ||
+                     (0 != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                    utELOG("DL GPD is forwarded before PDN binding! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+                * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+                */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        /*
+                *   Simulate DL traffic to IPCore
+                *
+                *   - 1st IPv4 GPD is IPv4 DHCP packet and will be sent to DHCP4C module
+                *   - All other GPDs should be forward to DL callback regardless of IP types (IPv4/IPv6)
+                *
+                */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+            kal_uint32  alignment;
+            kal_uint32  unite;
+            kal_uint32  spd;
+            kal_uint32  spd_igr_bit;
+            kal_uint32  spd_position;
+            kal_uint32  total_cnt;
+            kal_uint32  spd_payload_cnt;
+            kal_uint32  i;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (spd = 0; spd < 1; spd++)
+            for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+            for (spd_position = 0; spd_position < 3; spd_position++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+                utDLOG("@ [Binded] uni(%d),align(%d),v4_cnt(%d),v6_cnt(%d)\r\n", unite, alignment, ipv4_cnt, ipv6_cnt);
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            (unite == 0)?0:10,
+                                            alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            NULL,
+                                            NULL,
+                                            spd,
+                                            spd_igr_bit,
+                                            spd_position);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink(IPC_UT_PDN_ID, head_gpd, tail_gpd);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if  (   (ipv4_cnt > 0) &&
+                        /* DHCPv4 is only enabled for IPv4 related session */
+                        ((ip_types[idx] == IPV4_ADDR_TYPE) ||
+                            (ip_types[idx] == IPV4V6_ADDR_TYPE))   ) {
+                    /* Least 1 IPv4 DHCP packet : this packet will be forwarded to DHCP4C module instead of sending to DL network interface */
+                    if (1 == spd) {
+                        if ((1 == ipv4_cnt) && (0 == ipv6_cnt)) {
+                            total_cnt = 0;
+                            spd_payload_cnt = 0;
+                        } else {
+                            total_cnt = ipv4_cnt + ipv6_cnt + 1/*spd*/ - 1/*dhcp4c*/;
+                            spd_payload_cnt = ipv4_cnt + ipv6_cnt - 1/*dhcp4c*/;
+                            if (1 == spd_igr_bit) {
+                                /* the first packet would be filtered out, so add the duplicate substration back. */
+                                spd_payload_cnt++;
+
+                                if (1 == spd_igr_bit) {
+                                    kal_uint32 igr_payload_cnt = 0;
+                                    for (i = 0; i < (ipv4_cnt + ipv6_cnt); i++) {
+                                        igr_payload_cnt += ipc_ut_spd_packet_igr_s[i];
+                                    }
+                                    if ((ipv4_cnt + ipv6_cnt) == igr_payload_cnt) {
+                                        /* All SPD's payloads has been ignored. */
+                                        total_cnt--;
+                                        spd_payload_cnt = 0;
+                                    } else {
+                                        spd_payload_cnt -= igr_payload_cnt;
+                                    }
+                                }
+                            }
+                        }
+                    } else {
+                        total_cnt = ipv4_cnt + ipv6_cnt - 1/*dhcp4c*/;
+                        spd_payload_cnt = 0;
+                    }
+                    if ( (total_cnt != ipc_ut_dl_callback_gpd_cnt) ||
+                         (spd_payload_cnt != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                        utELOG("DL GPD is NOT forwarded to bound handler or DHCP handling is failed! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                        return KAL_FALSE;
+                    }
+                } else {
+                    /* All GPDs should be handled by DL network interface */
+                    if (1 == spd) {
+                        total_cnt = ipv4_cnt + ipv6_cnt + 1/*spd*/;
+                        spd_payload_cnt = ipv4_cnt + ipv6_cnt;
+                        if (1 == spd_igr_bit) {
+                            kal_uint32 igr_payload_cnt = 0;
+                            for (i = 0; i < (ipv4_cnt + ipv6_cnt); i++) {
+                                igr_payload_cnt += ipc_ut_spd_packet_igr_s[i];
+                            }
+                            if ((ipv4_cnt + ipv6_cnt) == igr_payload_cnt) {
+                                /* All SPD's payloads has been ignored. */
+                                total_cnt--;
+                                spd_payload_cnt = 0;
+                            } else {
+                                spd_payload_cnt -= igr_payload_cnt;
+                            }
+                        }
+                    } else {
+                        total_cnt = ipv4_cnt + ipv6_cnt;
+                        spd_payload_cnt = 0;
+                    }
+                    if ( (total_cnt != ipc_ut_dl_callback_gpd_cnt) ||
+                         (spd_payload_cnt != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                        utELOG("DL GPD is NOT forwarded to bound handler! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                        return KAL_FALSE;
+                    }
+                }
+                /* DL callback or DHCP4C indication are correctly called : all GPDs should be released */
+            }
+        }
+
+        /*
+                * PDN deactivation.
+                */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+         /*
+                *   Simulate DL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered
+                */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+            kal_uint32  alignment;
+            kal_uint32  unite;
+            kal_uint32  spd;
+            kal_uint32  spd_igr_bit;
+            kal_uint32  spd_position;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (spd = 0; spd < 1; spd++)
+            for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+            for (spd_position = 0; spd_position < 3; spd_position++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+                utDLOG("@ [Deactivated] uni(%d),align(%d),v4_cnt(%d),v6_cnt(%d)\r\n", unite, alignment, ipv4_cnt, ipv6_cnt);
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            (unite == 0)?0:10,
+                                            alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            NULL,
+                                            NULL,
+                                            spd,
+                                            spd_igr_bit,
+                                            spd_position);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink(IPC_UT_PDN_ID, head_gpd, tail_gpd);
+
+                if ( (0 != ipc_ut_dl_callback_gpd_cnt) ||
+                     (0 != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                    utELOG("DL GPD is forwarded after PDN deactivation! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+                * ipc_detach().
+                */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+kal_bool ipc_ut_downlink_invalid_packet(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool          result;
+    kal_uint16 ipv4_pkt_len[IPC_UT_INVALID_PKT_CASE][IPC_UT_INVALID_PKT_CNT] = {{IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, 0, 0, IPC_INVALID_PKT_LEN3},// first invalid & last invalid
+                                  {0, IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, 0, 0},// first valid & last valid
+                                  {IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3},// all invalid
+                                  {0, 0, 0, 0, 0},// all valid
+                                  {IPC_INVALID_PKT_LEN3, 0, 0, 0, 0}};// first valid
+    kal_uint16 ipv6_pkt_len[IPC_UT_INVALID_PKT_CASE][IPC_UT_INVALID_PKT_CNT] = {{IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, 0, 0, IPC_INVALID_PKT_LEN3},// first invalid & last invalid
+                                  {0, IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, 0, 0},// first valid & last valid
+                                  {IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3, IPC_INVALID_PKT_LEN3},// all invalid
+                                  {0, 0, 0, 0, IPC_INVALID_PKT_LEN3},// last invalid
+                                  {0, 0, 0, 0, 0}};// all valid
+    kal_uint8 case_cnt, valid_cnt, len_cnt;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /*
+                * ipc_attach()
+                */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = 0;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+
+        /*
+                * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+                */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+         /*
+                *   Simulate DL traffic to IPCore : All GPDs should be forward to DL callback regardless of IP types (IPv4/IPv6)
+                */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+
+            ipv4_cnt = ipv6_cnt = 5;
+
+            for (case_cnt = 0; case_cnt<IPC_UT_INVALID_PKT_CASE; case_cnt++) {
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            0,//(unite == 0)?0:10,
+                                            0,//alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            ipv4_pkt_len[case_cnt],
+                                            ipv6_pkt_len[case_cnt],
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            0);
+
+                valid_cnt = 0;
+                for (len_cnt = 0; len_cnt<ipv4_cnt ; len_cnt++) {
+                    if (ipv4_pkt_len[case_cnt][len_cnt] <= 1500) {
+                      valid_cnt++;
+                    }
+                }
+                for (len_cnt = 0; len_cnt<ipv6_cnt ; len_cnt++) {
+                    if (ipv6_pkt_len[case_cnt][len_cnt] <= 1500) {
+                      valid_cnt++;
+                    }
+                }
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink(IPC_UT_PDN_ID, head_gpd, tail_gpd);
+
+                if ( (valid_cnt != ipc_ut_dl_callback_gpd_cnt) ) {
+                    utELOG("DL GPD is NOT forwarded to bound handler!\r\n");
+                    ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                    return KAL_FALSE;
+                }
+                /* DL callback is correctly called : all GPDs are released */
+            }
+        }
+
+        /*
+                * PDN deactivation.
+                */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /*
+                * ipc_detach().
+                */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+#endif
+
+kal_bool ipc_ut_uplink_filter(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32                          callback_with_info;
+    kal_uint32                          idx;
+    ipc_ut_netif_t                      *net;
+    ipcore_upcm_pdn_bind_ind_struct     *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct    *deact_req;
+    kal_uint8                           ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool                            result;
+    kal_uint32                          ipv4_cnt;
+    kal_uint32                          ipv6_cnt;
+    kal_uint32                          ipv4_filter_cnt;
+    kal_uint32                          ipv6_filter_cnt;
+    kal_uint32                          with_wildcard;
+    kal_uint32                          with_bwm;
+    kal_uint8                           matched_filter_idx_v4;
+    kal_uint8                           matched_filter_idx_v6;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 4; ipv4_cnt+=2)
+    for (ipv6_cnt = 0; ipv6_cnt <= 4; ipv6_cnt+=2)
+    for (ipv4_filter_cnt = 0; ipv4_filter_cnt <= 4; ipv4_filter_cnt+=4)
+    for (ipv6_filter_cnt = 0; ipv6_filter_cnt <= 4; ipv6_filter_cnt+=4)
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++)
+    for (with_wildcard = 0; with_wildcard < 2; with_wildcard++)
+    for (with_bwm = 0; with_bwm < 2; with_bwm++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < ipv4_filter_cnt; matched_filter_idx_v4++)
+    for (matched_filter_idx_v6 = 0; matched_filter_idx_v6 < ipv6_filter_cnt; matched_filter_idx_v6++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+        utDLOG("ifo(%d) v4Cnt(%d) v6Cnt(%d) v4FltCnt(%d) v6FltCnt(%d) withWC(%d) withBWM(%d) IPType(%d) v4Idx(%d) v6Idx(%d)\r\n",
+                        callback_with_info, ipv4_cnt, ipv6_cnt, ipv4_filter_cnt , ipv6_filter_cnt, with_wildcard, with_bwm, idx, matched_filter_idx_v4, matched_filter_idx_v6);
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+
+        /* Install UL filter for each test loop */
+        ipc_ut_install_ul_filters(callback_with_info, KAL_TRUE, ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm, matched_filter_idx_v4, matched_filter_idx_v6, IPC_UT_NETID_START);
+
+        /*
+                * ipc_attach()
+                */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = 0;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+            return KAL_FALSE;
+        }
+
+        /*
+                * Before activate, the UL packet from this network interface
+                *   1. CAN be filtered out
+                *   2. CAN NOT be forwarded to UPCM
+                */
+        {
+            kal_uint32          dhcpv4_idx;
+            kal_uint32          dhcpv6_idx;
+            qbm_gpd             *head_gpd;
+            qbm_gpd             *tail_gpd;
+            ipc_io_request_t    *ior;
+
+            for (dhcpv4_idx = 0 ; ((ipv4_cnt == 0 && dhcpv4_idx == 0) || (dhcpv4_idx < ipv4_cnt)) ; dhcpv4_idx+=2)
+            for (dhcpv6_idx = 0 ; ((ipv6_cnt == 0 && dhcpv6_idx == 0) || (dhcpv6_idx < ipv6_cnt)) ; dhcpv6_idx+=2) {
+                kal_uint32 expected_ul_v4_filter_out_cnt;
+                kal_uint32 expected_ul_v6_filter_out_cnt;
+                kal_uint32 expected_ul_filter_out_cnt;
+
+                utDLOG("@ Before activation : dhcpv4Idx(%d), dhcpv6Idx(%d)\r\n",
+                                dhcpv4_idx, dhcpv6_idx);
+
+
+                ipc_ut_prepare_ul_gpd_list(KAL_TRUE,
+                                            ipv4_cnt, dhcpv4_idx,
+                                            ipv6_cnt, dhcpv6_idx,
+                                            &head_gpd, &tail_gpd, &ior);
+
+                if (NULL == ior) {
+                    utELOG("UL packet prepare failed!\r\r");
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_ul_filter_info();
+
+                ipc_uplink(net->handle, ior);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                /*
+                             *  1. If least 1 IPv4 filter rule & 1 IPv4 gpd -> least 1 packet (DHCPv4) will be filtered out
+                             *  2. If least 1 IPv6 filter rule & 1 IPv6 gpd -> least 1 packet (DHCPv6) will be filtered out
+                             *  3. NO any packet will been forwarded to network before PDN bind
+                             */
+                if (with_wildcard) {
+                    expected_ul_v4_filter_out_cnt = ipv4_cnt - (((ipv4_cnt > 0) && with_bwm)?1:0);
+                    expected_ul_v6_filter_out_cnt = ipv6_cnt - (((ipv6_cnt > 0) && with_bwm)?1:0);
+                } else {
+                    expected_ul_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                      (ipv4_cnt > 0) &&
+                                                      (!with_bwm) )? 1:0;
+                    expected_ul_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                      (ipv6_cnt > 0) &&
+                                                      (!with_bwm) )?1:0;
+                }
+                expected_ul_filter_out_cnt = expected_ul_v4_filter_out_cnt + expected_ul_v6_filter_out_cnt;
+
+                if (callback_with_info && expected_ul_filter_out_cnt > 0) {
+                    if (ipc_ut_ul_filter_info.netif_id != net->conf.netif_id) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != ipc_get_ip_id(net->handle)) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                } else {
+                    if (ipc_ut_ul_filter_info.netif_id != 0) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != -1) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                }
+
+                if (ipc_ut_ul_filter_gpd_cnt != expected_ul_filter_out_cnt) {
+                    utELOG("Filtered-out gpd count is incorrect!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                if (ipc_ut_ul_gpd_cnt > 0) {
+                    utELOG("GPD is forwarded to network before valid PDN binding!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+                * Activate IPv4/IPv4v6/IPv6 PDN
+                *
+                */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        /*
+                * After PDN binding activate, the UL packet from this network interface
+                *   1. CAN be filtered out
+                *   2. CAN be forwarded to UPCM
+                */
+        {
+            kal_uint32          dhcpv4_idx;
+            kal_uint32          dhcpv6_idx;
+            qbm_gpd             *head_gpd;
+            qbm_gpd             *tail_gpd;
+            ipc_io_request_t    *ior;
+
+            for (dhcpv4_idx = 0 ; ((ipv4_cnt == 0 && dhcpv4_idx == 0) || (dhcpv4_idx < ipv4_cnt)) ; dhcpv4_idx+=2)
+            for (dhcpv6_idx = 0 ; ((ipv6_cnt == 0 && dhcpv6_idx == 0) || (dhcpv6_idx < ipv6_cnt)) ; dhcpv6_idx+=2) {
+                kal_uint32 expected_ul_v4_filter_out_cnt;
+                kal_uint32 expected_ul_v6_filter_out_cnt;
+                kal_uint32 expected_ul_filter_out_cnt;
+                kal_uint32 expected_ul_cnt;
+
+                utDLOG("@ PDN connected : dhcpv4Idx(%d), dhcpv6Idx(%d)\r\n",
+                                dhcpv4_idx, dhcpv6_idx);
+
+                ipc_ut_prepare_ul_gpd_list(KAL_TRUE,
+                                            ipv4_cnt, dhcpv4_idx,
+                                            ipv6_cnt, dhcpv6_idx,
+                                            &head_gpd, &tail_gpd, &ior);
+
+                if (NULL == ior) {
+                    utELOG("UL packet prepare failed!\r\r");
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_ul_filter_info();
+
+                ipc_uplink(net->handle, ior);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                /*
+                             *  1. If least 1 IPv4 filter rule & 1 IPv4 gpd -> least 1 packet (DHCPv4) will be filtered out
+                             *  2. If least 1 IPv6 filter rule & 1 IPv6 gpd -> least 1 packet (DHCPv6) will be filtered out
+                             *  3. All non-filtered GPDs with matched IP type will been forwarded to network
+                             */
+                if (with_wildcard) {
+                    expected_ul_v4_filter_out_cnt = ipv4_cnt - (((ipv4_cnt > 0) && with_bwm)?1:0);
+                    expected_ul_v6_filter_out_cnt = ipv6_cnt - (((ipv6_cnt > 0) && with_bwm)?1:0);
+                } else {
+                    expected_ul_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                      (ipv4_cnt > 0) &&
+                                                      (!with_bwm) )? 1:0;
+                    expected_ul_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                      (ipv6_cnt > 0) &&
+                                                      (!with_bwm) )?1:0;
+                }
+                expected_ul_filter_out_cnt = expected_ul_v4_filter_out_cnt + expected_ul_v6_filter_out_cnt;
+
+                if (callback_with_info && expected_ul_filter_out_cnt > 0) {
+                    if (ipc_ut_ul_filter_info.netif_id != net->conf.netif_id) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != ipc_get_ip_id(net->handle)) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                } else {
+                    if (ipc_ut_ul_filter_info.netif_id != 0) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != -1) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                }
+
+                if (ipc_ut_ul_filter_gpd_cnt != expected_ul_filter_out_cnt) {
+                    utELOG("Filtered-out gpd count is incorrect!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                expected_ul_cnt =   (bind_req->ip_addr.ip_addr_type == IPV4_ADDR_TYPE)?(ipv4_cnt - expected_ul_v4_filter_out_cnt):
+                                    (bind_req->ip_addr.ip_addr_type == IPV6_ADDR_TYPE)?(ipv6_cnt - expected_ul_v6_filter_out_cnt):
+                                    ((ipv4_cnt + ipv6_cnt) - (expected_ul_filter_out_cnt));
+
+                if (ipc_ut_ul_gpd_cnt != expected_ul_cnt) {
+                    utELOG("GPD is not forwarded to network correctly!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+                if ((expected_ul_cnt > 0) &&
+                    (ipc_ut_ul_pdn_id != bind_req->pdn_id)) {
+                    utELOG("GPD is not forwarded to correct network PDN!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+                * PDN deactivation.
+                */
+
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /*
+                * After deactivate, the UL packet from this network interface
+                *   1. CAN be filtered out
+                *   2. CAN NOT be forwarded to UPCM
+                */
+        {
+            kal_uint32          dhcpv4_idx;
+            kal_uint32          dhcpv6_idx;
+            qbm_gpd             *head_gpd;
+            qbm_gpd             *tail_gpd;
+            ipc_io_request_t    *ior;
+
+            for (dhcpv4_idx = 0 ; ((ipv4_cnt == 0 && dhcpv4_idx == 0) || (dhcpv4_idx < ipv4_cnt)) ; dhcpv4_idx+=2)
+            for (dhcpv6_idx = 0 ; ((ipv6_cnt == 0 && dhcpv6_idx == 0) || (dhcpv6_idx < ipv6_cnt)) ; dhcpv6_idx+=2) {
+                kal_uint32 expected_ul_v4_filter_out_cnt;
+                kal_uint32 expected_ul_v6_filter_out_cnt;
+                kal_uint32 expected_ul_filter_out_cnt;
+
+                utDLOG("@ After deactivation : dhcpv4Idx(%d), dhcpv6Idx(%d)\r\n",
+                                dhcpv4_idx, dhcpv6_idx);
+
+                ipc_ut_prepare_ul_gpd_list(KAL_TRUE,
+                                            ipv4_cnt, dhcpv4_idx,
+                                            ipv6_cnt, dhcpv6_idx,
+                                            &head_gpd, &tail_gpd, &ior);
+
+                if (NULL == ior) {
+                    utELOG("UL packet prepare failed!\r\r");
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_ul_filter_info();
+
+                ipc_uplink(net->handle, ior);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                /*
+                             *  1. If least 1 IPv4 filter rule & 1 IPv4 gpd -> least 1 packet (DHCPv4) will be filtered out
+                             *  2. If least 1 IPv6 filter rule & 1 IPv6 gpd -> least 1 packet (DHCPv6) will be filtered out
+                             *  3. NO any packet will been forwarded to network after PDN deactivation
+                             */
+                if (with_wildcard) {
+                    expected_ul_v4_filter_out_cnt = ipv4_cnt - (((ipv4_cnt > 0) && with_bwm)?1:0);
+                    expected_ul_v6_filter_out_cnt = ipv6_cnt - (((ipv6_cnt > 0) && with_bwm)?1:0);
+                } else {
+                    expected_ul_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                      (ipv4_cnt > 0) &&
+                                                      (!with_bwm) )? 1:0;
+                    expected_ul_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                      (ipv6_cnt > 0) &&
+                                                      (!with_bwm) )?1:0;
+                }
+                expected_ul_filter_out_cnt = expected_ul_v4_filter_out_cnt + expected_ul_v6_filter_out_cnt;
+
+                if (callback_with_info && expected_ul_filter_out_cnt > 0) {
+                    if (ipc_ut_ul_filter_info.netif_id != net->conf.netif_id) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != ipc_get_ip_id(net->handle)) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                } else {
+                    if (ipc_ut_ul_filter_info.netif_id != 0) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != -1) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                }
+
+                if (ipc_ut_ul_filter_gpd_cnt != expected_ul_filter_out_cnt) {
+                    utELOG("Filtered-out gpd count is incorrect!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                if (ipc_ut_ul_gpd_cnt > 0) {
+                    utELOG("GPD is forwarded to network before valid PDN binding!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+                * ipc_detach().
+                */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+            return KAL_FALSE;
+        }
+
+
+        /* Uninstall UL filters after test procedure */
+        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_link_notification(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32                          idx;
+    ipc_ut_netif_t                      *net;
+    kal_uint8                           ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool                            result;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    {
+        kal_uint32 link_update;
+        kal_uint32 is_up;
+
+        /*
+                * ipc_attach()
+                */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = 0;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                *   Notifiy Link change for attached network interface : Trigger IPCORE to send ILM
+                */
+        for (link_update = 0 ; link_update < 2 ; link_update ++)
+        for (is_up = 0 ; is_up < 2 ; is_up ++)
+        for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+            msg_type message_type;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+
+            ipc_notify_link_change(net->conf.netif_id,
+                                    ip_types[idx],
+                                    link_update?KAL_TRUE:KAL_FALSE,
+                                    is_up?KAL_TRUE:KAL_FALSE);
+
+            if (link_update) {   /* To update Link status */
+                message_type    = is_up ? MSG_ID_IPCORE_LINK_UP_REQ : MSG_ID_IPCORE_LINK_DOWN_REQ;
+            } else {   /* To update IP status */
+                message_type    = is_up ? MSG_ID_IPCORE_IP_UP_REQ : MSG_ID_IPCORE_IP_DOWN_REQ;
+            }
+
+            if (ipc_ut_msg_chk( MOD_IPCORE,
+                                net->conf.module_id,
+                                IPCORE_SAP,
+                                message_type,
+                                1) != KAL_TRUE) {
+                utELOG("Link notification check failed!\r\n");
+                return KAL_FALSE;
+            }
+        }
+
+        /*
+                *   Notifiy Link change for non-attached network interface : Trigger nothing
+                */
+        for (link_update = 0 ; link_update < 2 ; link_update ++)
+        for (is_up = 0 ; is_up < 2 ; is_up ++)
+        for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+            msg_type message_type;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+
+            ipc_notify_link_change(net->conf.netif_id + 1 /* netif which is not attached to IPCORE */,
+                                    ip_types[idx],
+                                    link_update?KAL_TRUE:KAL_FALSE,
+                                    is_up?KAL_TRUE:KAL_FALSE);
+
+            if (link_update) {   /* To update Link status */
+                message_type    = is_up ? MSG_ID_IPCORE_LINK_UP_REQ : MSG_ID_IPCORE_LINK_DOWN_REQ;
+            } else {   /* To update IP status */
+                message_type    = is_up ? MSG_ID_IPCORE_IP_UP_REQ : MSG_ID_IPCORE_IP_DOWN_REQ;
+            }
+
+            if (ipc_ut_msg_chk( 0,
+                                0,
+                                0,
+                                0,
+                                0) != KAL_TRUE) {
+                utELOG("Link notification check failed!\r\n");
+                return KAL_FALSE;
+            }
+        }
+
+        /*
+                * ipc_detach().
+                */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+
+kal_bool ipc_ut_link_status_ind(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32                          idx;
+    kal_uint32                          linkChangeTestIdx;
+    ipc_ut_netif_t                      *net;
+    ipcore_upcm_pdn_bind_ind_struct     *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct    *deact_req;
+    kal_uint8                           ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool                            result;
+    kal_int32                           orgIlmCnt;
+    kal_int32                           ip_id;
+    kal_int32                           set_ntfy_module;
+    kal_int32                           ntfy_cnt;
+    kal_int32                           ntfy_dereg_cnt;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (set_ntfy_module = 0 ; set_ntfy_module < 2 ; set_ntfy_module ++)
+    for (ntfy_cnt = 0 ; ntfy_cnt < IPC_MAX_NTFY_CNT + 2 ; ntfy_cnt ++)
+    for (ntfy_dereg_cnt = 0 ; ntfy_dereg_cnt <= ntfy_cnt ; ntfy_dereg_cnt ++)
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        kal_int32 ntfy_entry_cnt;
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        utDLOG("set_ntfy_md %d ntfy_cnt %d ntfy_dereg_cnt %d idx %d\r\n", set_ntfy_module, ntfy_cnt, ntfy_dereg_cnt, idx);
+
+        /*
+                * Configure notification setting
+                */
+        if (set_ntfy_module) {
+            ipc_register_link_up_ind_handler(MOD_IPCORE);
+        } else {
+            ipc_deregister_link_up_ind_handler();
+        }
+
+        ipc_ut_ntfy_reset_info();
+        if (ipc_ut_ntfy_registration(ntfy_cnt) != KAL_TRUE) {
+            utELOG("ipc_ut_ntfy_registration() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+        ipc_ut_ntfy_deregistration(KAL_FALSE, ntfy_dereg_cnt, &ntfy_entry_cnt);
+
+        /*
+                * Before any network interface attachment : trigger link change to test original ILM count
+                */
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ipc_ut_ntfy_reset_param();
+        ipc_notify_all_netif_link_change(ip_types[idx], KAL_TRUE);
+        orgIlmCnt = ipc_ut_msg_sent._trigger_cnt;
+
+        /*
+                * ipc_attach()
+                */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = 0;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                * Activate IPv4/IPv4v6/IPv6 PDN
+                * - Link-UP should be called
+                *
+                */
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ipc_ut_ntfy_reset_param();
+
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        ip_id = ipc_get_ip_id(net->handle);
+
+        /* LINK-UP */
+        if (ipc_ut_msg_chk( MOD_IPCORE,
+                            net->conf.module_id,
+                            IPCORE_SAP,
+                            MSG_ID_IPCORE_LINK_UP_REQ,
+                            1) != KAL_TRUE) {
+            utELOG("MSG_ID_IPCORE_LINK_UP_REQ check failed!\r\n");
+            return KAL_FALSE;
+        }
+
+        if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_UP,
+                                    net->conf.netif_id,
+                                    ip_id,
+                                    ntfy_entry_cnt) != KAL_TRUE) {
+            utELOG("IPC_NTFY_TYPE_LINK_UP notification check failed!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                *   Simulate ALL network interface link change
+                *
+                *   1. totally trigger count should be "orgIlmCnt+1"
+                *   2. totally notification count for specific network interface should same as registered count
+                *
+                */
+        for (linkChangeTestIdx = 0 ; linkChangeTestIdx < 16 ; linkChangeTestIdx ++) {
+            /* Link UP */
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ipc_ut_ntfy_reset_param();
+
+            ipc_notify_all_netif_link_change(ip_types[idx], KAL_TRUE);
+
+            if (ipc_ut_msg_chk( MOD_IPCORE,
+                                net->conf.module_id,
+                                IPCORE_SAP,
+                                MSG_ID_IPCORE_LINK_UP_REQ,
+                                orgIlmCnt + 1) != KAL_TRUE) {
+                utELOG("MSG_ID_IPCORE_LINK_UP_REQ check failed!\r\n");
+                return KAL_FALSE;
+            }
+
+            if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_UP,
+                                        net->conf.netif_id,
+                                        ip_id,
+                                        ntfy_entry_cnt) != KAL_TRUE) {
+                utELOG("IPC_NTFY_TYPE_LINK_UP notification check failed!\r\n");
+                return KAL_FALSE;
+            }
+
+            /* Link DOWN */
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ipc_ut_ntfy_reset_param();
+
+            ipc_notify_all_netif_link_change(ip_types[idx], KAL_FALSE);
+
+            if (ipc_ut_msg_chk( MOD_IPCORE,
+                                net->conf.module_id,
+                                IPCORE_SAP,
+                                MSG_ID_IPCORE_LINK_DOWN_REQ,
+                                orgIlmCnt + 1) != KAL_TRUE) {
+                utELOG("MSG_ID_IPCORE_LINK_DOWN_REQ check failed!\r\n");
+                return KAL_FALSE;
+            }
+
+            if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_DOWN,
+                                        net->conf.netif_id,
+                                        ip_id,
+                                        ntfy_entry_cnt) != KAL_TRUE) {
+                utELOG("IPC_NTFY_TYPE_LINK_DOWN notification check failed!\r\n");
+                return KAL_FALSE;
+            }
+        }
+
+        /* Notify Link UP */
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ipc_ut_ntfy_reset_param();
+
+        ipc_notify_all_netif_link_change(ip_types[idx], KAL_TRUE);
+
+        if (ipc_ut_msg_chk( MOD_IPCORE,
+                            net->conf.module_id,
+                            IPCORE_SAP,
+                            MSG_ID_IPCORE_LINK_UP_REQ,
+                            orgIlmCnt + 1) != KAL_TRUE) {
+            utELOG("MSG_ID_IPCORE_LINK_UP_REQ check failed!\r\n");
+            return KAL_FALSE;
+        }
+
+        if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_UP,
+                                    net->conf.netif_id,
+                                    ip_id,
+                                    ntfy_entry_cnt) != KAL_TRUE) {
+            utELOG("IPC_NTFY_TYPE_LINK_UP notification check failed!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                * PDN deactivation.
+                */
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ipc_ut_ntfy_reset_param();
+
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* LINK-DOWN */
+        if (ipc_ut_msg_chk( MOD_IPCORE,
+                            net->conf.module_id,
+                            IPCORE_SAP,
+                            MSG_ID_IPCORE_LINK_DOWN_REQ,
+                            1) != KAL_TRUE) {
+            utELOG("MSG_ID_IPCORE_LINK_DOWN_REQ check failed!\r\n");
+            return KAL_FALSE;
+        }
+
+        if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_DOWN,
+                                    net->conf.netif_id,
+                                    ip_id,
+                                    ntfy_entry_cnt) != KAL_TRUE) {
+            utELOG("IPC_NTFY_TYPE_LINK_DOWN notification check failed!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                * ipc_detach().
+                */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /* Always deregister all notification entries */
+        ipc_ut_ntfy_deregistration(KAL_TRUE, 0, NULL);
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ipv4_status_ind(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32                          idx;
+    ipc_ut_netif_t                      *net;
+    ipc_session_t                       *session;
+    kal_int32                           ip_id;
+    kal_uint8                           dhcp4c_id;
+    ipcore_upcm_pdn_bind_ind_struct     *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct    *deact_req;
+    kal_uint8                           ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool                            result;
+    kal_int32                           set_ntfy_module;
+    kal_int32                           ntfy_cnt;
+    kal_int32                           ntfy_dereg_cnt;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (set_ntfy_module = 0 ; set_ntfy_module < 2 ; set_ntfy_module ++)
+    for (ntfy_cnt = 0 ; ntfy_cnt < IPC_MAX_NTFY_CNT + 2 ; ntfy_cnt ++)
+    for (ntfy_dereg_cnt = 0 ; ntfy_dereg_cnt <= ntfy_cnt ; ntfy_dereg_cnt ++)
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        kal_int32 ntfy_entry_cnt;
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        utDLOG("set_ntfy_md %d ntfy_cnt %d ntfy_dereg_cnt: %d idx %d\r\n", set_ntfy_module, ntfy_cnt, ntfy_dereg_cnt, idx);
+
+        /*
+                * Configure notification setting
+                */
+        if (set_ntfy_module) {
+            ipc_register_ip_up_ind_handler(MOD_IPCORE);
+        } else {
+            ipc_deregister_ip_up_ind_handler();
+        }
+
+        ipc_ut_ntfy_reset_info();
+        if (ipc_ut_ntfy_registration(ntfy_cnt) != KAL_TRUE) {
+            utELOG("ipc_ut_ntfy_registration() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+        ipc_ut_ntfy_deregistration(KAL_FALSE, ntfy_dereg_cnt, &ntfy_entry_cnt);
+
+        /*
+                * ipc_attach()
+                */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = IPC_F_DHCP4C;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+                */
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ipc_ut_ntfy_reset_param();
+
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        /* Get session */
+        session = ipc_find_session_by_context(IPC_UT_PDN_ID);
+        if (!session) {
+            utELOG("no session found!\r\n");
+            return KAL_FALSE;
+        }
+        dhcp4c_id = session->dhcp4c_id;
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+        ip_id = ipc_get_ip_id(net->handle);
+
+        if (   (ip_types[idx] == IPV4_ADDR_TYPE) ||
+                (ip_types[idx] == IPV4V6_ADDR_TYPE)) {
+            /* DHCP4c only activated in IPv4 related types */
+            if (ipc_ut_msg_chk( 0,
+                                0,
+                                0,
+                                0,
+                                0) != KAL_TRUE) {
+                utELOG("MSG_ID_IPCORE_LINK_UP_REQ check failed!\r\n");
+                return KAL_FALSE;
+            }
+
+            if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_UP,
+                                        net->conf.netif_id,
+                                        ip_id,
+                                        0) != KAL_TRUE) {
+                utELOG("IPC_NTFY_TYPE_LINK_UP notification check failed!\r\n");
+                return KAL_FALSE;
+            }
+        } else {   /* For IPv6 only type, Link UP directly */
+            if (ipc_ut_msg_chk( MOD_IPCORE,
+                                net->conf.module_id,
+                                IPCORE_SAP,
+                                MSG_ID_IPCORE_LINK_UP_REQ,
+                                1) != KAL_TRUE) {
+                utELOG("MSG_ID_IPCORE_LINK_UP_REQ check failed!\r\n");
+                return KAL_FALSE;
+            }
+
+            if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_UP,
+                                        net->conf.netif_id,
+                                        ip_id,
+                                        ntfy_entry_cnt) != KAL_TRUE) {
+                utELOG("IPC_NTFY_TYPE_LINK_UP notification check failed!\r\n");
+                return KAL_FALSE;
+            }
+        }
+
+
+        /*
+                *   Simulate IP-up/down indication from DHCP4c are called
+                *
+                *   1. 1st IP-UP notification     : trigger Link-up indication
+                *   2. IP-DOWN notification     : trigger IP-down indication
+                *   3. IP-UP notification           : trigger IP-UP indication
+                *
+                */
+        {
+            kal_uint32 cnt;
+            dhcp4c_ip_up_ind_struct     ip_up_ind;
+            dhcp4c_ip_down_ind_struct   ip_down_ind;
+
+            /* 1st IP-UP : Link UP */
+            {
+                ip_up_ind.ip_id = ip_id;
+                ip_up_ind.dhcp_id = dhcp4c_id;
+
+                ipc_ut_msg_reset(NULL, 0, NULL, 0);
+                ipc_ut_ntfy_reset_param();
+
+                ipc_on_dhcp4c_ip_up_ind((void*)&ip_up_ind);
+
+
+                if (   (ip_types[idx] == IPV4_ADDR_TYPE) ||
+                        (ip_types[idx] == IPV4V6_ADDR_TYPE)) {
+                    /* DHCP4c only activated in IPv4 related types */
+                    if (ipc_ut_msg_chk( MOD_IPCORE,
+                                        net->conf.module_id,
+                                        IPCORE_SAP,
+                                        MSG_ID_IPCORE_LINK_UP_REQ,
+                                        1) != KAL_TRUE) {
+                        utELOG("MSG_ID_IPCORE_LINK_UP_REQ check failed!\r\n");
+                        return KAL_FALSE;
+                    }
+
+                    if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_UP,
+                                                net->conf.netif_id,
+                                                ip_id,
+                                                ntfy_entry_cnt) != KAL_TRUE) {
+                        utELOG("IPC_NTFY_TYPE_LINK_UP notification check failed!\r\n");
+                        return KAL_FALSE;
+                    }
+                } else {
+                    if (ipc_ut_msg_chk( 0,
+                                        0,
+                                        0,
+                                        0,
+                                        0) != KAL_TRUE) {
+                            utELOG("DHCP4c still works in IPv6 PDN : check failed!\r\n");
+                            return KAL_FALSE;
+                    }
+
+                    if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_UP,
+                                                net->conf.netif_id,
+                                                ip_id,
+                                                0) != KAL_TRUE) {
+                        utELOG("IPC_NTFY_TYPE_LINK_UP notification check failed!\r\n");
+                        return KAL_FALSE;
+                    }
+                }
+            }
+
+            /* After 1st IP-UP: Link UP/DOWN will be forwarded to corresponding network interface */
+            for ( cnt = 0 ; cnt < 16 ; cnt ++ ) {
+                /* IP DOWN */
+                {
+                    ip_down_ind.ip_id = ip_id;
+                    ip_down_ind.dhcp_id = dhcp4c_id;
+
+                    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+                    ipc_ut_ntfy_reset_param();
+
+                    ipc_on_dhcp4c_ip_down_ind((void*)&ip_down_ind);
+
+                    if (   (ip_types[idx] == IPV4_ADDR_TYPE) ||
+                            (ip_types[idx] == IPV4V6_ADDR_TYPE)) {
+                        /* DHCP4c only activated in IPv4 related types */
+                        if (ipc_ut_msg_chk( MOD_IPCORE,
+                                            net->conf.module_id,
+                                            IPCORE_SAP,
+                                            MSG_ID_IPCORE_IP_DOWN_REQ,
+                                            1) != KAL_TRUE) {
+                            utELOG("MSG_ID_IPCORE_IP_DOWN_REQ check failed!\r\n");
+                            return KAL_FALSE;
+                        }
+
+                        if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_IP_DOWN,
+                                                    net->conf.netif_id,
+                                                    ip_id,
+                                                    ntfy_entry_cnt) != KAL_TRUE) {
+                            utELOG("IPC_NTFY_TYPE_IP_DOWN notification check failed!\r\n");
+                            return KAL_FALSE;
+                        }
+                    } else {
+                        if (ipc_ut_msg_chk( 0,
+                                            0,
+                                            0,
+                                            0,
+                                            0) != KAL_TRUE) {
+                                utELOG("DHCP4c still works in IPv6 PDN : check failed!\r\n");
+                                return KAL_FALSE;
+                        }
+
+                        if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_IP_DOWN,
+                                                    net->conf.netif_id,
+                                                    ip_id,
+                                                    0) != KAL_TRUE) {
+                            utELOG("IPC_NTFY_TYPE_IP_DOWN notification check failed!\r\n");
+                            return KAL_FALSE;
+                        }
+                    }
+                }
+
+                /* IP UP */
+                {
+                    ip_up_ind.ip_id = ip_id;
+                    ip_up_ind.dhcp_id = dhcp4c_id;
+
+                    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+                    ipc_ut_ntfy_reset_param();
+
+                    ipc_on_dhcp4c_ip_up_ind((void*)&ip_up_ind);
+
+                    if (   (ip_types[idx] == IPV4_ADDR_TYPE) ||
+                            (ip_types[idx] == IPV4V6_ADDR_TYPE)) {
+                        /* DHCP4c only activated in IPv4 related types */
+                        if (ipc_ut_msg_chk( MOD_IPCORE,
+                                            net->conf.module_id,
+                                            IPCORE_SAP,
+                                            MSG_ID_IPCORE_IP_UP_REQ,
+                                            1) != KAL_TRUE) {
+                            utELOG("MSG_ID_IPCORE_IP_UP_REQ check failed!\r\n");
+                            return KAL_FALSE;
+                        }
+
+                        if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_IP_UP,
+                                                    net->conf.netif_id,
+                                                    ip_id,
+                                                    ntfy_entry_cnt) != KAL_TRUE) {
+                            utELOG("IPC_NTFY_TYPE_IP_UP notification check failed!\r\n");
+                            return KAL_FALSE;
+                        }
+                    } else {
+                        if (ipc_ut_msg_chk( 0,
+                                            0,
+                                            0,
+                                            0,
+                                            0) != KAL_TRUE) {
+                                utELOG("DHCP4c still works in IPv6 PDN : check failed!\r\n");
+                                return KAL_FALSE;
+                        }
+
+                        if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_IP_UP,
+                                                    net->conf.netif_id,
+                                                    ip_id,
+                                                    0) != KAL_TRUE) {
+                            utELOG("IPC_NTFY_TYPE_IP_UP notification check failed!\r\n");
+                            return KAL_FALSE;
+                        }
+                    }
+                }
+            }
+        }
+
+        /*
+                * PDN deactivation.
+                */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        if (ipc_ut_ntfy_chk_param(  IPC_NTFY_TYPE_LINK_DOWN,
+                                    net->conf.netif_id,
+                                    ip_id,
+                                    ntfy_entry_cnt) != KAL_TRUE) {
+            utELOG("IPC_NTFY_TYPE_LINK_DOWN notification check failed!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                *   Simulate IP-up/down indication from DHCP4c are called
+                *
+                *   - After deactivation, No any notification should be triggered
+                *
+                */
+        {
+            dhcp4c_ip_up_ind_struct     ip_up_ind;
+            dhcp4c_ip_down_ind_struct   ip_down_ind;
+
+            /* IP DOWN */
+            {
+                ip_down_ind.ip_id = ip_id;
+                ip_down_ind.dhcp_id = dhcp4c_id;
+
+                ipc_ut_msg_reset(NULL, 0, NULL, 0);
+                ipc_on_dhcp4c_ip_down_ind((void*)&ip_down_ind);
+
+                if (ipc_ut_msg_chk( 0,
+                                    0,
+                                    0,
+                                    0,
+                                    0) != KAL_TRUE) {
+                    utELOG("[IP DOWN notification handling after deactivation] check failed!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+
+            /* IP UP */
+            {
+                ip_up_ind.ip_id = ip_id;
+                ip_up_ind.dhcp_id = dhcp4c_id;
+
+                ipc_ut_msg_reset(NULL, 0, NULL, 0);
+                ipc_on_dhcp4c_ip_up_ind((void*)&ip_up_ind);
+
+                if (ipc_ut_msg_chk( 0,
+                                    0,
+                                    0,
+                                    0,
+                                    0) != KAL_TRUE) {
+                    utELOG("[IP UP notification handling after deactivation] check failed!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+                * ipc_detach().
+                */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+                *   Simulate IP-up/down indication from DHCP4c are called
+                *
+                *   - After detach, No any notification should be triggered
+                *
+                */
+        {
+            dhcp4c_ip_up_ind_struct     ip_up_ind;
+            dhcp4c_ip_down_ind_struct   ip_down_ind;
+
+            /* IP DOWN */
+            {
+                ip_down_ind.ip_id = ip_id;
+                ip_down_ind.dhcp_id = dhcp4c_id;
+
+                ipc_ut_msg_reset(NULL, 0, NULL, 0);
+                ipc_on_dhcp4c_ip_down_ind((void*)&ip_down_ind);
+
+                if (ipc_ut_msg_chk( 0,
+                                    0,
+                                    0,
+                                    0,
+                                    0) != KAL_TRUE) {
+                    utELOG("[IP DOWN notification handling after detach] check failed!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+
+            /* IP UP */
+            {
+                ip_up_ind.ip_id = ip_id;
+                ip_up_ind.dhcp_id = dhcp4c_id;
+
+                ipc_ut_msg_reset(NULL, 0, NULL, 0);
+                ipc_on_dhcp4c_ip_up_ind((void*)&ip_up_ind);
+
+                if (ipc_ut_msg_chk( 0,
+                                    0,
+                                    0,
+                                    0,
+                                    0) != KAL_TRUE) {
+                    utELOG("[IP UP notification handling after detach] check failed!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /* Always deregister all notification entries */
+        ipc_ut_ntfy_deregistration(KAL_TRUE, 0, NULL);
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_en_dhcp4c_unspecified_addr(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipc_session_t    *session;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool          result;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+    /*
+         * ipc_attach() with IPC_F_DHCP4C
+         */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = IPC_F_DHCP4C;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+    /*
+         * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        session = ipc_find_session_by_context(IPC_UT_PDN_ID);
+        if (!session) {
+            utELOG("no session found!\r\n");
+            return KAL_FALSE;
+        }
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+    /*
+         * Check downlink filter and DHCPv4 client ID's.
+         */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+        IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+        if (IPV4_ADDR_TYPE == ip_types[idx] || IPV4V6_ADDR_TYPE == ip_types[idx]) {
+            if (0 > session->dhcp4c_dl_filter_id) {
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                utELOG("Downlink filter for DHCPv4 is not installed!\r\n");
+                return KAL_FALSE;
+            }
+            if (!session->dhcp4c_running) {
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                utELOG("DHCPv4 client is not running!\r\n");
+                return KAL_FALSE;
+            }
+        } else {
+            if (0 <= session->dhcp4c_dl_filter_id) {
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                utELOG("Downlink filter for DHCPv4 shall not be installed!\r\n");
+                return KAL_FALSE;
+            }
+            if (session->dhcp4c_running) {
+                IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+                utELOG("DHCPv4 client shall not be running!\r\n");
+                return KAL_FALSE;
+            }
+        }
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+    /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+    /*
+         * ipc_detach().
+         */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_en_dhcp4c_valid_addr(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipc_session_t    *session;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE};
+    kal_bool          result;
+    kal_uint8         valid_ipv4_addr[] = {192, 168, 0, 1};
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /*
+         * ipc_attach() with IPC_F_DHCP4C
+         */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = IPC_F_DHCP4C;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * Activate IPv4/IPv4v6 PDN with valid IP address.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        IPC_CP_V4_ADDR(bind_req->ip_addr.ipv4, valid_ipv4_addr);
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        session = ipc_find_session_by_context(IPC_UT_PDN_ID);
+        if (!session) {
+            utELOG("no session found!\r\n");
+            return KAL_FALSE;
+        }
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        /*
+         * Check downlink filter and DHCPv4 client ID's.
+         */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+        IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+        if (0 <= session->dhcp4c_dl_filter_id) {
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            utELOG("Downlink filter for DHCPv4 shall not be installed!\r\n");
+            return KAL_FALSE;
+        }
+        if (session->dhcp4c_running) {
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            utELOG("DHCPv4 client shall not be running!\r\n");
+            return KAL_FALSE;
+        }
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /*
+         * ipc_detach().
+         */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dis_dhcp4c_unspecified_addr(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipc_session_t    *session;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool          result;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /*
+         * ipc_attach() without IPC_F_DHCP4C
+         */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.features = 0;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+        session = ipc_find_session_by_context(IPC_UT_PDN_ID);
+        if (!session) {
+            utELOG("no session found!\r\n");
+            return KAL_FALSE;
+        }
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        /*
+         * Check downlink filter and DHCPv4 client ID's.
+         */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+        IPC_R_LOCK_OBJECT(session, ipc_spinlock_g);
+        if (0 <= session->dhcp4c_dl_filter_id) {
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            utELOG("Downlink filter for DHCPv4 shall not be installed!\r\n");
+            return KAL_FALSE;
+        }
+        if (session->dhcp4c_running) {
+            IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+            utELOG("DHCPv4 client shall not be running!\r\n");
+            return KAL_FALSE;
+        }
+        IPC_R_UNLOCK_OBJECT(session, ipc_spinlock_g);
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /*
+         * ipc_detach().
+         */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ul_filter_none(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32  ipv4_cnt;
+    kal_uint32  ipv6_cnt;
+    qbm_gpd    *head_gpd;
+    qbm_gpd    *tail_gpd;
+    kal_uint8   session_type;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+            ipc_ut_reset_ul_filter_info();
+            ipc_ut_prepare_ul_gpd_list(KAL_FALSE, ipv4_cnt, 0, ipv6_cnt, 0, &head_gpd, &tail_gpd, NULL);
+
+            if (NULL == head_gpd || NULL == tail_gpd) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+            session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                                                ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                                                                   IPC_IP_TYPE_MIXED) );
+
+            ipc_do_ul_filter(session_type, IPC_UT_NETID_START, &head_gpd, &tail_gpd);
+
+            if (ipc_ut_ul_filter_id >= 0) {
+                utELOG("No filter test case failed (Filter ID is configured)!\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                return KAL_FALSE;
+            }
+
+            if (NULL != ipc_ut_ul_head_gpd ||
+                NULL != ipc_ut_ul_tail_gpd ||
+                ipc_ut_ul_filter_gpd_cnt != 0 ||
+                (ipv4_cnt + ipv6_cnt) != ipc_ut_gpd_list_count(head_gpd, tail_gpd)) {
+                utELOG("No filter test case failed!\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                return KAL_FALSE;
+            }
+
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_filter_none(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32  ipv4_cnt;
+    kal_uint32  ipv6_cnt;
+    qbm_gpd    *head_gpd;
+    qbm_gpd    *tail_gpd;
+    kal_uint8   session_type;
+    kal_uint32  alignment;
+    kal_uint32  unite;
+    kal_uint32  spd;
+    kal_uint32  spd_igr_bit;
+    kal_uint32  spd_position;
+    kal_uint32  total_cnt;
+    kal_uint32  spd_payload_cnt;
+    kal_uint32  i;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (unite = 0 ; unite < 2 ; unite ++)
+    for (alignment = 0 ; alignment < 4 ; alignment ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+    for (spd = 0; spd < 1; spd++)
+    for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+    for (spd_position = 0; spd_position < 3; spd_position++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+        if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+        ipc_ut_reset_dl_filter_info();
+        ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                    0,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    ipv6_cnt,
+                                    0,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    (unite == 0)?0:10,
+                                    alignment,
+                                    &head_gpd,
+                                    &tail_gpd,
+                                    NULL,
+                                    NULL,
+                                    spd,
+                                    spd_igr_bit,
+                                    spd_position);
+
+        session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                                            ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                                                               IPC_IP_TYPE_MIXED) );
+
+        ipc_do_dl_filter(session_type, IPC_UT_NETID_START, IPC_UT_PDN_ID, &head_gpd, &tail_gpd);
+
+        if (ipc_ut_dl_filter_id >= 0) {
+            utELOG("No filter test case failed (Filter ID is configured)! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            return KAL_FALSE;
+        }
+
+        if (1 == spd) {
+            total_cnt = ipv4_cnt + ipv6_cnt + 1;
+            spd_payload_cnt = ipv4_cnt + ipv6_cnt;
+            if (1 == spd_igr_bit) {
+                kal_uint32 igr_payload_cnt = 0;
+                for (i = 0; i < (ipv4_cnt + ipv6_cnt); i++) {
+                    igr_payload_cnt += ipc_ut_spd_packet_igr_s[i];
+                }
+                if ((ipv4_cnt + ipv6_cnt) == igr_payload_cnt) {
+                    /* All SPD's payloads has been ignored. */
+                    total_cnt--;
+                    spd_payload_cnt = 0;
+                } else {
+                    spd_payload_cnt -= igr_payload_cnt;
+                }
+            }
+        } else {
+            total_cnt = ipv4_cnt + ipv6_cnt;
+            spd_payload_cnt = 0;
+        }
+
+        if (NULL != ipc_ut_dl_head_gpd ||
+            NULL != ipc_ut_dl_tail_gpd ||
+            (0 != ipc_ut_dl_filter_gpd_cnt) ||
+            (total_cnt != ipc_ut_gpd_list_count(head_gpd, tail_gpd)) ||
+            (spd_payload_cnt != ipc_ut_spd_payload_count(head_gpd, tail_gpd)) ) {
+            utELOG("No filter test case failed! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            return KAL_FALSE;
+        }
+
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ul_filter_ipv4(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32 callback_with_info;
+    kal_uint32  ipv4_cnt;
+    kal_uint32  ipv6_cnt;
+    kal_uint32  filter_cnt;
+    qbm_gpd    *head_gpd;
+    qbm_gpd    *tail_gpd;
+    kal_uint8   session_type;
+    kal_uint8   matched_filter_idx_v4;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * (#ipv4 packets, #ipv6 packets, #ipv4 filters, #ipv6 filters)=(1-16, 0-3, 1-3, 0),
+     * where one of IPv4 GPD's is DHCP packet and one of IPv4 filters  is DHCP
+     * => only one GPD matched.
+     */
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 1; ipv4_cnt <= 16; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+    for (filter_cnt = 1; filter_cnt < 4; filter_cnt++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < filter_cnt; matched_filter_idx_v4++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+        ipc_ut_install_ul_filters(callback_with_info, KAL_TRUE, filter_cnt, 0, KAL_FALSE, KAL_FALSE, matched_filter_idx_v4, 0, IPC_UT_NETID_START);
+
+        ipc_ut_reset_ul_filter_info();
+        ipc_ut_prepare_ul_gpd_list(KAL_FALSE, ipv4_cnt, ipv4_cnt-1, ipv6_cnt, 0, &head_gpd, &tail_gpd, NULL);
+
+        if (NULL == head_gpd || NULL == tail_gpd) {
+            utELOG("UL packet prepare failed!\r\r");
+            return KAL_FALSE;
+        }
+
+        session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                 IPC_IP_TYPE_MIXED) );
+        ipc_do_ul_filter(session_type, IPC_UT_NETID_START, &head_gpd, &tail_gpd);
+
+        if (callback_with_info) {
+            if (ipc_ut_ul_filter_info.netif_id != IPC_UT_NETID_START) {
+                utELOG("IPv4 filter test case failed! (netif_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+            if (ipc_ut_ul_filter_info.ip_id != -1) {
+                utELOG("IPv4 filter test case failed! (ip_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+        } else {
+            if (ipc_ut_ul_filter_info.netif_id != 0) {
+                utELOG("IPv4 filter test case failed! (netif_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+            if (ipc_ut_ul_filter_info.ip_id != -1) {
+                utELOG("IPv4 filter test case failed! (ip_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+        }
+
+        if (ipc_ut_ul_filter_id != matched_filter_idx_v4) {
+            utELOG("IPv4 filter test case failed! (Filter ID match fail)\r\n");
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+            return KAL_FALSE;
+        }
+
+        if (NULL == ipc_ut_ul_head_gpd ||
+                NULL == ipc_ut_ul_tail_gpd ||
+                ipc_ut_ul_head_gpd != ipc_ut_ul_tail_gpd ||
+                ipc_ut_ul_filter_gpd_cnt != 1 ||
+                (ipv4_cnt + ipv6_cnt - 1) != ipc_ut_gpd_list_count(head_gpd, tail_gpd)) {
+            utELOG("IPv4 filter test case failed!\r\n");
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+            return KAL_FALSE;
+        }
+
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+        ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_filter_ipv4(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32  callback_with_info;
+    kal_uint32  ipv4_cnt;
+    kal_uint32  ipv6_cnt;
+    kal_uint32  filter_cnt;
+    qbm_gpd    *head_gpd;
+    qbm_gpd    *tail_gpd;
+    kal_uint8   session_type;
+    kal_uint32  alignment;
+    kal_uint32  unite;
+    kal_uint8   matched_filter_idx_v4;
+    kal_uint32  spd;
+    kal_uint32  spd_position;
+    kal_uint32  total_cnt;
+    kal_uint32  spd_payload_cnt;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * (#ipv4 packets, #ipv6 packets, #ipv4 filters, #ipv6 filters)=(1-16, 0-3, 1-3, 0),
+     * where one of IPv4 GPD's is DHCP packet and one of IPv4 filters  is DHCP
+     * => only one GPD matched.
+     */
+    for (unite = 0 ; unite < 2 ; unite ++)
+    for (alignment = 0 ; alignment < 4 ; alignment ++)
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 1; ipv4_cnt <= 16; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+    for (filter_cnt = 1; filter_cnt < 4; filter_cnt++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < filter_cnt; matched_filter_idx_v4++)
+    for (spd = 0; spd < 1; spd++)
+//     for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+    for (spd_position = 0; spd_position < 3; spd_position++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+        if (0 == spd && 0 < spd_position) continue;
+
+        ipc_ut_install_dl_filters(callback_with_info, KAL_TRUE, filter_cnt, 0, matched_filter_idx_v4, 0, IPC_UT_NETID_START);
+
+        ipc_ut_reset_dl_filter_info();
+        ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                    ipv4_cnt-1,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    ipv6_cnt,
+                                    0,
+                                    KAL_FALSE, KAL_FALSE,
+                                    (unite == 0)?0:10,
+                                    alignment,
+                                    &head_gpd,
+                                    &tail_gpd,
+                                    NULL,
+                                    NULL,
+                                    spd,
+                                    KAL_FALSE,
+                                    spd_position);
+
+        session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                                            ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                                                               IPC_IP_TYPE_MIXED) );
+
+        ipc_do_dl_filter(session_type, IPC_UT_NETID_START, IPC_UT_PDN_ID, &head_gpd, &tail_gpd);
+
+        if (callback_with_info) {
+            if (ipc_ut_dl_filter_info.netif_id != IPC_UT_NETID_START) {
+                utELOG("IPv4 filter test case failed! (NetIF ID match fail) (SPD:%d)\r\n", spd);
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        } else {
+            if (ipc_ut_dl_filter_info.netif_id != 0) {
+                utELOG("IPv4 filter test case failed! (NetIF ID match fail) (SPD:%d)\r\n", spd);
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        }
+
+        if (ipc_ut_dl_filter_id != matched_filter_idx_v4) {
+            utELOG("IPv4 filter test case failed! (Filter ID match fail) (SPD:%d)\r\n", spd);
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+            return KAL_FALSE;
+        }
+
+        if (1 == spd) {
+            if ((1 == ipv4_cnt) && (0 == ipv6_cnt)) {
+                /* Only ipv4 DHCP packet left, so there is no SPD */
+                total_cnt = ipv4_cnt + ipv6_cnt - 1;
+                spd_payload_cnt = 0;
+            } else {
+                total_cnt = ipv4_cnt + ipv6_cnt - ipc_ut_dl_filter_expect_gpd_cnt/*dhcp4c*/ + 1/*spd*/;
+                spd_payload_cnt = ipv4_cnt + ipv6_cnt - ipc_ut_dl_filter_expect_gpd_cnt/*dhcp4c*/;
+            }
+            if (NULL == ipc_ut_dl_head_gpd ||
+                NULL == ipc_ut_dl_tail_gpd ||
+                ipc_ut_dl_filter_expect_gpd_cnt*2 != ipc_ut_dl_filter_gpd_cnt ||
+                total_cnt != ipc_ut_gpd_list_count(head_gpd, tail_gpd) ||
+                spd_payload_cnt != ipc_ut_spd_payload_count(head_gpd, tail_gpd) ) {
+                utELOG("IPv4 filter test case failed! (with SPD)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        } else {
+            if (NULL == ipc_ut_dl_head_gpd ||
+                NULL == ipc_ut_dl_tail_gpd ||
+                //ipc_ut_dl_head_gpd != ipc_ut_dl_tail_gpd ||
+                ipc_ut_dl_filter_expect_gpd_cnt != ipc_ut_dl_filter_gpd_cnt ||
+                (ipv4_cnt + ipv6_cnt - ipc_ut_dl_filter_expect_gpd_cnt) != ipc_ut_gpd_list_count(head_gpd, tail_gpd) ||
+                0 != ipc_ut_spd_payload_count(head_gpd, tail_gpd) ) {
+                utELOG("IPv4 filter test case failed!\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        }
+
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+        ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+    }
+    ipc_ut_install_netif_filter(IPC_UT_NETID_START);
+
+    for (ipv4_cnt = 1; ipv4_cnt <= 16; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+    {
+        ipc_ut_reset_dl_filter_info();
+        ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                    ipv4_cnt-1,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    ipv6_cnt,
+                                    0,
+                                    KAL_FALSE, KAL_FALSE,
+                                    0,
+                                    0,
+                                    &head_gpd,
+                                    &tail_gpd,
+                                    NULL,
+                                    NULL,
+                                    0,
+                                    KAL_FALSE,
+                                    0);
+        session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                                            ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                                                               IPC_IP_TYPE_MIXED) );
+
+
+        ipc_do_dl_filter(session_type, IPC_UT_NETID_START, IPC_UT_PDN_ID, &head_gpd, &tail_gpd);
+        if (ipc_ut_dl_filter_info.netif_id != IPC_UT_NETID_START) {
+            utELOG("IPv4 filter test case failed! (NetIF ID match fail) (SPD:%d)\r\n", spd);
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+            return KAL_FALSE;
+        }
+        if (ipc_ut_dl_filter_id != 0) {
+            utELOG("IPv4 filter test case failed! (Filter ID match fail) (SPD:%d)\r\n", spd);
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+            return KAL_FALSE;
+        }
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+        
+    }
+
+    ipc_ut_uninstall_netif_filter();
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ul_filter_ipv6(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32  callback_with_info;
+    kal_uint32  ipv4_cnt;
+    kal_uint32  ipv6_cnt;
+    kal_uint32  filter_cnt;
+    qbm_gpd    *head_gpd;
+    qbm_gpd    *tail_gpd;
+    kal_uint8   session_type;
+    kal_uint8   matched_filter_idx_v6;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * (#ipv4 packets, #ipv6 packets, #ipv4 filters, #ipv6 filters)=(0-3, 1-16, 0, 1-3),
+     * where one of IPv4 GPD's is DHCP packet and one of IPv4 filters  is DHCP
+     * => only one GPD matched.
+     */
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 1; ipv6_cnt <= 16; ipv6_cnt++)
+    for (filter_cnt = 1; filter_cnt < 4; filter_cnt++)
+    for (matched_filter_idx_v6 = 0; matched_filter_idx_v6 < filter_cnt; matched_filter_idx_v6++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+        utDLOG("if(%d) 4Ct(%d) 6Ct(%d) fCt(%d) fIdx(%d)\r\n",
+                        callback_with_info, ipv4_cnt, ipv6_cnt, filter_cnt, matched_filter_idx_v6);
+
+        ipc_ut_install_ul_filters(callback_with_info, KAL_TRUE, 0, filter_cnt, KAL_FALSE, KAL_FALSE, 0, matched_filter_idx_v6, IPC_UT_NETID_START);
+
+        ipc_ut_reset_ul_filter_info();
+        ipc_ut_prepare_ul_gpd_list(KAL_FALSE, ipv4_cnt, 0, ipv6_cnt, ipv6_cnt-1, &head_gpd, &tail_gpd, NULL);
+
+        if (NULL == head_gpd || NULL == tail_gpd) {
+            utELOG("UL packet prepare failed!\r\r");
+            return KAL_FALSE;
+        }
+
+        session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                                            ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                                                               IPC_IP_TYPE_MIXED) );
+
+        ipc_do_ul_filter(session_type, IPC_UT_NETID_START, &head_gpd, &tail_gpd);
+
+        if (callback_with_info) {
+            if (ipc_ut_ul_filter_info.netif_id != IPC_UT_NETID_START) {
+                utELOG("IPv6 filter test case failed! (netif_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(0, filter_cnt, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+            if (ipc_ut_ul_filter_info.ip_id != -1) {
+                utELOG("IPv6 filter test case failed! (ip_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(0, filter_cnt, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+        } else {
+            if (ipc_ut_ul_filter_info.netif_id != 0) {
+                utELOG("IPv6 filter test case failed! (netif_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(0, filter_cnt, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+            if (ipc_ut_ul_filter_info.ip_id != -1) {
+                utELOG("IPv6 filter test case failed! (ip_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(0, filter_cnt, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+        }
+
+        if (ipc_ut_ul_filter_id != matched_filter_idx_v6) {
+            utELOG("IPv6 filter test case failed! (Filter ID match fail)\r\n");
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_ul_filters(0, filter_cnt, KAL_FALSE, KAL_FALSE);
+            return KAL_FALSE;
+        }
+
+        if (NULL == ipc_ut_ul_head_gpd ||
+            NULL == ipc_ut_ul_tail_gpd ||
+            ipc_ut_ul_head_gpd != ipc_ut_ul_tail_gpd ||
+            ipc_ut_ul_filter_gpd_cnt != 1 ||
+            (ipv4_cnt + ipv6_cnt - 1) != ipc_ut_gpd_list_count(head_gpd, tail_gpd)) {
+            utELOG("IPv6 filter test case failed!\r\n");
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_ul_filters(0, filter_cnt, KAL_FALSE, KAL_FALSE);
+            return KAL_FALSE;
+        }
+
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+        ipc_ut_uninstall_ul_filters(0, filter_cnt, KAL_FALSE, KAL_FALSE);
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_filter_ipv6(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32  callback_with_info;
+    kal_uint32  ipv4_cnt;
+    kal_uint32  ipv6_cnt;
+    kal_uint32  filter_cnt;
+    qbm_gpd    *head_gpd;
+    qbm_gpd    *tail_gpd;
+    kal_uint8   session_type;
+    kal_uint32  alignment;
+    kal_uint32  unite;
+    kal_uint8   matched_filter_idx_v6;
+    kal_uint32  spd;
+    kal_uint32  spd_position;
+    kal_uint32  total_cnt;
+    kal_uint32  spd_payload_cnt;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * (#ipv4 packets, #ipv6 packets, #ipv4 filters, #ipv6 filters)=(0-3, 1-16, 0, 1-3),
+     * where one of IPv6 GPD's is DHCP packet and one of IPv6 filters  is DHCP
+     * => only one GPD matched.
+     */
+    for (unite = 0 ; unite < 2 ; unite ++)
+    for (alignment = 0 ; alignment < 4 ; alignment ++)
+    for (callback_with_info = 0 ; callback_with_info < 2; callback_with_info ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 1; ipv6_cnt <= 16; ipv6_cnt++)
+    for (filter_cnt = 1; filter_cnt < 4; filter_cnt++)
+    for (matched_filter_idx_v6 = 0; matched_filter_idx_v6 < filter_cnt; matched_filter_idx_v6++)
+    for (spd = 0; spd < 1; spd++)
+    for (spd_position = 0; spd_position < 3; spd_position++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+        if (0 == spd && 0 < spd_position) continue;
+
+        utDLOG("un(%d) al(%d) if(%d) 4Ct(%d) 6Ct(%d) fCt(%d) fIdx(%d)\r\n",
+                        unite, alignment, callback_with_info, ipv4_cnt, ipv6_cnt, filter_cnt, matched_filter_idx_v6);
+
+        ipc_ut_install_dl_filters(callback_with_info, KAL_TRUE, 0, filter_cnt, 0, matched_filter_idx_v6, IPC_UT_NETID_START);
+
+        ipc_ut_reset_dl_filter_info();
+        ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                    0,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    ipv6_cnt,
+                                    ipv6_cnt-1,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    (unite == 0)?0:10,
+                                    alignment,
+                                    &head_gpd,&tail_gpd,
+                                    NULL,
+                                    NULL,
+                                    spd,
+                                    KAL_FALSE,
+                                    spd_position);
+
+        session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                                            ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                                                               IPC_IP_TYPE_MIXED) );
+
+        ipc_do_dl_filter(session_type, IPC_UT_NETID_START, IPC_UT_PDN_ID, &head_gpd, &tail_gpd);
+
+        if (callback_with_info) {
+            if (ipc_ut_dl_filter_info.netif_id != IPC_UT_NETID_START) {
+                utELOG("IPv6 filter test case failed! (NetIF ID match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(0, filter_cnt);
+                return KAL_FALSE;
+            }
+        } else {
+            if (ipc_ut_dl_filter_info.netif_id != 0) {
+                utELOG("IPv6 filter test case failed! (NetIF ID match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(0, filter_cnt);
+                return KAL_FALSE;
+            }
+        }
+
+        if (ipc_ut_dl_filter_id != matched_filter_idx_v6) {
+            utELOG("IPv6 filter test case failed! (Filter ID match fail)\r\n");
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_dl_filters(0, filter_cnt);
+            return KAL_FALSE;
+        }
+
+        if (1 == spd) {
+            if ((0 == ipv4_cnt) && (1 == ipv6_cnt)) {
+                /* Only ipv6 DHCP packet left, so there is no SPD */
+                total_cnt = ipv4_cnt + ipv6_cnt - 1;
+                spd_payload_cnt = 0;
+            } else {
+                total_cnt = ipv4_cnt + ipv6_cnt - 1/*dhcp*/ + 1/*spd*/;
+                spd_payload_cnt = ipv4_cnt + ipv6_cnt - 1/*dhcp*/;
+            }
+            if (NULL == ipc_ut_dl_head_gpd ||
+                NULL == ipc_ut_dl_tail_gpd ||
+                2 != ipc_ut_dl_filter_gpd_cnt ||
+                total_cnt != ipc_ut_gpd_list_count(head_gpd, tail_gpd) ||
+                spd_payload_cnt != ipc_ut_spd_payload_count(head_gpd, tail_gpd) ) {
+                utELOG("IPv6 filter test case failed! (with SPD)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        } else {
+            if (NULL == ipc_ut_dl_head_gpd ||
+                NULL == ipc_ut_dl_tail_gpd ||
+                ipc_ut_dl_head_gpd != ipc_ut_dl_tail_gpd ||
+                1 != ipc_ut_dl_filter_gpd_cnt ||
+                (ipv4_cnt + ipv6_cnt - 1) != ipc_ut_gpd_list_count(head_gpd, tail_gpd) ||
+                0 != ipc_ut_spd_payload_count(head_gpd, tail_gpd) ) {
+                utELOG("IPv6 filter test case failed!\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        }
+
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+        ipc_ut_uninstall_dl_filters(0, filter_cnt);
+    }
+    ipc_ut_install_netif_filter(IPC_UT_NETID_START);
+
+    for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 1; ipv6_cnt <= 16; ipv6_cnt++) {
+        ipc_ut_reset_dl_filter_info();
+        ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                    0,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    ipv6_cnt,
+                                    ipv6_cnt-1,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    0,
+                                    0,
+                                    &head_gpd,&tail_gpd,
+                                    NULL,
+                                    NULL,
+                                    0,
+                                    KAL_FALSE,
+                                    0);
+
+        session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                                            ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                                                               IPC_IP_TYPE_MIXED) );
+
+        ipc_do_dl_filter(session_type, IPC_UT_NETID_START, IPC_UT_PDN_ID, &head_gpd, &tail_gpd);
+
+        if (ipc_ut_dl_filter_info.netif_id != IPC_UT_NETID_START) {
+            utELOG("IPv4 filter test case failed! (NetIF ID match fail) (SPD:%d)\r\n", spd);
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+            return KAL_FALSE;
+        }
+        if (ipc_ut_dl_filter_id != 0) {
+            utELOG("IPv4 filter test case failed! (Filter ID match fail) (SPD:%d)\r\n", spd);
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+            return KAL_FALSE;
+        }
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+
+    }
+
+    ipc_ut_uninstall_netif_filter();
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ul_filter_and_forward_msg(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32  callback_with_info;
+    kal_uint32  ipv4_cnt;
+    kal_uint32  ipv6_cnt;
+    kal_uint32  filter_cnt;
+    qbm_gpd    *head_gpd;
+    qbm_gpd    *tail_gpd;
+    kal_uint8   session_type;
+    kal_uint8   matched_filter_idx_v4;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * (#ipv4 packets, #ipv6 packets, #ipv4 filters, #ipv6 filters)=(3, 0-3, 1-3, 0),
+     * where one of IPv4 GPD's is DHCP packet and one of IPv4 filters  is DHCP
+     * => only one GPD matched.
+     */
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 1; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+    for (filter_cnt = 1; filter_cnt < 4; filter_cnt++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < filter_cnt; matched_filter_idx_v4++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+        utDLOG("if(%d) 4Cnt(%d) 6Cnt(%d) fCnt(%d) fIdx(%d)\r\n",
+                        callback_with_info, ipv4_cnt, ipv6_cnt, filter_cnt, matched_filter_idx_v4);
+
+        ipc_ut_install_ul_filters(callback_with_info, KAL_FALSE, filter_cnt, 0, KAL_FALSE, KAL_FALSE, matched_filter_idx_v4, 0, IPC_UT_NETID_START);
+
+        ipc_ut_reset_ul_filter_info();
+        ipc_ut_prepare_ul_gpd_list(KAL_FALSE,
+                                    ipv4_cnt,
+                                    ipv4_cnt-1,
+                                    ipv6_cnt,
+                                    0,
+                                    &head_gpd,
+                                    &tail_gpd,
+                                    NULL);
+
+        session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                                            ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                                                               IPC_IP_TYPE_MIXED) );
+
+        ipc_do_ul_filter(session_type, IPC_UT_NETID_START, &head_gpd, &tail_gpd);
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (callback_with_info) {
+            if (ipc_ut_ul_filter_info.netif_id != IPC_UT_NETID_START) {
+                utELOG("IPv4 filter (MSG) test case failed! (netif_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+            if (ipc_ut_ul_filter_info.ip_id != -1) {
+                utELOG("IPv4 filter (MSG) test case failed! (ip_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+        } else {
+            if (ipc_ut_ul_filter_info.netif_id != 0) {
+                utELOG("IPv4 filter (MSG) test case failed! (netif_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+            if (ipc_ut_ul_filter_info.ip_id != -1) {
+                utELOG("IPv4 filter (MSG) test case failed! (ip_id match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+                return KAL_FALSE;
+            }
+        }
+
+        if (ipc_ut_ul_filter_id != matched_filter_idx_v4) {
+            utELOG("IPv4 filter (MSG) test case failed! (Filter ID match fail)\r\n");
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+            return KAL_FALSE;
+        }
+
+        if (NULL == ipc_ut_ul_head_gpd ||
+            NULL == ipc_ut_ul_tail_gpd ||
+            ipc_ut_ul_head_gpd != ipc_ut_ul_tail_gpd ||
+            ipc_ut_ul_filter_gpd_cnt != 1 ||
+            (ipv4_cnt + ipv6_cnt - 1) != ipc_ut_gpd_list_count(head_gpd, tail_gpd)) {
+            utELOG("IPv4 filter (MSG) test case failed!\r\n");
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+            return KAL_FALSE;
+        }
+
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+        ipc_ut_uninstall_ul_filters(filter_cnt, 0, KAL_FALSE, KAL_FALSE);
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_filter_and_forward_msg(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32  callback_with_info;
+    kal_uint32  ipv4_cnt;
+    kal_uint32  ipv6_cnt;
+    kal_uint32  filter_cnt;
+    qbm_gpd    *head_gpd;
+    qbm_gpd    *tail_gpd;
+    kal_uint8   session_type;
+    kal_uint32  alignment;
+    kal_uint32  unite;
+    kal_uint8   matched_filter_idx_v4;
+    kal_uint32  spd;
+    kal_uint32  spd_position;
+    kal_uint32  total_cnt;
+    kal_uint32  spd_payload_cnt;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * (#ipv4 packets, #ipv6 packets, #ipv4 filters, #ipv6 filters)=(3, 0-3, 1-3, 0),
+     * where one of IPv4 GPD's is DHCP packet and one of IPv4 filters  is DHCP
+     * => only one GPD matched.
+     */
+    for (unite = 0 ; unite < 2 ; unite ++)
+    for (alignment = 0 ; alignment < 4 ; alignment ++)
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 1; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+    for (filter_cnt = 1; filter_cnt < 4; filter_cnt++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < filter_cnt; matched_filter_idx_v4++)
+    for (spd = 0; spd < 1; spd++)
+//     for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+    for (spd_position = 0; spd_position < 3; spd_position++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+        if (0 == spd && 0 < spd_position) continue;
+
+        utDLOG("ui(%d) if(%d) ai(%d) 4Cnt(%d) 6Cnt(%d) fCnt(%d) fIdx(%d)\r\n",
+                        unite, callback_with_info, alignment, ipv4_cnt, ipv6_cnt, filter_cnt, matched_filter_idx_v4);
+
+        ipc_ut_install_dl_filters(callback_with_info, KAL_FALSE, filter_cnt, 0, matched_filter_idx_v4, 0, IPC_UT_NETID_START);
+
+        ipc_ut_reset_dl_filter_info();
+        ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                    ipv4_cnt-1,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    ipv6_cnt,
+                                    0,
+                                    KAL_FALSE,
+                                    KAL_FALSE,
+                                    (unite == 0)?0:10,
+                                    alignment,
+                                    &head_gpd,
+                                    &tail_gpd,
+                                    NULL,
+                                    NULL,
+                                    spd,
+                                    KAL_FALSE,
+                                    spd_position);
+
+        session_type = ( (0 == ipv4_cnt) ?  IPC_IP_TYPE_IPV6 :
+                                            ((0 == ipv6_cnt) ? IPC_IP_TYPE_IPV4 :
+                                                               IPC_IP_TYPE_MIXED) );
+
+        ipc_do_dl_filter(session_type, IPC_UT_NETID_START, IPC_UT_PDN_ID, &head_gpd, &tail_gpd);
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (callback_with_info) {
+            if (ipc_ut_dl_filter_info.netif_id != IPC_UT_NETID_START) {
+                utELOG("IPv4 filter (MSG) test case failed! (NetIF ID match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        } else {
+            if (ipc_ut_dl_filter_info.netif_id != 0) {
+                utELOG("IPv4 filter test (MSG) case failed! (NetIF ID match fail)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        }
+
+        if (ipc_ut_dl_filter_id != matched_filter_idx_v4) {
+            utELOG("IPv4 filter (MSG) test case failed! (Filter ID match fail)\r\n");
+            ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+            ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+            return KAL_FALSE;
+        }
+
+        if (1 == spd) {
+            if ((1 == ipv4_cnt) && (0 == ipv6_cnt)) {
+                /* Only ipv4 DHCP packet left, so there is no SPD */
+                total_cnt = ipv4_cnt + ipv6_cnt - 1;
+                spd_payload_cnt = 0;
+            } else {
+                total_cnt = ipv4_cnt + ipv6_cnt - 1/*dhcp*/ + 1/*spd*/;
+                spd_payload_cnt = ipv4_cnt + ipv6_cnt - 1/*dhcp*/;
+            }
+            if (NULL == ipc_ut_dl_head_gpd ||
+                NULL == ipc_ut_dl_tail_gpd ||
+                2 != ipc_ut_dl_filter_gpd_cnt ||
+                total_cnt != ipc_ut_gpd_list_count(head_gpd, tail_gpd) ||
+                spd_payload_cnt != ipc_ut_spd_payload_count(head_gpd, tail_gpd) ) {
+                utELOG("IPv4 filter (MSG) test case failed! (with SPD)\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        } else {
+            if (NULL == ipc_ut_dl_head_gpd ||
+                NULL == ipc_ut_dl_tail_gpd ||
+                ipc_ut_dl_head_gpd != ipc_ut_dl_tail_gpd ||
+                1 != ipc_ut_dl_filter_gpd_cnt ||
+                (ipv4_cnt + ipv6_cnt - 1) != ipc_ut_gpd_list_count(head_gpd, tail_gpd) ||
+                0 != ipc_ut_spd_payload_count(head_gpd, tail_gpd) ) {
+                utELOG("IPv4 filter (MSG) test case failed!\r\n");
+                ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+                return KAL_FALSE;
+            }
+        }
+
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+        ipc_ut_uninstall_dl_filters(filter_cnt, 0);
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_gpd_copy(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    qbm_gpd    *head_gpd;
+    qbm_gpd    *tail_gpd;
+    qbm_gpd    *bd;
+    kal_uint8  *dataptr;
+    kal_uint32  idx;
+    kal_uint32  total_len = 0;
+    kal_bool    result;
+    static      kal_uint8 _dst_buf[256];
+    static      kal_uint32 _copied;
+
+    // init before test
+    ipc_ut_init();
+
+     /*
+         *   Reset IPCore before test
+         */
+     if (KAL_TRUE != ipc_reset()) {
+         utELOG("ipc_reset() FAIL!\r\n");
+         return KAL_FALSE;
+     }
+
+    /*
+     * GPD list.
+     */
+    if (2 != qbmt_alloc_q(
+                        QBM_TYPE_NET_DL,
+                        2,
+                        (void**)&head_gpd,
+                        (void**)&tail_gpd)) {
+        UT_ASSERT(KAL_FALSE);
+        return KAL_FALSE;
+    }
+
+    bd = (qbm_gpd *)QBM_DES_GET_DATAPTR(head_gpd);
+    dataptr = (kal_uint8 *)QBM_DES_GET_DATAPTR(bd);
+    for (idx = 0; idx < 100; idx++) {
+        *(dataptr + idx) = (kal_uint8)(total_len + idx);
+    }
+    total_len += idx;
+    QBM_DES_SET_DATALEN(bd, idx);
+    QBM_DES_SET_DATALEN(head_gpd, idx);
+
+    bd = (qbm_gpd *)QBM_DES_GET_DATAPTR(tail_gpd);
+    dataptr = (kal_uint8 *)QBM_DES_GET_DATAPTR(bd);
+    for (idx = 0; idx < 100; idx++) {
+        *(dataptr + idx) = (kal_uint8)(total_len + idx);
+    }
+    total_len += idx;
+    QBM_DES_SET_DATALEN(bd, idx);
+    QBM_DES_SET_DATALEN(tail_gpd, idx);
+
+    kal_mem_set(_dst_buf, 0, sizeof(_dst_buf));
+    result = ipc_gpd_copy(_dst_buf, sizeof(_dst_buf), &_copied, head_gpd, tail_gpd);
+    if (!result || _copied != total_len) {
+        utELOG("[G] ipc_gpd_copy() returns KAL_FALSE or wrong length copied!\r\n");
+        qbmt_dest_q(head_gpd, tail_gpd);
+        return KAL_FALSE;
+    }
+    for (idx = 0; idx < total_len; idx++) {
+        if (*(_dst_buf + idx) != (kal_uint8)idx) {
+            utELOG("[G] ipc_gpd_copy() buffer copied is wrong!\r\n");
+            qbmt_dest_q(head_gpd, tail_gpd);
+            return KAL_FALSE;
+        }
+    }
+
+    /*
+     * BD list.
+     */
+    bd = (qbm_gpd *)QBM_DES_GET_DATAPTR(head_gpd);
+    QBM_DES_SET_NEXT(bd, tail_gpd);
+    QBM_DES_CLR_EOL(bd);
+    bd = (qbm_gpd *)QBM_DES_GET_DATAPTR(tail_gpd);
+    kal_mem_cpy(tail_gpd, bd, sizeof(qbm_gpd));
+    QBM_DES_SET_DATALEN(head_gpd, total_len);
+
+    kal_mem_set(_dst_buf, 0, sizeof(_dst_buf));
+    result = ipc_gpd_copy(_dst_buf, sizeof(_dst_buf), &_copied, head_gpd, head_gpd);
+    if (!result || _copied != total_len) {
+        utELOG("[B] ipc_gpd_copy() returns KAL_FALSE or wrong length copied!\r\n");
+        qbmt_dest_q(head_gpd, head_gpd);
+        return KAL_FALSE;
+    }
+    for (idx = 0; idx < total_len; idx++) {
+        if (*(_dst_buf + idx) != (kal_uint8)idx) {
+            utELOG("[B] ipc_gpd_copy() buffer copied is wrong!\r\n");
+            qbmt_dest_q(head_gpd, head_gpd);
+            return KAL_FALSE;
+        }
+    }
+
+    qbmt_dest_q(head_gpd, head_gpd);
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_send_ul_pkt(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint8  *ip_header;
+    kal_uint32  total_length;
+    kal_uint8  *udp_header;
+    kal_uint32  udp_length;
+    kal_uint32  ul_total_length;
+    kal_bool    result;
+
+    kal_uint32  to_generate_hdr;
+    ipc_pkt_t   pkt;
+    ipc_hdr_t   hdr;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for ( to_generate_hdr = 0 ; to_generate_hdr < 2 ; to_generate_hdr ++ ) {
+        qbm_gpd    *curr_gpd;
+        kal_uint32 isGPD;
+        kal_uint32 pktcnt;
+        kal_uint32 alignment;
+
+        ip_header = ipc_ut_ipv4_dns_packet;
+        total_length = sizeof(ipc_ut_ipv4_dns_packet);
+        udp_header = IPC_HDR_V4_GET_NHPTR(ip_header);
+        udp_length = total_length - IPC_HDR_V4_GET_IHL(ip_header);
+
+        for (alignment = 0 ; alignment < 4 ; alignment ++)
+        for (isGPD = 0 ; isGPD < 2 ; isGPD ++)
+        for (pktcnt = 1 ; pktcnt < 4 ; pktcnt ++) {
+            /* IP/UDP Header information */
+            hdr.ip_type = IPC_IP_TYPE_IPV4;
+            hdr.src_addr = IPC_HDR_V4_GET_SRC_ADDR(ip_header);
+            hdr.dst_addr = IPC_HDR_V4_GET_DST_ADDR(ip_header);
+            hdr.src_port = IPC_HDR_UDP_GET_SRC_PORT(udp_header);
+            hdr.dst_port = IPC_HDR_UDP_GET_DST_PORT(udp_header);
+            hdr.dscp_tc = 0;
+
+            /* Generate Packet */
+            if (0 == isGPD) {
+                pkt.isGPD       = KAL_FALSE;
+                pkt.data        = (0 == to_generate_hdr) ? ip_header : udp_header + IPC_HDR_UDP_HEADER_SIZE;
+                pkt.data_len    = (0 == to_generate_hdr) ? total_length : udp_length - IPC_HDR_UDP_HEADER_SIZE;
+            } else {
+                pkt.isGPD = KAL_TRUE;
+                /* Using "dl_gpd_list" preparing to generate packet (which is more suitable for this case) */
+                ipc_ut_prepare_dl_gpd_list(pktcnt,
+                                                0,
+                                                KAL_TRUE,
+                                                (0 == to_generate_hdr)?KAL_TRUE:KAL_FALSE,
+                                                0,
+                                                0,
+                                                KAL_FALSE,
+                                                KAL_FALSE,
+                                                0,  /* We does NOT divide packet in pieces for following comparison */
+                                                alignment,
+                                                &(pkt.head),
+                                                &(pkt.tail),
+                                                NULL,
+                                                NULL,
+                                                KAL_FALSE,
+                                                KAL_FALSE,
+                                                0);
+            }
+
+            result = ipc_send_ul_pkt(
+                        &pkt,
+                        (0 == to_generate_hdr)?NULL:&hdr,
+                        IPC_UT_UL_EBI);
+
+            if (!result) {
+                utELOG("[4] ipc_send_ul_pkt() failed!\r\n");
+                return KAL_FALSE;
+            }
+            if (NULL == ipc_ut_ul_ebi_head_gpd || NULL == ipc_ut_ul_ebi_tail_gpd) {
+                utELOG("[4] ipc_send_ul_pkt() failed! no UL SDU sent.\r\n");
+                return KAL_FALSE;
+            }
+
+            /* Run GPD copy and content check */
+            curr_gpd = ipc_ut_ul_ebi_head_gpd;
+            do {
+                if (!ipc_gpd_copy(ipc_ut_checksum_buf_s,
+                                  sizeof(ipc_ut_checksum_buf_s),
+                                  &ul_total_length,
+                                  curr_gpd,
+                                  curr_gpd)) {
+                    utELOG("[4] ipc_gpd_copy() failed!\r\n");
+                    return KAL_FALSE;
+                }
+                if (ul_total_length != total_length) {
+                    utELOG("[4] ipc_send_ul_pkt() IPv4 total_length mismatched!\r\n");
+                    return KAL_FALSE;
+                }
+                if ( !IPC_HDR_IS_V4(ipc_ut_checksum_buf_s) ||
+                     total_length != IPC_HDR_V4_GET_TOTAL_LENGTH(ipc_ut_checksum_buf_s) ||
+                     !IPC_EQ_V4_ADDR(IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_checksum_buf_s), IPC_HDR_V4_GET_SRC_ADDR(ip_header)) ||
+                     !IPC_EQ_V4_ADDR(IPC_HDR_V4_GET_DST_ADDR(ipc_ut_checksum_buf_s), IPC_HDR_V4_GET_DST_ADDR(ip_header)) ||
+                     IPC_HDR_PROT_UDP != IPC_HDR_V4_GET_PROTOCOL(ipc_ut_checksum_buf_s) ||
+                     0 != ipc_utils_calc_ipv4_checksum(ipc_ut_checksum_buf_s) ) {
+                    utELOG("[4] ipc_send_ul_pkt() wrong IPv4 header!\r\n");
+                    return KAL_FALSE;
+                }
+                if ( kal_mem_cmp(IPC_HDR_V4_GET_NHPTR(ipc_ut_checksum_buf_s), udp_header, udp_length) ) {
+                    utELOG("[4] ipc_send_ul_pkt() UDP header or data mismatched!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Check next GPD */
+                if (ipc_ut_ul_ebi_tail_gpd == curr_gpd) {
+                    curr_gpd = NULL;
+                } else {
+                    curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+                }
+            } while (curr_gpd);
+
+            /* Free GPD list */
+            qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+            ipc_ut_ul_ebi_head_gpd = NULL;
+            ipc_ut_ul_ebi_tail_gpd = NULL;
+        }
+
+        ip_header = ipc_ut_ipv6_mdns_packet;
+        total_length = sizeof(ipc_ut_ipv6_mdns_packet);
+        udp_header = IPC_HDR_V6_GET_NHPTR(ip_header);
+        udp_length = total_length - IPC_HDR_V6_HEADER_SIZE;
+
+        for (alignment = 0 ; alignment < 4 ; alignment ++)
+        for (isGPD = 0 ; isGPD < 2 ; isGPD ++)
+        for (pktcnt = 1 ; pktcnt < 4 ; pktcnt ++) {
+            /* IP/UDP Header information */
+            hdr.ip_type = IPC_IP_TYPE_IPV6;
+            hdr.src_addr = IPC_HDR_V6_GET_SRC_ADDR(ip_header);
+            hdr.dst_addr = IPC_HDR_V6_GET_DST_ADDR(ip_header);
+            hdr.src_port = IPC_HDR_UDP_GET_SRC_PORT(udp_header);
+            hdr.dst_port = IPC_HDR_UDP_GET_DST_PORT(udp_header);
+            hdr.dscp_tc = 0;
+
+            /* Generate Packet */
+            if (0 == isGPD) {
+                pkt.isGPD       = KAL_FALSE;
+                pkt.data        = (0 == to_generate_hdr) ? ip_header : (udp_header + IPC_HDR_UDP_HEADER_SIZE);
+                pkt.data_len    = (0 == to_generate_hdr) ? total_length : udp_length - IPC_HDR_UDP_HEADER_SIZE;
+
+            } else {
+                pkt.isGPD = KAL_TRUE;
+                /* Using "dl_gpd_list" preparing to generate packet (which is more suitable for this case) */
+                ipc_ut_prepare_dl_gpd_list(0,
+                                                0,
+                                                KAL_FALSE,
+                                                KAL_FALSE,
+                                                pktcnt,
+                                                0,
+                                                KAL_TRUE,
+                                                (0 == to_generate_hdr)?KAL_TRUE:KAL_FALSE,
+                                                0, /* We does NOT divide packet in pieces for following comparison */
+                                                alignment,
+                                                &(pkt.head),
+                                                &(pkt.tail),
+                                                NULL,
+                                                NULL,
+                                                KAL_FALSE,
+                                                KAL_FALSE,
+                                                0);
+            }
+
+            result = ipc_send_ul_pkt(
+                        &pkt,
+                        (0 == to_generate_hdr)?NULL:&hdr,
+                        IPC_UT_UL_EBI);
+
+            if (!result) {
+                utELOG("[6] ipc_send_ul_pkt() failed!\r\n");
+                return KAL_FALSE;
+            }
+            if (NULL == ipc_ut_ul_ebi_head_gpd || NULL == ipc_ut_ul_ebi_tail_gpd) {
+                utELOG("[6] ipc_send_ul_pkt() failed! no UL SDU sent.\r\n");
+                return KAL_FALSE;
+            }
+
+            /* Run GPD copy and content check */
+            curr_gpd = ipc_ut_ul_ebi_head_gpd;
+            do {
+                if (!ipc_gpd_copy(ipc_ut_checksum_buf_s,
+                                  sizeof(ipc_ut_checksum_buf_s),
+                                  &ul_total_length,
+                                  curr_gpd,
+                                  curr_gpd)) {
+                    utELOG("[6] ipc_gpd_copy() failed!\r\n");
+                    return KAL_FALSE;
+                }
+                if (ul_total_length != total_length) {
+                    utELOG("[6] ipc_send_ul_pkt() IPv6 total_length mismatched!\r\n");
+                    return KAL_FALSE;
+                }
+                if ( !IPC_HDR_IS_V6(ipc_ut_checksum_buf_s) ||
+                     !IPC_EQ_V6_ADDR(IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_checksum_buf_s), IPC_HDR_V6_GET_SRC_ADDR(ip_header)) ||
+                     !IPC_EQ_V6_ADDR(IPC_HDR_V6_GET_DST_ADDR(ipc_ut_checksum_buf_s), IPC_HDR_V6_GET_DST_ADDR(ip_header)) ||
+                     IPC_HDR_PROT_UDP != IPC_HDR_V6_GET_NH_TYPE(ipc_ut_checksum_buf_s) ) {
+                    utELOG("[6] ipc_send_ul_pkt() wrong IPv6 header!\r\n");
+                    return KAL_FALSE;
+                }
+                if ( kal_mem_cmp(IPC_HDR_V6_GET_NHPTR(ipc_ut_checksum_buf_s), udp_header, udp_length) ) {
+                    utELOG("[6] ipc_send_ul_pkt() UDP header or data mismatched!\r\n");
+                    return KAL_FALSE;
+                }
+                if (ipc_ut_ul_ebi_tail_gpd == curr_gpd) {
+                    curr_gpd = NULL;
+                } else {
+                    curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+                }
+            } while (curr_gpd);
+
+            /* Free GPD list */
+            qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+            ipc_ut_ul_ebi_head_gpd = NULL;
+            ipc_ut_ul_ebi_tail_gpd = NULL;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_send_dl_pkt(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32  netif_exist;
+    kal_uint32  idx;
+    kal_uint32  failNetifIdOffset;
+    kal_uint32  to_generate_hdr;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for ( netif_exist = 0 ; netif_exist < 2 ; netif_exist ++ )
+    for ( idx = 0 ; idx < 2 ; idx ++ )
+    for ( failNetifIdOffset = 0 ; failNetifIdOffset < 2 ; failNetifIdOffset ++ )
+    for ( to_generate_hdr = 0 ; to_generate_hdr < 2 ; to_generate_hdr ++ ) {
+        kal_bool        result;
+        ipc_ut_netif_t  *net;
+
+        if (netif_exist) {
+            /*
+                        * ipc_attach()
+                        */
+            net = &(ipc_ut_nets_s[0]);
+            kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+            net->conf.module_id = MOD_IPCORE;
+            net->conf.netif_id = IPC_UT_NETID_START + idx;
+            net->conf.ul_reload_context = net;
+            net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+            net->conf.callback_context = net;
+            net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+            net->conf.features = 0;
+            result = ipc_attach(&net->conf, &net->handle);
+            if (!result) {
+                utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+                return KAL_FALSE;
+            }
+        }
+
+        /* For IPv4 */
+        {
+            kal_uint32 isGPD;
+            kal_uint32 pktcnt;
+            ipc_pkt_t  pkt;
+            ipc_hdr_t  hdr;
+            kal_uint32 alignment;
+            kal_uint32 unite;
+
+            kal_uint8  *ip_header;
+            kal_uint32  total_length;
+            kal_uint8  *udp_header;
+            kal_uint32  udp_length;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (isGPD = 0 ; isGPD < 2 ; isGPD ++)
+            for (pktcnt = 1 ; pktcnt < 4 ; pktcnt ++) {
+                ip_header = ipc_ut_ipv4_dhcp_packet;
+                total_length = sizeof(ipc_ut_ipv4_dhcp_packet);
+                udp_header = IPC_HDR_V4_GET_NHPTR(ip_header);
+                udp_length = total_length - IPC_HDR_V4_GET_IHL(ip_header);
+
+                /* IP/UDP Header information */
+                hdr.ip_type = IPC_IP_TYPE_IPV4;
+                hdr.src_addr = IPC_HDR_V4_GET_SRC_ADDR(ip_header);
+                hdr.dst_addr = IPC_HDR_V4_GET_DST_ADDR(ip_header);
+                hdr.src_port = IPC_HDR_UDP_GET_SRC_PORT(udp_header);
+                hdr.dst_port = IPC_HDR_UDP_GET_DST_PORT(udp_header);
+                hdr.dscp_tc = 0;
+
+                /* Generate Packet */
+                if (0 == isGPD) {
+                    pkt.isGPD       = KAL_FALSE;
+                    pkt.data        = (0 == to_generate_hdr) ? ip_header : udp_header + IPC_HDR_UDP_HEADER_SIZE;
+                    pkt.data_len    = (0 == to_generate_hdr) ? total_length : udp_length - IPC_HDR_UDP_HEADER_SIZE;
+                } else {
+                    pkt.isGPD = KAL_TRUE;
+                    ipc_ut_prepare_dl_gpd_list(pktcnt,
+                                                    0,
+                                                    KAL_TRUE,
+                                                    (0 == to_generate_hdr)?KAL_TRUE:KAL_FALSE,
+                                                    0,
+                                                    0,
+                                                    KAL_FALSE,
+                                                    KAL_FALSE,
+                                                    (unite == 0)?0:10,
+                                                    alignment,
+                                                    &(pkt.head),
+                                                    &(pkt.tail),
+                                                    NULL,
+                                                    NULL,
+                                                    KAL_FALSE,
+                                                    KAL_FALSE,
+                                                    0);
+                }
+
+                ipc_ut_set_error(IPC_UT_NO_ERROR);
+                ipc_ut_reset_dl_callback_info();
+
+                result = ipc_send_dl_pkt(
+                            &pkt,
+                            (0 == to_generate_hdr)?NULL:&hdr,
+                            (netif_exist)?(net->conf.netif_id + failNetifIdOffset):IPC_UT_NETID_START);
+
+                if ((!netif_exist) || failNetifIdOffset) {   /* DL packet sending should be failed */
+                    if (KAL_FALSE != result) {
+                        utELOG("[4] ipc_send_dl_pkt() should be failed with error code [IPC_UT_DL_PKT_NETIF_NOT_FOUND]!\r\n");
+                        return KAL_FALSE;
+                    }
+                } else {   /* DL packet sending should be success */
+                    if (!result) {
+                        utELOG("[4] ipc_send_dl_pkt() failed!\r\n");
+                        return KAL_FALSE;
+                    }
+
+                    if (    ((isGPD == 0) && (ipc_ut_dl_callback_gpd_cnt != 1)) ||
+                            ((isGPD != 0) && (ipc_ut_dl_callback_gpd_cnt != pktcnt))) {
+                        utELOG("[4] ipc_send_dl_pkt() failed! DL packet count is not correct!\r\n");
+                        return KAL_FALSE;
+                    }
+                }
+            }
+        }
+
+        /* For IPv6 */
+        {
+            kal_uint32 isGPD;
+            kal_uint32 pktcnt;
+            ipc_pkt_t  pkt;
+            ipc_hdr_t  hdr;
+            kal_uint32 alignment;
+            kal_uint32 unite;
+
+            kal_uint8  *ip_header;
+            kal_uint32  total_length;
+            kal_uint8  *udp_header;
+            kal_uint32  udp_length;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (isGPD = 0 ; isGPD < 2 ; isGPD ++)
+            for (pktcnt = 1 ; pktcnt < 4 ; pktcnt ++) {
+                ip_header = ipc_ut_ipv6_dhcp_packet;
+                total_length = sizeof(ipc_ut_ipv6_dhcp_packet);
+                udp_header = IPC_HDR_V4_GET_NHPTR(ip_header);
+                udp_length = total_length - IPC_HDR_V4_GET_IHL(ip_header);
+
+                /* IP/UDP Header information */
+                hdr.ip_type = IPC_IP_TYPE_IPV6;
+                hdr.src_addr = IPC_HDR_V6_GET_SRC_ADDR(ip_header);
+                hdr.dst_addr = IPC_HDR_V6_GET_DST_ADDR(ip_header);
+                hdr.src_port = IPC_HDR_UDP_GET_SRC_PORT(udp_header);
+                hdr.dst_port = IPC_HDR_UDP_GET_DST_PORT(udp_header);
+                hdr.dscp_tc = 0;
+
+                /* Generate Packet */
+                if (0 == isGPD) {
+                    pkt.isGPD       = KAL_FALSE;
+                    pkt.data        = (0 == to_generate_hdr) ? ip_header : udp_header + IPC_HDR_UDP_HEADER_SIZE;
+                    pkt.data_len    = (0 == to_generate_hdr) ? total_length : udp_length - IPC_HDR_UDP_HEADER_SIZE;
+                } else {
+                    pkt.isGPD = KAL_TRUE;
+                    ipc_ut_prepare_dl_gpd_list(0,
+                                                    0,
+                                                    KAL_FALSE,
+                                                    KAL_FALSE,
+                                                    pktcnt,
+                                                    0,
+                                                    KAL_TRUE,
+                                                    (0 == to_generate_hdr)?KAL_TRUE:KAL_FALSE,
+                                                    (unite == 0)?0:10,
+                                                    alignment,
+                                                    &(pkt.head),
+                                                    &(pkt.tail),
+                                                    NULL,
+                                                    NULL,
+                                                    KAL_FALSE,
+                                                    KAL_FALSE,
+                                                    0);
+                }
+
+                ipc_ut_set_error(IPC_UT_NO_ERROR);
+                ipc_ut_reset_dl_callback_info();
+
+                result = ipc_send_dl_pkt(
+                            &pkt,
+                            (0 == to_generate_hdr)?NULL:&hdr,
+                            (netif_exist)?(net->conf.netif_id + failNetifIdOffset):IPC_UT_NETID_START);
+
+                if ((!netif_exist) || failNetifIdOffset) {   /* DL packet sending should be failed */
+                    if (KAL_FALSE != result) {
+                        utELOG("[6] ipc_send_dl_pkt() should be failed with error code [IPC_UT_DL_PKT_NETIF_NOT_FOUND]!\r\n");
+                        return KAL_FALSE;
+                    }
+                } else {   /* DL packet sending should be success */
+                    if (!result) {
+                        utELOG("[6] ipc_send_dl_pkt() failed!\r\n");
+                        return KAL_FALSE;
+                    }
+
+                    if (    ((isGPD == 0) && (ipc_ut_dl_callback_gpd_cnt != 1)) ||
+                            ((isGPD != 0) && (ipc_ut_dl_callback_gpd_cnt != pktcnt))) {
+                        utELOG("[6] ipc_send_dl_pkt() failed! DL packet count is not correct!\r\n");
+                        return KAL_FALSE;
+                    }
+                }
+            }
+        }
+
+        /* For MIX */
+        {
+            kal_uint32 alignment;
+            kal_uint32 ipv4Pktcnt;
+            kal_uint32 ipv6Pktcnt;
+            ipc_pkt_t  pkt;
+            kal_uint32 unite;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4Pktcnt = 0 ; ipv4Pktcnt <= 4 ; ipv4Pktcnt ++)
+            for (ipv6Pktcnt = 0 ; ipv6Pktcnt <= 4 ; ipv6Pktcnt ++) {
+                /*
+                                For MIX case : it should be GPD list without generating header
+                            */
+                if (to_generate_hdr) {continue;}
+
+                /* Generate Packet */
+                {
+                    pkt.isGPD = KAL_TRUE;
+                    ipc_ut_prepare_dl_gpd_list(ipv4Pktcnt,
+                                                    0,
+                                                    KAL_TRUE,
+                                                    KAL_TRUE,
+                                                    ipv6Pktcnt,
+                                                    0,
+                                                    KAL_TRUE,
+                                                    KAL_TRUE,
+                                                    (unite == 0)?0:10,
+                                                    alignment,
+                                                    &(pkt.head),
+                                                    &(pkt.tail),
+                                                    NULL,
+                                                    NULL,
+                                                    KAL_FALSE,
+                                                    KAL_FALSE,
+                                                    0);
+                }
+
+                ipc_ut_set_error(IPC_UT_NO_ERROR);
+                ipc_ut_reset_dl_callback_info();
+
+                result = ipc_send_dl_pkt(
+                            &pkt,
+                            NULL,
+                            (netif_exist)?(net->conf.netif_id + failNetifIdOffset):IPC_UT_NETID_START);
+
+                if ((!netif_exist) || failNetifIdOffset) {   /* DL packet sending should be failed */
+                    if (KAL_FALSE != result) {
+                        utELOG("[MIX] ipc_send_dl_pkt() should be failed with error code [IPC_UT_DL_PKT_NETIF_NOT_FOUND]!\r\n");
+                        return KAL_FALSE;
+                    }
+                } else {   /* DL packet sending should be success */
+                    if (!result) {
+                        utELOG("[MIX] ipc_send_dl_pkt() failed!\r\n");
+                        return KAL_FALSE;
+                    }
+
+                    if (ipc_ut_dl_callback_gpd_cnt != (ipv4Pktcnt + ipv6Pktcnt)) {
+                        utELOG("[MIX] ipc_send_dl_pkt() failed! DL packet count is not correct!\r\n");
+                        return KAL_FALSE;
+                    }
+                }
+            }
+        }
+
+        /*
+                * ipc_detach().
+                */
+        if (netif_exist) {
+            result = ipc_detach(net->handle);
+            if (!result) {
+                utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+                return KAL_FALSE;
+            }
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ul_throttle(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32                          ipv4_cnt;
+    kal_uint32                          blocked_cnt = 0;
+    qbm_gpd                            *head_gpd, *head_gpd_latency;
+    qbm_gpd                            *tail_gpd, *tail_gpd_latency;
+    ipc_io_request_t                   *ior, *ior_latency;
+    ipc_ut_netif_t                     *net, *net_latency;
+    kal_bool                            result;
+    kal_uint32                          idx = 1;
+    ipcore_upcm_pdn_bind_ind_struct    *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct   *deact_req;
+    kal_uint8                           ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    ipc_ul_throttle_conf_t              conf = {0};
+    tmc_ctrl_config                     tmc_cfg = {0};
+    kal_uint32                          conf_in_int = 0;
+    ipc_set_ul_throttle_param_t        *p_ipc_ul_thrott_cfg = NULL;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_UT_NETID_START;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    net_latency = &(ipc_ut_nets_s[1]);
+    kal_mem_set(net_latency, 0, sizeof(ipc_ut_netif_t));
+    net_latency->conf.module_id = MOD_IPCORE;
+    net_latency->conf.netif_id = IPC_UT_NETID_START + 1;
+    net_latency->conf.ul_reload_context = net_latency;
+    net_latency->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net_latency->conf.callback_context = net_latency;
+    net_latency->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net_latency->conf.features |= IPC_F_LATENCY_CONCERN;
+    result = ipc_attach(&net_latency->conf, &net_latency->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* PDN activation. */
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = net->conf.netif_id;
+    bind_req->pdn_id = IPC_UT_PDN_ID;
+    bind_req->ip_addr.ip_addr_type = ip_types[idx];
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+    free_local_para((local_para_struct *)bind_req);
+
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = net_latency->conf.netif_id;
+    bind_req->pdn_id = IPC_UT_PDN_ID_2;
+    bind_req->ip_addr.ip_addr_type = ip_types[idx];
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+    free_local_para((local_para_struct *)bind_req);
+
+    /* Enable UL Throttle */
+#if defined(__MD93__)
+    kal_mem_set(&conf, 0, sizeof(ipc_ul_throttle_conf_t));
+    conf.enabled = 1;
+    conf.active_period_100ms = 10;
+    conf.suspend_period_100ms = 10;
+    kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+    tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+    p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+    UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+    p_ipc_ul_thrott_cfg->conf.enabled = KAL_TRUE;
+    p_ipc_ul_thrott_cfg->conf.active_period_100ms = 10;
+    p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 10;
+    p_ipc_ul_thrott_cfg->conf.features = 0;
+    ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+    free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     * TEST CASE 1: Basic
+     * Throttle active mode.
+     * Both netifs should forward GPDs to network without blocking.
+     */
+    {
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            ipc_uplink(net->handle, ior);
+            ipc_uplink(net_latency->handle, ior_latency);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if (ipv4_cnt + ipv4_cnt != ipc_ut_ul_gpd_cnt) {
+                utELOG("GPD is not forwarded to network correctly when active mode!\r\r");
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            /* Free GPD after test */
+            ipc_ut_free_gpd_list(NULL, NULL);
+        }
+    }
+
+    /* Throttling Mode: ACTIVE -> SUSPEND*/
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_TIMER_EXPIRY, /* msg_id */
+              NULL, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     * TEST CASE 1: Basic
+     * Throttle suspend mode.
+     * Netif_1 should be throttled, while netif_2 should be able to forward GPDs.
+     */
+    {
+        blocked_cnt = 0;
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            ipc_uplink(net->handle, ior);
+            ipc_uplink(net_latency->handle, ior_latency);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if (ipv4_cnt != ipc_ut_ul_gpd_cnt) {
+                utELOG("GPD is not forwarded to network correctly when suspend mode!\r\r");
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            blocked_cnt += ipv4_cnt;
+
+            /* Free GPD after test */
+            ipc_ut_free_gpd_list(NULL, NULL);
+        }
+    }
+
+    /*
+     * TEST CASE 1: Basic
+     * Throttle resume to active mode
+     * The blocked GPDs should be forwarded automatically.
+     */
+    {
+        ipc_ut_reset_ul_info();
+
+        /* Throttling Mode: SUSPEND -> ACTIVE*/
+        msg_send6(MOD_NIL, /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  MSG_ID_TIMER_EXPIRY, /* msg_id */
+                  NULL, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (blocked_cnt != ipc_ut_ul_gpd_cnt) {
+            utELOG("The blocked GPDs are not forwarded to network automatically when active mode.!\r\r");
+            ipc_ut_free_gpd_list(NULL, NULL);
+            return KAL_FALSE;
+        }
+
+        /* Free GPD after test */
+        ipc_ut_free_gpd_list(NULL, NULL);
+    }
+
+    /* Throttling Mode: ACTIVE -> SUSPEND*/
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_TIMER_EXPIRY, /* msg_id */
+              NULL, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     * TEST CASE 1: Basic
+     * Throttle suspend mode case 2.
+     * When throttling is turning off, it should send ilm MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ to ipcore.
+     */
+    {
+        blocked_cnt = 0;
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            ipc_uplink(net->handle, ior);
+            ipc_uplink(net_latency->handle, ior_latency);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if (ipv4_cnt != ipc_ut_ul_gpd_cnt) {
+                utELOG("GPD is not forwarded to network correctly when suspend mode!\r\r");
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            blocked_cnt += ipv4_cnt;
+
+            /* Free GPD after test */
+            ipc_ut_free_gpd_list(NULL, NULL);
+        }
+
+        ipc_ut_reset_ul_info();
+
+        /*
+         * Diable UL throttle
+         */
+#if defined(__MD93__)
+        conf.enabled = 0;
+        kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+        tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+        p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+        UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+        p_ipc_ul_thrott_cfg->conf.enabled = KAL_FALSE;
+        p_ipc_ul_thrott_cfg->conf.active_period_100ms = 10;
+        p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 10;
+        p_ipc_ul_thrott_cfg->conf.features = 0;
+        ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+        free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (blocked_cnt != ipc_ut_ul_gpd_cnt) {
+            utELOG("The blocked GPDs are not forwarded to network automatically when throttling is turning off!\r\r");
+            ipc_ut_free_gpd_list(NULL, NULL);
+            return KAL_FALSE;
+        }
+
+        /* Free GPD after test */
+        ipc_ut_free_gpd_list(NULL, NULL);
+    }
+
+    /*
+     * TEST CASE 2: IMS Basic
+     * Throttling v2: IMS may be blocked.
+     * Enable UL Throttle (with blocking IMS)
+     */
+#if defined(__MD93__)
+    conf.enabled = 1;
+    conf.active_period_100ms = 1;
+    conf.suspend_period_100ms = 255;
+    conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+    tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+    p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+    UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+    p_ipc_ul_thrott_cfg->conf.enabled = KAL_TRUE;
+    p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+    p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+    p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+    free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     * TEST CASE 2: IMS Basic
+     * Throttle SUSPEND-FOREVER mode.
+     * Both netifs should be throttled, and no packet is forwarded.
+     */
+    {
+        blocked_cnt = 0;
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            ipc_uplink(net->handle, ior);
+            ipc_uplink(net_latency->handle, ior_latency);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if (0 != ipc_ut_ul_gpd_cnt) {
+                utELOG("(IMS) GPD is not forwarded to network correctly when suspend mode!\r\r");
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            blocked_cnt += ipv4_cnt + ipv4_cnt;
+
+            /* Free GPD after test */
+            ipc_ut_free_gpd_list(NULL, NULL);
+        }
+    }
+
+    /*
+     * TEST CASE 2: IMS Basic
+     * Turn off throttling.
+     * The blocked GPDs should be forwarded automatically.
+     */
+    {
+        ipc_ut_reset_ul_info();
+
+        /*
+         * Diable UL throttle
+         */
+#if defined(__MD93__)
+        conf.enabled = 0;
+        kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+        tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+        p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+        UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+        p_ipc_ul_thrott_cfg->conf.enabled = KAL_FALSE;
+        p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+        p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+        p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+        ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+        free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (blocked_cnt != ipc_ut_ul_gpd_cnt) {
+            utELOG("(IMS) The blocked GPDs are not forwarded to network automatically when active mode.!\r\r");
+            ipc_ut_free_gpd_list(NULL, NULL);
+            return KAL_FALSE;
+        }
+
+        /* Free GPD after test */
+        ipc_ut_free_gpd_list(NULL, NULL);
+    }
+
+    /*
+     * TEST CASE 2: IMS Basic
+     * Throttling v2: IMS may be blocked.
+     * Case 2: packets from ipc_send_ul_pkt should be blocked as well.
+     */
+
+#if defined(__MD93__)
+    conf.enabled = 1;
+    conf.active_period_100ms = 1;
+    conf.suspend_period_100ms = 255;
+    conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+    tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+    p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+    UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+    p_ipc_ul_thrott_cfg->conf.enabled = KAL_TRUE;
+    p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+    p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+    p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+    free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     * TEST CASE 2: IMS Basic
+     * Throttle suspend mode case 2.
+     * Packets from ipc_send_ul_pkt should be blocked as well.
+     */
+    {
+        ipc_pkt_t pkt_ebi, pkt_pdn;
+
+        blocked_cnt = 0;
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            /* Prepare ipc_pkt_t */
+            kal_mem_set(&pkt_ebi, 0, sizeof(ipc_pkt_t));
+            pkt_ebi.isGPD = KAL_TRUE;
+            pkt_ebi.head = head_gpd;
+            pkt_ebi.tail = tail_gpd;
+
+            kal_mem_set(&pkt_pdn, 0, sizeof(ipc_pkt_t));
+            pkt_pdn.isGPD = KAL_TRUE;
+            pkt_pdn.head = head_gpd_latency;
+            pkt_pdn.tail = tail_gpd_latency;
+
+            ipc_send_ul_pkt(&pkt_ebi, NULL, IPC_UT_UL_EBI);
+            ipc_send_ul_pkt_by_pdn(&pkt_pdn, NULL, IPC_UT_PDN_ID, IPC_IP_TYPE_IPV4);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if ( (NULL != ipc_ut_ul_ebi_head_gpd) ||
+                 (NULL != ipc_ut_ul_ebi_tail_gpd) ||
+                 (0 != ipc_ut_ul_gpd_cnt) ) {
+                utELOG("(IMS send_ul_pkt) GPD is not forwarded to network correctly when suspend mode!\r\r");
+                qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+                ipc_ut_ul_ebi_head_gpd = NULL;
+                ipc_ut_ul_ebi_tail_gpd = NULL;
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            blocked_cnt += ipv4_cnt;
+        }
+    }
+
+    /*
+     * TEST CASE 2: IMS Basic
+     * Turn off throttling
+     * The blocked GPDs should be forwarded automatically.
+     */
+    {
+        ipc_ut_reset_ul_info();
+
+        /* Diable UL throttle */
+#if defined(__MD93__)
+        conf.enabled = 0;
+        kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+        tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+        p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+        UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+        p_ipc_ul_thrott_cfg->conf.enabled = KAL_FALSE;
+        p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+        p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+        p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+        ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+        free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if ( (blocked_cnt != ipc_ut_gpd_list_count(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd)) ||
+             (blocked_cnt != ipc_ut_ul_gpd_cnt) ) {
+            utELOG("(IMS send_ul_pkt) The blocked GPDs are not forwarded to network automatically when active mode.!\r\r");
+            qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+            ipc_ut_ul_ebi_head_gpd = NULL;
+            ipc_ut_ul_ebi_tail_gpd = NULL;
+            ipc_ut_free_gpd_list(NULL, NULL);
+            return KAL_FALSE;
+        }
+
+        /* Free GPD after test */
+        if (ipc_ut_ul_ebi_head_gpd) {
+            qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+            ipc_ut_ul_ebi_head_gpd = NULL;
+            ipc_ut_ul_ebi_tail_gpd = NULL;
+        }
+        ipc_ut_free_gpd_list(NULL, NULL);
+    }
+
+    /* PDN deactivation. */
+    deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+    deact_req->pdn_id = IPC_UT_PDN_ID;
+    ipc_on_pdn_unbind((local_para_struct *)deact_req);
+    free_local_para((local_para_struct *)deact_req);
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ul_throttle_ims_emergency(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32 ipv4_cnt = 0;
+    kal_uint32 blocked_cnt = 0;
+    qbm_gpd *head_gpd, *head_gpd_latency = NULL;
+    qbm_gpd *tail_gpd, *tail_gpd_latency = NULL;
+    ipc_io_request_t *ior, *ior_latency = NULL;
+    ipc_ut_netif_t *net, *net_latency = NULL;
+    kal_bool result = KAL_FALSE;
+    kal_uint32 idx = 1;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    kal_uint8 ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    ipc_vdm_ims_emergency_call_ind_struct_t *local_para_ptr = NULL;
+    ipc_ul_throttle_conf_t conf = {0};
+    tmc_ctrl_config tmc_cfg = {0};
+    kal_uint32 conf_in_int = 0;
+    ipc_set_ul_throttle_param_t *p_ipc_ul_thrott_cfg = NULL;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_UT_NETID_START;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    net_latency = &(ipc_ut_nets_s[1]);
+    kal_mem_set(net_latency, 0, sizeof(ipc_ut_netif_t));
+    net_latency->conf.module_id = MOD_IPCORE;
+    net_latency->conf.netif_id = IPC_UT_NETID_START + 1;
+    net_latency->conf.ul_reload_context = net_latency;
+    net_latency->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net_latency->conf.callback_context = net_latency;
+    net_latency->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net_latency->conf.features |= IPC_F_LATENCY_CONCERN;
+    result = ipc_attach(&net_latency->conf, &net_latency->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* PDN activation. */
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = net->conf.netif_id;
+    bind_req->pdn_id = IPC_UT_PDN_ID;
+    bind_req->ip_addr.ip_addr_type = ip_types[idx];
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+    free_local_para((local_para_struct *)bind_req);
+
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = net_latency->conf.netif_id;
+    bind_req->pdn_id = IPC_UT_PDN_ID_2;
+    bind_req->ip_addr.ip_addr_type = ip_types[idx];
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+    free_local_para((local_para_struct *)bind_req);
+
+    /*
+     * TEST CASE 1: Throttle IMS-blocking mode with IMS emergency flag.
+     * 1-1. IMS emergency = TRUE: Only latency packets could pass.
+     */
+
+    /* Enable UL Throttle with IMS blocking mode */
+#if defined(__MD93__)
+    conf.enabled = 1;
+    conf.active_period_100ms = 1;
+    conf.suspend_period_100ms = 255;
+    conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+    tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+    p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+    UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+    p_ipc_ul_thrott_cfg->conf.enabled = KAL_TRUE;
+    p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+    p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+    p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+    free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    {
+        /* Notify IMS emergency call */
+        local_para_ptr = (ipc_vdm_ims_emergency_call_ind_struct_t *)construct_local_para(sizeof(ipc_vdm_ims_emergency_call_ind_struct_t), TD_RESET);
+        UT_ASSERT(NULL != local_para_ptr);
+
+        local_para_ptr->is_calling = KAL_TRUE;
+        msg_send6(MOD_NIL, /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  MSG_ID_IPCORE_VDM_IMS_EMERGENCY_CALL_IND, /* msg_id */
+                  (local_para_struct *)local_para_ptr, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        blocked_cnt = 0;
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            ipc_uplink(net->handle, ior);
+            ipc_uplink(net_latency->handle, ior_latency);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if (ipv4_cnt != ipc_ut_ul_gpd_cnt) {
+                utELOG("1-1: GPD is not forwarded to network correctly when IMS emergency call!\r\r");
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            blocked_cnt += ipv4_cnt;
+
+            /* Free GPD after test */
+            ipc_ut_free_gpd_list(NULL, NULL);
+        }
+
+        ipc_ut_reset_ul_info();
+
+        /* Diable UL throttle */
+#if defined(__MD93__)
+        conf.enabled = 0;
+        kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+        tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+        p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+        UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+        p_ipc_ul_thrott_cfg->conf.enabled = KAL_FALSE;
+        p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+        p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+        p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+        ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+        free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (blocked_cnt != ipc_ut_ul_gpd_cnt) {
+            utELOG("1-1: The blocked GPDs are not forwarded to network automatically!\r\r");
+            ipc_ut_free_gpd_list(NULL, NULL);
+            return KAL_FALSE;
+        }
+
+        /* Free GPD after test */
+        ipc_ut_free_gpd_list(NULL, NULL);
+    }
+
+    /*
+     * TEST CASE 1: Throttle IMS-blocking mode with IMS emergency flag.
+     * 1-2. IMS emergency = FALSE: Both netifs should be throttled.
+     */
+
+    /* Enable UL Throttle with IMS blocking mode */
+#if defined(__MD93__)
+    conf.enabled = 1;
+    conf.active_period_100ms = 1;
+    conf.suspend_period_100ms = 255;
+    conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+    tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+    p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+    UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+    p_ipc_ul_thrott_cfg->conf.enabled = KAL_TRUE;
+    p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+    p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+    p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+    free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    {
+        /* Notify the end of IMS emergency call */
+        local_para_ptr = (ipc_vdm_ims_emergency_call_ind_struct_t *)construct_local_para(sizeof(ipc_vdm_ims_emergency_call_ind_struct_t), TD_RESET);
+        UT_ASSERT(NULL != local_para_ptr);
+
+        local_para_ptr->is_calling = KAL_FALSE;
+        msg_send6(MOD_NIL, /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  MSG_ID_IPCORE_VDM_IMS_EMERGENCY_CALL_IND, /* msg_id */
+                  (local_para_struct *)local_para_ptr, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        blocked_cnt = 0;
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            ipc_uplink(net->handle, ior);
+            ipc_uplink(net_latency->handle, ior_latency);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if (0 != ipc_ut_ul_gpd_cnt) {
+                utELOG("1-2: GPD is not forwarded to network correctly when suspend mode!\r\r");
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            blocked_cnt += ipv4_cnt;
+
+            /* Free GPD after test */
+            ipc_ut_free_gpd_list(NULL, NULL);
+        }
+    }
+
+    /*
+     * TEST CASE 1: Throttle IMS-blocking mode with IMS emergency flag.
+     * 1-3. Turn IMS emergency to TRUE: The blocked GPDs should be forwarded automatically.
+     */
+
+    {
+        ipc_ut_reset_ul_info();
+
+        /* Notify IMS emergency call */
+        local_para_ptr = (ipc_vdm_ims_emergency_call_ind_struct_t *)construct_local_para(sizeof(ipc_vdm_ims_emergency_call_ind_struct_t), TD_RESET);
+        UT_ASSERT(NULL != local_para_ptr);
+
+        local_para_ptr->is_calling = KAL_TRUE;
+        msg_send6(MOD_NIL, /* src_mod_id */
+                MOD_IPCORE, /* dest_mod_id */
+                IPCORE_SAP, /* sap_id */
+                MSG_ID_IPCORE_VDM_IMS_EMERGENCY_CALL_IND, /* msg_id */
+                (local_para_struct *)local_para_ptr, /* local_para_ptr */
+                NULL); /* peer_buff_ptr */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (blocked_cnt != ipc_ut_ul_gpd_cnt) {
+            utELOG("1-3: The blocked GPDs are not forwarded to network automatically when IMS emergency call.!\r\r");
+            ipc_ut_free_gpd_list(NULL, NULL);
+            return KAL_FALSE;
+        }
+
+        /* Free GPD after test */
+        ipc_ut_free_gpd_list(NULL, NULL);
+
+        ipc_ut_reset_ul_info();
+
+        /* Diable UL throttle */
+#if defined(__MD93__)
+        conf.enabled = 0;
+        kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+        tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+        p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+        UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+        p_ipc_ul_thrott_cfg->conf.enabled = KAL_FALSE;
+        p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+        p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+        p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+        ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+        free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (blocked_cnt != ipc_ut_ul_gpd_cnt) {
+            utELOG("1-3: The blocked GPDs are not forwarded to network automatically when throttling is turning off!\r\r");
+            ipc_ut_free_gpd_list(NULL, NULL);
+            return KAL_FALSE;
+        }
+
+        /* Free GPD after test */
+        ipc_ut_free_gpd_list(NULL, NULL);
+    }
+
+    /*
+     * TEST CASE 2: IMS emergency call when throttling turned off
+     * When throttling is turning off, it should send ilm MSG_ID_IPCORE_PROCESS_UL_QUEUE_REQ to ipcore.
+     */
+
+    /* Enable UL Throttle with IMS blocking mode */
+#if defined(__MD93__)
+    conf.enabled = 1;
+    conf.active_period_100ms = 1;
+    conf.suspend_period_100ms = 255;
+    conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+    tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+    p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+    UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+    p_ipc_ul_thrott_cfg->conf.enabled = KAL_TRUE;
+    p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+    p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+    p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+    free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    {
+        /* Notify the end of IMS emergency call */
+        local_para_ptr = (ipc_vdm_ims_emergency_call_ind_struct_t *)construct_local_para(sizeof(ipc_vdm_ims_emergency_call_ind_struct_t), TD_RESET);
+        UT_ASSERT(NULL != local_para_ptr);
+
+        local_para_ptr->is_calling = KAL_FALSE;
+        msg_send6(MOD_NIL, /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  MSG_ID_IPCORE_VDM_IMS_EMERGENCY_CALL_IND, /* msg_id */
+                  (local_para_struct *)local_para_ptr, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        blocked_cnt = 0;
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            ipc_uplink(net->handle, ior);
+            ipc_uplink(net_latency->handle, ior_latency);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if (0 != ipc_ut_ul_gpd_cnt) {
+                utELOG("2: GPD is not forwarded to network correctly when suspend mode!\r\r");
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            blocked_cnt += ipv4_cnt + ipv4_cnt;
+
+            /* Free GPD after test */
+            ipc_ut_free_gpd_list(NULL, NULL);
+        }
+
+        ipc_ut_reset_ul_info();
+
+        /*
+         * Diable UL throttle
+         */
+#if defined(__MD93__)
+        conf.enabled = 0;
+        kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+        tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+        p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+        UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+        p_ipc_ul_thrott_cfg->conf.enabled = KAL_FALSE;
+        p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+        p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+        p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+        ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+        free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if (blocked_cnt != ipc_ut_ul_gpd_cnt) {
+            utELOG("2: The blocked GPDs are not forwarded to network automatically when throttling is turning off!\r\r");
+            ipc_ut_free_gpd_list(NULL, NULL);
+            return KAL_FALSE;
+        }
+
+        /* Free GPD after test */
+        ipc_ut_free_gpd_list(NULL, NULL);
+    }
+
+    /*
+     * TEST CASE 3: ipc_send_ul_pkt case
+     * 3-1. IMS emergency = TRUE: Packets from ipc_send_ul_pkt should be able to sent to the network.
+     */
+
+    /* Enable UL Throttle with IMS blocking mode */
+#if defined(__MD93__)
+    conf.enabled = 1;
+    conf.active_period_100ms = 1;
+    conf.suspend_period_100ms = 255;
+    conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+    tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+    p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+    UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+    p_ipc_ul_thrott_cfg->conf.enabled = KAL_TRUE;
+    p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+    p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+    p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+    ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+    free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    {
+        ipc_pkt_t pkt_ebi, pkt_pdn;
+
+        /* Notify IMS emergency call */
+        local_para_ptr = (ipc_vdm_ims_emergency_call_ind_struct_t *)construct_local_para(sizeof(ipc_vdm_ims_emergency_call_ind_struct_t), TD_RESET);
+        UT_ASSERT(NULL != local_para_ptr);
+
+        local_para_ptr->is_calling = KAL_TRUE;
+        msg_send6(MOD_NIL, /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  MSG_ID_IPCORE_VDM_IMS_EMERGENCY_CALL_IND, /* msg_id */
+                  (local_para_struct *)local_para_ptr, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            /* Prepare ipc_pkt_t */
+            kal_mem_set(&pkt_ebi, 0, sizeof(ipc_pkt_t));
+            pkt_ebi.isGPD = KAL_TRUE;
+            pkt_ebi.head = head_gpd;
+            pkt_ebi.tail = tail_gpd;
+
+            kal_mem_set(&pkt_pdn, 0, sizeof(ipc_pkt_t));
+            pkt_pdn.isGPD = KAL_TRUE;
+            pkt_pdn.head = head_gpd_latency;
+            pkt_pdn.tail = tail_gpd_latency;
+
+            ipc_send_ul_pkt(&pkt_ebi, NULL, IPC_UT_UL_EBI);
+            ipc_send_ul_pkt_by_pdn(&pkt_pdn, NULL, IPC_UT_PDN_ID, IPC_IP_TYPE_IPV4);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if ( (NULL == ipc_ut_ul_ebi_head_gpd) ||
+                 (NULL == ipc_ut_ul_ebi_tail_gpd) ||
+                 (ipv4_cnt != ipc_ut_gpd_list_count(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd)) ||
+                 (ipv4_cnt != ipc_ut_ul_gpd_cnt) ) {
+                utELOG("3-1: (IMS send_ul_pkt) GPD is not forwarded to network correctly!\r\r");
+                qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+                ipc_ut_ul_ebi_head_gpd = NULL;
+                ipc_ut_ul_ebi_tail_gpd = NULL;
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            /* Free GPD after test */
+            if (ipc_ut_ul_ebi_head_gpd) {
+                qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+                ipc_ut_ul_ebi_head_gpd = NULL;
+                ipc_ut_ul_ebi_tail_gpd = NULL;
+            }
+            ipc_ut_free_gpd_list(NULL, NULL);
+        }
+    }
+
+    /*
+     * TEST CASE 3: ipc_send_ul_pkt case
+     * 3-2. IMS emergency = FALSE: Packets from ipc_send_ul_pkt should be blocked.
+     */
+    {
+        ipc_pkt_t pkt_ebi, pkt_pdn;
+
+        /* Notify the end of IMS emergency call */
+        local_para_ptr = (ipc_vdm_ims_emergency_call_ind_struct_t *)construct_local_para(sizeof(ipc_vdm_ims_emergency_call_ind_struct_t), TD_RESET);
+        UT_ASSERT(NULL != local_para_ptr);
+
+        local_para_ptr->is_calling = KAL_FALSE;
+        msg_send6(MOD_NIL, /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  MSG_ID_IPCORE_VDM_IMS_EMERGENCY_CALL_IND, /* msg_id */
+                  (local_para_struct *)local_para_ptr, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        blocked_cnt = 0;
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++) {
+            if (0 == ipv4_cnt) continue;
+
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd, &tail_gpd, &ior);
+            ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, 0, 0, &head_gpd_latency, &tail_gpd_latency, &ior_latency);
+
+            if (NULL == ior) {
+                utELOG("UL packet prepare failed!\r\r");
+                return KAL_FALSE;
+            }
+
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            /* Prepare ipc_pkt_t */
+            kal_mem_set(&pkt_ebi, 0, sizeof(ipc_pkt_t));
+            pkt_ebi.isGPD = KAL_TRUE;
+            pkt_ebi.head = head_gpd;
+            pkt_ebi.tail = tail_gpd;
+
+            kal_mem_set(&pkt_pdn, 0, sizeof(ipc_pkt_t));
+            pkt_pdn.isGPD = KAL_TRUE;
+            pkt_pdn.head = head_gpd_latency;
+            pkt_pdn.tail = tail_gpd_latency;
+
+            ipc_send_ul_pkt(&pkt_ebi, NULL, IPC_UT_UL_EBI);
+            ipc_send_ul_pkt_by_pdn(&pkt_pdn, NULL, IPC_UT_PDN_ID, IPC_IP_TYPE_IPV4);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if ( (NULL != ipc_ut_ul_ebi_head_gpd) ||
+                 (NULL != ipc_ut_ul_ebi_tail_gpd) ||
+                 (0 != ipc_ut_ul_gpd_cnt) ) {
+                utELOG("3-2: (IMS send_ul_pkt) GPD is not forwarded to network correctly!\r\r");
+                qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+                ipc_ut_ul_ebi_head_gpd = NULL;
+                ipc_ut_ul_ebi_tail_gpd = NULL;
+                ipc_ut_free_gpd_list(NULL, NULL);
+                return KAL_FALSE;
+            }
+
+            blocked_cnt += ipv4_cnt;
+        }
+    }
+
+    /*
+     * TEST CASE 3: ipc_send_ul_pkt case
+     * 3-3. IMS emergency = TRUE: The blocked GPDs should be forwarded automatically.
+     */
+
+    {
+        ipc_ut_reset_ul_info();
+
+        /* Notify IMS emergency call */
+        local_para_ptr = (ipc_vdm_ims_emergency_call_ind_struct_t *)construct_local_para(sizeof(ipc_vdm_ims_emergency_call_ind_struct_t), TD_RESET);
+        UT_ASSERT(NULL != local_para_ptr);
+
+        local_para_ptr->is_calling = KAL_TRUE;
+        msg_send6(MOD_NIL, /* src_mod_id */
+                  MOD_IPCORE, /* dest_mod_id */
+                  IPCORE_SAP, /* sap_id */
+                  MSG_ID_IPCORE_VDM_IMS_EMERGENCY_CALL_IND, /* msg_id */
+                  (local_para_struct *)local_para_ptr, /* local_para_ptr */
+                  NULL); /* peer_buff_ptr */
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        if ( (blocked_cnt != ipc_ut_gpd_list_count(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd)) ||
+             (blocked_cnt != ipc_ut_ul_gpd_cnt) ) {
+            utELOG("3-3: (IMS send_ul_pkt) The blocked GPDs are not forwarded to network automatically when active mode.!\r\r");
+            qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+            ipc_ut_ul_ebi_head_gpd = NULL;
+            ipc_ut_ul_ebi_tail_gpd = NULL;
+            ipc_ut_free_gpd_list(NULL, NULL);
+            return KAL_FALSE;
+        }
+
+        /* Free GPD after test */
+        if (ipc_ut_ul_ebi_head_gpd) {
+            qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+            ipc_ut_ul_ebi_head_gpd = NULL;
+            ipc_ut_ul_ebi_tail_gpd = NULL;
+        }
+        ipc_ut_free_gpd_list(NULL, NULL);
+
+        /* Diable UL throttle */
+#if defined(__MD93__)
+        conf.enabled = 0;
+        kal_mem_cpy(&conf_in_int, &conf, sizeof(ipc_ul_throttle_conf_t));
+        tmc_md_thermal_feature_ctrl_sysmsgsrv_cbk_93(conf_in_int);
+#else
+        p_ipc_ul_thrott_cfg = (ipc_set_ul_throttle_param_t *)construct_local_para(sizeof(ipc_set_ul_throttle_param_t), TD_RESET);
+        UT_ASSERT(NULL != p_ipc_ul_thrott_cfg);
+        p_ipc_ul_thrott_cfg->conf.enabled = KAL_FALSE;
+        p_ipc_ul_thrott_cfg->conf.active_period_100ms = 1;
+        p_ipc_ul_thrott_cfg->conf.suspend_period_100ms = 255;
+        p_ipc_ul_thrott_cfg->conf.features = IPC_THROTTLE_FEATURE_BLOCK_LANTENCY_CONCERN;
+        ipc_set_ul_throttle((local_para_struct *)p_ipc_ul_thrott_cfg);
+        free_local_para((local_para_struct *)p_ipc_ul_thrott_cfg);
+#endif
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+        /* Free GPD after test */
+        ipc_ut_free_gpd_list(NULL, NULL);
+    }
+
+    /* PDN deactivation. */
+    deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+    deact_req->pdn_id = IPC_UT_PDN_ID;
+    ipc_on_pdn_unbind((local_para_struct *)deact_req);
+    free_local_para((local_para_struct *)deact_req);
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+void ipc_ut_prepare_dl_did_list_garbage(kal_uint32 ipv4_cnt,
+                                        kal_uint32 ipv6_cnt,
+                                        kal_uint32 ipv4_idx,
+                                        kal_uint32 ipv6_idx,
+                                        kal_uint32 align_offset,
+                                        upcm_did   **did_head,
+                                        upcm_did   **did_tail,
+                                        kal_uint32 did_cnt)
+{
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx;
+    upcm_did           *curr_did;
+    upcm_did_si        *curr_sit;
+    upcm_did_si        *curr_si;
+    kal_uint32          curr_si_idx;
+    kal_uint32          pkt_start_si_idx;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          pkt_num;
+    kal_uint32          seg_num;
+    kal_uint8           per_pkt_max_sit_num = 10; /* one DID max packet number will be 7. one DID has 62 SIT entries */
+
+    if (did_cnt != ipc_ut_alloc_did(
+                        did_cnt,
+                        did_head,
+                        did_tail)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did *next_did;
+        kal_bool end_of_list;
+        kal_uint32 i;
+        upcm_did_si *si;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (curr_did = *did_head; curr_did && (end_of_list == KAL_FALSE); curr_did = next_did){
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                si = &curr_sit[i];
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+            next_did = UPCM_DID_GET_NEXT(curr_did);
+            (*did_tail == curr_did)?(end_of_list = KAL_TRUE):(end_of_list = KAL_FALSE);
+        }
+    }
+    
+    curr_did = *did_head;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        switch(idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv4_tcp_ack_packet;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_ack_packet);
+                ipc_ut_str_garbage_expect_host_cnt++;
+                break;
+            default:
+                packet_buf = ipc_ut_ipv4_tcp_syn_packet_2;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_syn_packet_2);
+                break;
+
+        }
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len)
+            {
+                kal_uint32 current_copy_len;
+
+                if ((curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) || (cont_loop_cnt == per_pkt_max_sit_num-1))
+                {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else
+                {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt ++;
+            }
+        }
+        pkt_num ++;
+
+    }
+
+    if(ipv4_cnt > 0){
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+
+    /*IPv6*/
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        switch(idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv6_udp_packet;
+                packet_len = sizeof(ipc_ut_ipv6_udp_packet);
+                ipc_ut_str_garbage_expect_host_cnt++;
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_tcp_syn_packet_2;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_syn_packet_2);
+                break;
+
+        }
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len)
+            {
+                kal_uint32 current_copy_len;
+
+                if ((curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) || (cont_loop_cnt == per_pkt_max_sit_num-1))
+                {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else
+                {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt ++;
+            }
+        }
+        pkt_num ++;
+
+    }
+    
+    if(ipv6_cnt > 0){
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }      
+}
+
+kal_bool ipc_ut_str_garbage_filter(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    pfm_filter_set_t filter_set;
+    local_para_struct *local_para_ptr;
+    peer_buff_struct *peer_buff_ptr;
+    pfm_str_filter_t *filter_info;
+    kal_uint8 i;
+    kal_uint8 *pdu_ptr;
+    kal_uint16 peer_buf_len;
+    ipc_ut_netif_t *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    static kal_uint8 ipv4_mask[192] = {0};
+    static kal_uint8 ipv6_mask[192] = {0};
+    kal_bool result;
+    kal_int32 *filter_id;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_UT_LHIF_NETID_START;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* PDN activation. */
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = net->conf.netif_id;
+    bind_req->pdn_id = IPC_UT_PDN_ID;
+    bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+    free_local_para((local_para_struct *)bind_req);
+
+    /*
+     *   Register 0-7 IPv4 filter, 8-16 IPv6 filter
+     */
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_STR_FILTER_SET_ID;
+    filter_set.filter_cnt = 16;
+    filter_set.uplink = KAL_FALSE;
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ((kal_uint8*)&filter_set)+4, sizeof(filter_set) - 4); // shift local_para_ptr header
+
+    /* Init mask */
+    ipv4_mask[0] = ipv6_mask[0] = 0xF0; /* IP version */
+    ipv4_mask[8] = ipv6_mask[6] = 0xFF; /* Protocol */
+    ipv4_mask[22] = ipv4_mask[23] = ipv6_mask[42] = ipv6_mask[43] = 0xFF; /* L4 dest port */
+
+    peer_buff_ptr = construct_peer_buff(sizeof(pfm_str_filter_t)*16, 0, 0, TD_RESET);
+    if (!peer_buff_ptr) {
+        utDLOG("peer_buff_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    pdu_ptr = get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+
+    filter_info = (pfm_str_filter_t*)pdu_ptr;
+    for(i = 0; i < 16; i++){
+        filter_info->filter_id = i;
+        filter_info->magic_code = 0x1798; //PFM_STR_FILTER_MAGIC_CODE
+        filter_info->mask_len = 192;
+        filter_info->netif_id = IPC_UT_LHIF_NETID_START;
+        if( i < 8){
+            /* IPv4 filter pattern */
+            filter_info->filter_len = sizeof(ipc_ut_ipv4_tcp_ack_packet);
+
+            kal_mem_cpy(filter_info->mask, ipv4_mask, 192);
+            kal_mem_cpy(filter_info->filter, ipc_ut_ipv4_tcp_ack_packet, sizeof(ipc_ut_ipv4_tcp_ack_packet));
+
+            if(0 != i){
+                /* Not first pattern, increase dst port value (ipv4) */
+                filter_info->filter[23]++;
+                if(0 == filter_info->filter[23]){
+                    filter_info->filter[22]++;
+                }
+            }
+        }else{
+            /* IPv6 filter pattern */
+            filter_info->filter_len = sizeof(ipc_ut_ipv6_udp_packet);
+
+            kal_mem_cpy(filter_info->mask, ipv6_mask, 192);
+            kal_mem_cpy(filter_info->filter, ipc_ut_ipv6_udp_packet, sizeof(ipc_ut_ipv6_udp_packet));
+            if(8 != i){
+                /* Not first pattern, increase dst port value (ipv4) */
+                filter_info->filter[42]++;
+                if(0 == filter_info->filter[42]){
+                    filter_info->filter[43]++;
+                }
+            }
+        }
+        filter_info = filter_info+1;
+    }
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+          MOD_IPCORE, /* dest_mod_id */
+          IPCORE_SAP, /* sap_id */
+          MSG_ID_PFM_REGISTER_FILTER_REQ, /* msg_id */
+          local_para_ptr, /* local_para_ptr */
+          peer_buff_ptr); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /* Simulate DL traffic to IPCore : Only data matched garbage filter should be forward to DL callback regardless of IP types (IPv4/IPv6) */
+    {
+        kal_uint32 ipv4_cnt;
+        kal_uint32 ipv6_cnt;
+        kal_uint32 total_cnt;
+        kal_uint32 did_cnt;
+        upcm_did *did_head;
+        upcm_did *did_tail;
+        kal_uint32 alignment;
+        kal_uint32 ipv4_idx;
+        kal_uint32 ipv6_idx;
+        kal_uint32 did_remain_cnt, gpd_remain_cnt_dl;
+
+        for (alignment = 0 ; alignment < 4 ; alignment ++)
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) 
+        for (ipv4_idx = 0; ipv4_idx < ipv4_cnt; ipv4_idx++)
+        for (ipv6_idx = 0; ipv6_idx < ipv6_cnt; ipv6_idx++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+            utDLOG("v4_cnt(%d),v6_cnt(%d),ipv4_idx(%d),ipv6_idx(%d),alignment(%d)\r\n", ipv4_cnt, ipv6_cnt, ipv4_idx, ipv6_idx, alignment);
+
+            did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+            total_cnt = ipv4_cnt + ipv6_cnt;
+
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+
+            /*Store DID remain cnt */
+            did_remain_cnt = upcm_did_get_buff_remain_num();
+
+            /*Store GPD remain cnt */
+            gpd_remain_cnt_dl = qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+            
+            ipc_ut_prepare_dl_did_list_garbage(ipv4_cnt,
+                                               ipv6_cnt,
+                                               ipv4_idx,
+                                               ipv6_idx,
+                                               alignment,
+                                               &did_head,
+                                               &did_tail,
+                                               did_cnt);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, 0);
+
+            if ( (did_cnt != ipc_ut_dl_callback_did_cnt) ||
+                 (ipc_ut_str_garbage_expect_host_cnt != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                utELOG("DL PKT is NOT forwarded to bound handler!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(gpd_remain_cnt_dl != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(did_remain_cnt != upcm_did_get_buff_remain_num()){
+                utELOG("wrong expected DID count!\r\n");
+                return KAL_FALSE;
+            }
+
+            ipc_ut_str_garbage_expect_host_cnt = 0;
+        }
+    }
+
+    /*
+     *   Deregister half of filters (0~7)
+     */
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_STR_FILTER_SET_ID;
+    filter_set.filter_cnt = 8;
+    filter_set.uplink = KAL_FALSE;
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ((kal_uint8*)&filter_set)+4, sizeof(filter_set) - 4); // shift local_para_ptr header
+
+    peer_buff_ptr = construct_peer_buff(sizeof(kal_int32)*8, 0, 0, TD_RESET);
+    if (!peer_buff_ptr) {
+        utDLOG("peer_buff_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    pdu_ptr = get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+
+    filter_id = (kal_int32*) pdu_ptr;
+    for (i = 0; i < 8; i++) {
+        *filter_id = (kal_int32) i;
+        filter_id++;
+    }
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_PFM_DEREGISTER_FILTER_REQ, /* msg_id */
+              local_para_ptr, /* local_para_ptr */
+              peer_buff_ptr); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     *   Register filter_id 0~7. Half of them should not be removed yet.
+     */
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_STR_FILTER_SET_ID;
+    filter_set.filter_cnt = 8;
+    filter_set.uplink = KAL_FALSE;
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ((kal_uint8*)&filter_set)+4, sizeof(filter_set) - 4); // shift local_para_ptr header
+
+    peer_buff_ptr = construct_peer_buff(sizeof(pfm_str_filter_t)*8, 0, 0, TD_RESET);
+    if (!peer_buff_ptr) {
+        utDLOG("peer_buff_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    pdu_ptr = get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+
+    filter_info = (pfm_str_filter_t*)pdu_ptr;
+    for(i = 0; i < 8; i++){
+        filter_info->filter_id = i;
+        filter_info->magic_code = 0x1798; //PFM_STR_FILTER_MAGIC_CODE
+        filter_info->mask_len = 192;
+        filter_info->netif_id = IPC_UT_LHIF_NETID_START;
+
+        /* IPv4 filter pattern */
+        filter_info->filter_len = sizeof(ipc_ut_ipv4_tcp_ack_packet);
+
+        kal_mem_cpy(filter_info->mask, ipv4_mask, 192);
+        kal_mem_cpy(filter_info->filter, ipc_ut_ipv4_tcp_ack_packet, sizeof(ipc_ut_ipv4_tcp_ack_packet));
+
+        if(0 != i){
+            /* Not first pattern, increase dst port value (ipv4) */
+            filter_info->filter[23]++;
+            if(0 == filter_info->filter[23]){
+                filter_info->filter[22]++;
+            }
+        }
+        filter_info = filter_info+1;
+    }
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+          MOD_IPCORE, /* dest_mod_id */
+          IPCORE_SAP, /* sap_id */
+          MSG_ID_PFM_REGISTER_FILTER_REQ, /* msg_id */
+          local_para_ptr, /* local_para_ptr */
+          peer_buff_ptr); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     *   Deregister all filters
+     */
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_STR_FILTER_SET_ID;
+    filter_set.filter_cnt = -1;
+    filter_set.uplink = KAL_FALSE;
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ((kal_uint8*)&filter_set)+4, sizeof(filter_set) - 4); // shift local_para_ptr header
+    
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_PFM_DEREGISTER_FILTER_REQ, /* msg_id */
+              local_para_ptr, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /* PDN deactivation. */
+    deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+    deact_req->pdn_id = IPC_UT_PDN_ID;
+    ipc_on_pdn_unbind((local_para_struct *)deact_req);
+    free_local_para((local_para_struct *)deact_req);
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_garbage_filter(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    pfm_filter_set_t            filter_set;
+    ipc_ut_garbage_filter_t     filter;
+    kal_uint32                  offset;
+    kal_uint32                  i;
+    kal_int32                   filter_id;
+    local_para_struct          *local_para_ptr;
+    peer_buff_struct           *peer_buff_ptr;
+    kal_uint8                  *pdu_ptr;
+    kal_uint16                  peer_buf_len;
+    qbm_gpd                    *head_gpd;
+    qbm_gpd                    *tail_gpd;
+    ipc_filter_rules_t          rules;
+    kal_uint32                  ipv4_cnt, ipv6_cnt, synv4_idx, synv6_idx;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     *   Register
+     */
+    offset = 0;
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_FILTER_SET_ID;
+    filter_set.filter_cnt = 128;
+    filter_set.uplink = KAL_FALSE;
+
+    kal_mem_cpy(ipc_ut_garbage_filter_buf_s, &filter_set, sizeof(filter_set));
+    offset += sizeof(filter_set);
+
+    for (i = 0; i < 128; i++) {
+        kal_mem_set(&filter, 0,sizeof(filter));
+
+        filter.filter_id = i;
+        filter.ip_type = IPC_IP_TYPE_IPV4;
+        filter.protocol = IPC_HDR_PROT_TCP;
+        filter.dst_port = 443+i;
+        filter.magic_code = 168;
+
+        kal_mem_cpy(ipc_ut_garbage_filter_buf_s + offset, &filter, sizeof(filter));
+        offset += sizeof(filter);
+    }
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ipc_ut_garbage_filter_buf_s + 4, sizeof(filter_set) - 4); // shift local_para_ptr header
+
+    peer_buff_ptr = construct_peer_buff(sizeof(kal_uint8)*(offset-sizeof(filter_set)), 0, 0, TD_RESET);
+    if (!peer_buff_ptr) {
+        utDLOG("peer_buff_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    pdu_ptr = get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+    kal_mem_cpy(pdu_ptr, ipc_ut_garbage_filter_buf_s + sizeof(filter_set), offset - sizeof(filter_set));
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_PFM_REGISTER_FILTER_REQ, /* msg_id */
+              local_para_ptr, /* local_para_ptr */
+              peer_buff_ptr); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /* Send DL packet */
+    for (ipv4_cnt = 1; ipv4_cnt <= 8; ipv4_cnt++)
+    for (ipv6_cnt = 1; ipv6_cnt <= 8; ipv6_cnt++)
+    for (synv4_idx = 0; synv4_idx < ipv4_cnt; synv4_idx++)
+    for (synv6_idx = 0; synv6_idx < ipv6_cnt; synv6_idx++) {
+        ipc_ut_prepare_garbage_filter_dl_gpd_list(ipv4_cnt, synv4_idx, ipv6_cnt, synv6_idx, &head_gpd, &tail_gpd);
+
+        ipc_do_dl_filter(IPC_IP_TYPE_IPV4, IPC_UT_NETID_START, IPC_UT_PDN_ID, &head_gpd, &tail_gpd);
+
+        if (NULL == head_gpd ||
+            NULL == tail_gpd ||
+            ipv4_cnt + ipv6_cnt - ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt
+            != ipc_ut_gpd_list_count(head_gpd, tail_gpd)) {
+            utELOG("Not trap Garbage packets!\r\n");
+            return KAL_FALSE;
+        }
+
+        if (ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt > 0 &&
+            (NULL == ipc_ut_ul_ebi_head_gpd ||
+              NULL == ipc_ut_ul_ebi_tail_gpd ||
+              ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt
+              != ipc_ut_gpd_list_count(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd) )) {
+            utELOG("Responsing TCP RST packets has something wrong!!\r\n");
+            return KAL_FALSE;
+        }
+
+        ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+
+        if (NULL != ipc_ut_ul_ebi_head_gpd) {
+            UT_ASSERT(NULL != ipc_ut_ul_ebi_tail_gpd);
+
+            qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+            ipc_ut_ul_ebi_head_gpd = NULL;
+            ipc_ut_ul_ebi_tail_gpd = NULL;
+        }
+
+        ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt = 0;
+    }
+
+
+    /*
+     *   Deregister half of filters
+     */
+    offset = 0;
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_FILTER_SET_ID;
+    filter_set.filter_cnt = 64;
+    filter_set.uplink = KAL_FALSE;
+
+    kal_mem_cpy(ipc_ut_garbage_filter_buf_s, &filter_set, sizeof(filter_set));
+    offset += sizeof(filter_set);
+
+    for (i = 0; i < 64; i++) {
+        filter_id = i << 1;
+
+        kal_mem_cpy(ipc_ut_garbage_filter_buf_s + offset, &filter_id, sizeof(filter_id));
+        offset += sizeof(filter_id);
+    }
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ipc_ut_garbage_filter_buf_s + 4, sizeof(filter_set) - 4);
+
+    peer_buff_ptr = construct_peer_buff(sizeof(kal_uint8)*(offset-sizeof(filter_set)), 0, 0, TD_RESET);
+    if (!peer_buff_ptr) {
+        utDLOG("peer_buff_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    pdu_ptr = get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+    kal_mem_cpy(pdu_ptr, ipc_ut_garbage_filter_buf_s + sizeof(filter_set), offset - sizeof(filter_set));
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_PFM_DEREGISTER_FILTER_REQ, /* msg_id */
+              local_para_ptr, /* local_para_ptr */
+              peer_buff_ptr); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     *   Register filter_id 1~64. Half of them should not be removed yet.
+     */
+    offset = 0;
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_FILTER_SET_ID;
+    filter_set.filter_cnt = 64;
+    filter_set.uplink = KAL_FALSE;
+
+    kal_mem_cpy(ipc_ut_garbage_filter_buf_s, &filter_set, sizeof(filter_set));
+    offset += sizeof(filter_set);
+
+    for (i = 0; i < 64; i++) {
+        kal_mem_set(&filter, 0,sizeof(filter));
+
+        filter.filter_id = i;
+        filter.ip_type = IPC_IP_TYPE_IPV4;
+        filter.protocol = IPC_HDR_PROT_TCP;
+        filter.dst_port = i;
+        filter.magic_code = 168;
+
+        kal_mem_cpy(ipc_ut_garbage_filter_buf_s + offset, &filter, sizeof(filter));
+        offset += sizeof(filter);
+    }
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ipc_ut_garbage_filter_buf_s + 4, sizeof(filter_set) - 4);
+
+    peer_buff_ptr = construct_peer_buff(sizeof(kal_uint8)*(offset-sizeof(filter_set)), 0, 0, TD_RESET);
+    if (!peer_buff_ptr) {
+        utDLOG("peer_buff_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    pdu_ptr = get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+    kal_mem_cpy(pdu_ptr, ipc_ut_garbage_filter_buf_s + sizeof(filter_set), offset - sizeof(filter_set));
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_PFM_REGISTER_FILTER_REQ, /* msg_id */
+              local_para_ptr, /* local_para_ptr */
+              peer_buff_ptr); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     *   Deregister all filters.
+     */
+    offset = 0;
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_FILTER_SET_ID;
+    filter_set.filter_cnt = -1;
+    filter_set.uplink = KAL_FALSE;
+
+    kal_mem_cpy(ipc_ut_garbage_filter_buf_s, &filter_set, sizeof(filter_set));
+    offset += sizeof(filter_set);
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ipc_ut_garbage_filter_buf_s + 4, sizeof(filter_set) - 4);
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_PFM_DEREGISTER_FILTER_REQ, /* msg_id */
+              local_para_ptr, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     * pfm_register_filter_msg & pfm_register_filter_with_info_msg
+     */
+    kal_mem_set(&rules, 0, sizeof(rules));
+    rules.features = IPC_FILTER_FEATURE_BWM;
+    rules.priority = IPC_UT_LOW_PRIORITY;
+    rules.valid_fields = (IPC_FILTER_BY_PROTOCOL |
+                           IPC_FILTER_BY_SRC_PORT);
+    rules.protocol = IPC_HDR_PROT_UDP;
+    rules.src_port = 67;
+    pfm_register_filter_msg(0, 0, KAL_TRUE, &rules, MOD_NIL, NULL);
+    pfm_register_filter_with_info_msg(0, 0, KAL_TRUE, &rules, MOD_NIL, NULL);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_downlink_multiple_ps(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         proto_idx[] = {0, 1};
+    kal_bool          result;
+    ilm_struct        ilm;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_UT_LHIF_NETID_START;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Simulate DL traffic to IPCore : Before PDN binding, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+            kal_uint32  alignment;
+            kal_uint32  unite;
+            kal_uint32  spd;
+            kal_uint32  spd_igr_bit;
+            kal_uint32  spd_position;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (spd = 0; spd < 1; spd++)
+            for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+            for (spd_position = 0; spd_position < 3; spd_position++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            (unite == 0)?0:10,
+                                            alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            NULL,
+                                            NULL,
+                                            spd,
+                                            spd_igr_bit,
+                                            spd_position);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink_multiple_ps(IPC_UT_PDN_ID, head_gpd, tail_gpd, idx);
+
+                if ( (0 != ipc_ut_dl_callback_gpd_cnt) ||
+                     (0 != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                    utELOG("DL GPD is forwarded before PDN binding! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM + idx, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+        free_local_para((local_para_struct *)bind_req);
+
+        /* Simulate DL traffic to IPCore : All GPDs should be forward to DL callback regardless of IP types (IPv4/IPv6) */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+            kal_uint32  alignment;
+            kal_uint32  unite;
+            kal_uint32  spd;
+            kal_uint32  spd_igr_bit;
+            kal_uint32  spd_position;
+            kal_uint32  total_cnt;
+            kal_uint32  spd_payload_cnt;
+            kal_uint32  i;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (spd = 0; spd < 1; spd++)
+            for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+            for (spd_position = 0; spd_position < 3; spd_position++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            (unite == 0)?0:10,
+                                            alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            NULL,
+                                            NULL,
+                                            spd,
+                                            spd_igr_bit,
+                                            spd_position);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink_multiple_ps(IPC_UT_PDN_ID, head_gpd, tail_gpd, idx);
+
+                if (1 == spd) {
+                    total_cnt = ipv4_cnt + ipv6_cnt + 1/*spd*/;
+                    spd_payload_cnt = ipv4_cnt + ipv6_cnt;
+                    if (1 == spd_igr_bit) {
+                        kal_uint32 igr_payload_cnt = 0;
+                        for (i = 0; i < (ipv4_cnt + ipv6_cnt); i++) {
+                            igr_payload_cnt += ipc_ut_spd_packet_igr_s[i];
+                        }
+                        if ((ipv4_cnt + ipv6_cnt) == igr_payload_cnt) {
+                            /* All SPD's payloads has been ignored. */
+                            total_cnt--;
+                            spd_payload_cnt = 0;
+                        } else {
+                            spd_payload_cnt -= igr_payload_cnt;
+                        }
+                    }
+                } else {
+                    total_cnt = ipv4_cnt + ipv6_cnt;
+                    spd_payload_cnt = 0;
+                }
+
+                if ( (total_cnt != ipc_ut_dl_callback_gpd_cnt) ||
+                     (spd_payload_cnt != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                    utELOG("DL GPD is NOT forwarded to bound handler! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                    ipc_ut_free_gpd_list(head_gpd, tail_gpd);
+                    return KAL_FALSE;
+                }
+
+                /* DL callback is correctly called : all GPDs are released */
+            }
+        }
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* Simulate DL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+            kal_uint32  alignment;
+            kal_uint32  unite;
+            kal_uint32  spd;
+            kal_uint32  spd_igr_bit;
+            kal_uint32  spd_position;
+
+            for (unite = 0 ; unite < 2 ; unite ++)
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (spd = 0; spd < 1; spd++)
+            for (spd_igr_bit = 0; spd_igr_bit < 2; spd_igr_bit++)
+            for (spd_position = 0; spd_position < 3; spd_position++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                if (0 == spd && ( 0 < spd_igr_bit || 0 < spd_position )) continue;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_gpd_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            (unite == 0)?0:10,
+                                            alignment,
+                                            &head_gpd,
+                                            &tail_gpd,
+                                            NULL,
+                                            NULL,
+                                            spd,
+                                            spd_igr_bit,
+                                            spd_position);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_downlink_multiple_ps(IPC_UT_PDN_ID, head_gpd, tail_gpd, idx);
+
+                if ( (0 != ipc_ut_dl_callback_gpd_cnt) ||
+                     (0 != ipc_ut_dl_callback_spd_payload_cnt) ) {
+                    utELOG("DL GPD is forwarded after PDN deactivation! (SPD:%d, IGR:%d)\r\n", spd, spd_igr_bit);
+                    return KAL_FALSE;
+                }
+            }
+        }
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_uplink_multiple_ps(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32                          blocked_cnt = 0;
+    ipc_io_request_t                   *ior;
+    ipc_ut_netif_t                     *net;
+    kal_bool                            result;
+    kal_uint32                          idx;
+    kal_uint8                           proto_idx[] = {0, 1};
+    ipcore_upcm_pdn_bind_ind_struct    *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct   *deact_req;
+    ilm_struct                          ilm;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_UT_LHIF_NETID_START;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Simulate UL traffic to IPCore : Before PDN binding, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_gpd, &tail_gpd, &ior);
+
+                if (NULL == ior) {
+                    utELOG("UL packet prepare failed!\r\r");
+                    return KAL_FALSE;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+
+                ipc_uplink(net->handle, ior);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if (0 != ipc_ut_ul_gpd_cnt) {
+                    utELOG("UL GPD is forwarded before PDN binding! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM + idx, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+        free_local_para((local_para_struct *)bind_req);
+
+        /* Simulate UL traffic to IPCore : All GPDs should be forward to UL callback regardless of IP types (IPv4/IPv6) */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_gpd, &tail_gpd, &ior);
+
+                if (NULL == ior) {
+                    utELOG("UL packet prepare failed!\r\r");
+                    return KAL_FALSE;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+
+                ipc_uplink(net->handle, ior);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if (ipv4_cnt + ipv6_cnt != ipc_ut_ul_gpd_cnt) {
+                    utELOG("UL GPD is forwarded to bound handler! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* Simulate UL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            qbm_gpd    *head_gpd;
+            qbm_gpd    *tail_gpd;
+
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                ipc_ut_prepare_ul_gpd_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_gpd, &tail_gpd, &ior);
+
+                if (NULL == ior) {
+                    utELOG("UL packet prepare failed!\r\r");
+                    return KAL_FALSE;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+
+                ipc_uplink(net->handle, ior);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if (0 != ipc_ut_ul_gpd_cnt) {
+                    utELOG("UL GPD is forwarded after PDN deactivation! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_send_ul_pkt_multiple_ps(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint8  *ip_header;
+    kal_uint32  total_length;
+    kal_uint8  *udp_header;
+    kal_uint32  udp_length;
+    kal_uint32  ul_total_length;
+    kal_bool    result;
+    kal_uint32  idx;
+    kal_uint8   proto_idx[] = {0, 1};
+
+    kal_uint32  to_generate_hdr;
+    ipc_pkt_t   pkt;
+    ipc_hdr_t   hdr;
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        // init before test
+        ipc_ut_init();
+
+        /*
+         *   Reset IPCore before test
+         */
+        if (KAL_TRUE != ipc_reset()) {
+            utELOG("ipc_reset() FAIL!\r\n");
+            return KAL_FALSE;
+        }
+
+        for ( to_generate_hdr = 0 ; to_generate_hdr < 2 ; to_generate_hdr ++ ) {
+            qbm_gpd    *curr_gpd;
+            kal_uint32 isGPD;
+            kal_uint32 pktcnt;
+            kal_uint32 alignment;
+
+            ip_header = ipc_ut_ipv4_dns_packet;
+            total_length = sizeof(ipc_ut_ipv4_dns_packet);
+            udp_header = IPC_HDR_V4_GET_NHPTR(ip_header);
+            udp_length = total_length - IPC_HDR_V4_GET_IHL(ip_header);
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (isGPD = 0 ; isGPD < 2 ; isGPD ++)
+            for (pktcnt = 1 ; pktcnt < 4 ; pktcnt ++) {
+                /* IP/UDP Header information */
+                hdr.ip_type = IPC_IP_TYPE_IPV4;
+                hdr.src_addr = IPC_HDR_V4_GET_SRC_ADDR(ip_header);
+                hdr.dst_addr = IPC_HDR_V4_GET_DST_ADDR(ip_header);
+                hdr.src_port = IPC_HDR_UDP_GET_SRC_PORT(udp_header);
+                hdr.dst_port = IPC_HDR_UDP_GET_DST_PORT(udp_header);
+                hdr.dscp_tc = 0;
+
+                /* Generate Packet */
+                if (0 == isGPD) {
+                    pkt.isGPD       = KAL_FALSE;
+                    pkt.data        = (0 == to_generate_hdr) ? ip_header : udp_header + IPC_HDR_UDP_HEADER_SIZE;
+                    pkt.data_len    = (0 == to_generate_hdr) ? total_length : udp_length - IPC_HDR_UDP_HEADER_SIZE;
+                } else {
+                    pkt.isGPD = KAL_TRUE;
+                    /* Using "dl_gpd_list" preparing to generate packet (which is more suitable for this case) */
+                    ipc_ut_prepare_dl_gpd_list(pktcnt,
+                                                    0,
+                                                    KAL_TRUE,
+                                                    (0 == to_generate_hdr)?KAL_TRUE:KAL_FALSE,
+                                                    0,
+                                                    0,
+                                                    KAL_FALSE,
+                                                    KAL_FALSE,
+                                                    0,  /* We does NOT divide packet in pieces for following comparison */
+                                                    alignment,
+                                                    &(pkt.head),
+                                                    &(pkt.tail),
+                                                    NULL,
+                                                    NULL,
+                                                    KAL_FALSE,
+                                                    KAL_FALSE,
+                                                    0);
+                }
+
+                result = ipc_send_ul_pkt_multiple_ps(
+                            &pkt,
+                            (0 == to_generate_hdr)?NULL:&hdr,
+                            IPC_UT_UL_EBI,
+                            idx);
+
+                if (!result) {
+                    utELOG("[4] ipc_send_ul_pkt() failed!\r\n");
+                    return KAL_FALSE;
+                }
+                if (NULL == ipc_ut_ul_ebi_head_gpd || NULL == ipc_ut_ul_ebi_tail_gpd) {
+                    utELOG("[4] ipc_send_ul_pkt() failed! no UL SDU sent.\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Run GPD copy and content check */
+                curr_gpd = ipc_ut_ul_ebi_head_gpd;
+                do {
+                    if (!ipc_gpd_copy(ipc_ut_checksum_buf_s,
+                                      sizeof(ipc_ut_checksum_buf_s),
+                                      &ul_total_length,
+                                      curr_gpd,
+                                      curr_gpd)) {
+                        utELOG("[4] ipc_gpd_copy() failed!\r\n");
+                        return KAL_FALSE;
+                    }
+                    if (ul_total_length != total_length) {
+                        utELOG("[4] ipc_send_ul_pkt() IPv4 total_length mismatched!\r\n");
+                        return KAL_FALSE;
+                    }
+                    if ( !IPC_HDR_IS_V4(ipc_ut_checksum_buf_s) ||
+                         total_length != IPC_HDR_V4_GET_TOTAL_LENGTH(ipc_ut_checksum_buf_s) ||
+                         !IPC_EQ_V4_ADDR(IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_checksum_buf_s), IPC_HDR_V4_GET_SRC_ADDR(ip_header)) ||
+                         !IPC_EQ_V4_ADDR(IPC_HDR_V4_GET_DST_ADDR(ipc_ut_checksum_buf_s), IPC_HDR_V4_GET_DST_ADDR(ip_header)) ||
+                         IPC_HDR_PROT_UDP != IPC_HDR_V4_GET_PROTOCOL(ipc_ut_checksum_buf_s) ||
+                         0 != ipc_utils_calc_ipv4_checksum(ipc_ut_checksum_buf_s) ) {
+                        utELOG("[4] ipc_send_ul_pkt() wrong IPv4 header!\r\n");
+                        return KAL_FALSE;
+                    }
+                    if ( kal_mem_cmp(IPC_HDR_V4_GET_NHPTR(ipc_ut_checksum_buf_s), udp_header, udp_length) ) {
+                        utELOG("[4] ipc_send_ul_pkt() UDP header or data mismatched!\r\n");
+                        return KAL_FALSE;
+                    }
+
+                    /* Check next GPD */
+                    if (ipc_ut_ul_ebi_tail_gpd == curr_gpd) {
+                        curr_gpd = NULL;
+                    } else {
+                        curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+                    }
+                } while (curr_gpd);
+
+                /* Free GPD list */
+                qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+                ipc_ut_ul_ebi_head_gpd = NULL;
+                ipc_ut_ul_ebi_tail_gpd = NULL;
+                ipc_ut_ul_proto_idx = IPC_UT_INVALID_UL_PROTO_IDX;
+            }
+
+            ip_header = ipc_ut_ipv6_mdns_packet;
+            total_length = sizeof(ipc_ut_ipv6_mdns_packet);
+            udp_header = IPC_HDR_V6_GET_NHPTR(ip_header);
+            udp_length = total_length - IPC_HDR_V6_HEADER_SIZE;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (isGPD = 0 ; isGPD < 2 ; isGPD ++)
+            for (pktcnt = 1 ; pktcnt < 4 ; pktcnt ++) {
+                /* IP/UDP Header information */
+                hdr.ip_type = IPC_IP_TYPE_IPV6;
+                hdr.src_addr = IPC_HDR_V6_GET_SRC_ADDR(ip_header);
+                hdr.dst_addr = IPC_HDR_V6_GET_DST_ADDR(ip_header);
+                hdr.src_port = IPC_HDR_UDP_GET_SRC_PORT(udp_header);
+                hdr.dst_port = IPC_HDR_UDP_GET_DST_PORT(udp_header);
+                hdr.dscp_tc = 0;
+
+                /* Generate Packet */
+                if (0 == isGPD) {
+                    pkt.isGPD       = KAL_FALSE;
+                    pkt.data        = (0 == to_generate_hdr) ? ip_header : (udp_header + IPC_HDR_UDP_HEADER_SIZE);
+                    pkt.data_len    = (0 == to_generate_hdr) ? total_length : udp_length - IPC_HDR_UDP_HEADER_SIZE;
+
+                } else {
+                    pkt.isGPD = KAL_TRUE;
+                    /* Using "dl_gpd_list" preparing to generate packet (which is more suitable for this case) */
+                    ipc_ut_prepare_dl_gpd_list(0,
+                                                    0,
+                                                    KAL_FALSE,
+                                                    KAL_FALSE,
+                                                    pktcnt,
+                                                    0,
+                                                    KAL_TRUE,
+                                                    (0 == to_generate_hdr)?KAL_TRUE:KAL_FALSE,
+                                                    0, /* We does NOT divide packet in pieces for following comparison */
+                                                    alignment,
+                                                    &(pkt.head),
+                                                    &(pkt.tail),
+                                                    NULL,
+                                                    NULL,
+                                                    KAL_FALSE,
+                                                    KAL_FALSE,
+                                                    0);
+                }
+
+                result = ipc_send_ul_pkt_multiple_ps(
+                            &pkt,
+                            (0 == to_generate_hdr)?NULL:&hdr,
+                            IPC_UT_UL_EBI,
+                            idx);
+
+                if (!result) {
+                    utELOG("[6] ipc_send_ul_pkt() failed!\r\n");
+                    return KAL_FALSE;
+                }
+                if (NULL == ipc_ut_ul_ebi_head_gpd || NULL == ipc_ut_ul_ebi_tail_gpd) {
+                    utELOG("[6] ipc_send_ul_pkt() failed! no UL SDU sent.\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Run GPD copy and content check */
+                curr_gpd = ipc_ut_ul_ebi_head_gpd;
+                do {
+                    if (!ipc_gpd_copy(ipc_ut_checksum_buf_s,
+                                      sizeof(ipc_ut_checksum_buf_s),
+                                      &ul_total_length,
+                                      curr_gpd,
+                                      curr_gpd)) {
+                        utELOG("[6] ipc_gpd_copy() failed!\r\n");
+                        return KAL_FALSE;
+                    }
+                    if (ul_total_length != total_length) {
+                        utELOG("[6] ipc_send_ul_pkt() IPv6 total_length mismatched!\r\n");
+                        return KAL_FALSE;
+                    }
+                    if ( !IPC_HDR_IS_V6(ipc_ut_checksum_buf_s) ||
+                         !IPC_EQ_V6_ADDR(IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_checksum_buf_s), IPC_HDR_V6_GET_SRC_ADDR(ip_header)) ||
+                         !IPC_EQ_V6_ADDR(IPC_HDR_V6_GET_DST_ADDR(ipc_ut_checksum_buf_s), IPC_HDR_V6_GET_DST_ADDR(ip_header)) ||
+                         IPC_HDR_PROT_UDP != IPC_HDR_V6_GET_NH_TYPE(ipc_ut_checksum_buf_s) ) {
+                        utELOG("[6] ipc_send_ul_pkt() wrong IPv6 header!\r\n");
+                        return KAL_FALSE;
+                    }
+                    if ( kal_mem_cmp(IPC_HDR_V6_GET_NHPTR(ipc_ut_checksum_buf_s), udp_header, udp_length) ) {
+                        utELOG("[6] ipc_send_ul_pkt() UDP header or data mismatched!\r\n");
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_ebi_tail_gpd == curr_gpd) {
+                        curr_gpd = NULL;
+                    } else {
+                        curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(curr_gpd);
+                    }
+                } while (curr_gpd);
+
+                /* Free GPD list */
+                qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+                ipc_ut_ul_ebi_head_gpd = NULL;
+                ipc_ut_ul_ebi_tail_gpd = NULL;
+                ipc_ut_ul_proto_idx = IPC_UT_INVALID_UL_PROTO_IDX;
+            }
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_meta_uplink(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32                          blocked_cnt = 0;
+    ipc_ut_netif_t                     *net;
+    kal_uint32                          netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool                            result;
+    kal_uint32                          idx;
+    kal_uint8                           proto_idx[] = {0, 1};
+    ipcore_upcm_pdn_bind_ind_struct    *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct   *deact_req;
+    ilm_struct                          ilm;
+    kal_uint8                           test_stage;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Simulate UL traffic to IPCore : Before PDN binding, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  total_cnt;
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  head_idx;
+            kal_uint32  tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+
+            test_stage = IPC_UT_STAGE_BEFORE_BINDING;
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Before Bind] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+
+                ipc_ut_prepare_ul_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (0 != ipc_ut_ul_meta_non_igr_cnt) ) {
+                    utELOG("UL META is forwarded before PDN binding! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM + idx, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+        free_local_para((local_para_struct *)bind_req);
+
+        /* Simulate UL traffic to IPCore : All GPDs should be forward to UL callback regardless of IP types (IPv4/IPv6) */
+        {
+            kal_uint32  total_cnt;
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  head_idx;
+            kal_uint32  tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+
+            test_stage = IPC_UT_STAGE_BINDING;
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Binded] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+
+                ipc_ut_prepare_ul_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (total_cnt != ipc_ut_ul_meta_non_igr_cnt) ) {
+                    utELOG("UL META is forwarded to bound handler! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+                if (IPC_UT_PDN_ID != ipc_ut_ul_pdn_id) {
+                    utELOG("UL META is forwarded with wrong PDN ID! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+                if (idx != ipc_ut_ul_proto_idx) {
+                    utELOG("UL META is forwarded with wrong Protocol ID! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* Simulate UL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  total_cnt;
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  head_idx;
+            kal_uint32  tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+
+            test_stage = IPC_UT_STAGE_UNBINDING;
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Deactivated] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+
+                ipc_ut_prepare_ul_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (0 != ipc_ut_ul_meta_non_igr_cnt) ) {
+                    utELOG("UL META is forwarded after PDN deactivation! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+            }
+        }
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_did_downlink(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    kal_uint32        netif_id = IPC_UT_LHIF_NETID_START;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         proto_idx[] = {0, 1};
+    kal_bool          result;
+    ilm_struct        ilm;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* IPCORE may send UL traffic in disconnected state */
+        ipc_ut_reset_ul_info();
+
+        /* Simulate DL traffic to IPCore : Before PDN binding, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Before Bind] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            0,
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL,
+                                            NULL,
+                                            did_cnt,
+                                            KAL_FALSE);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM + idx, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+        free_local_para((local_para_struct *)bind_req);
+
+        /* Simulate DL traffic to IPCore : All GPDs should be forward to DL callback regardless of IP types (IPv4/IPv6) */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  total_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Binded] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                total_cnt = ipv4_cnt + ipv6_cnt;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            0,
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL,
+                                            NULL,
+                                            did_cnt,
+                                            KAL_FALSE);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx);
+
+                if ( (did_cnt != ipc_ut_dl_callback_did_cnt) ||
+                     (total_cnt != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is NOT forwarded to bound handler!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* DL callback is correctly called : all GPDs are released */
+            }
+        }
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* Simulate DL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Deactivated] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            0,
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL,
+                                            NULL,
+                                            did_cnt,
+                                            KAL_FALSE);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded after PDN deactivation!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_uplink_filter_meta(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32                          callback_with_info;
+    kal_uint32                          idx;
+    ipc_ut_netif_t                      *net;
+    kal_uint32                          netif_id = IPC_UT_LHIF_NETID_START;
+    ipcore_upcm_pdn_bind_ind_struct     *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct    *deact_req;
+    kal_uint8                           ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool                            result;
+    kal_uint32                          total_cnt;
+    kal_uint32                          ipv4_cnt;
+    kal_uint32                          ipv6_cnt;
+    kal_uint32                          ipv4_filter_cnt;
+    kal_uint32                          ipv6_filter_cnt;
+    kal_uint32                          with_wildcard;
+    kal_uint32                          with_bwm;
+    kal_uint8                           matched_filter_idx_v4;
+    kal_uint8                           matched_filter_idx_v6;
+    kal_uint8                           test_stage;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 4; ipv4_cnt+=2)
+    for (ipv6_cnt = 2; ipv6_cnt <= 4; ipv6_cnt+=2)
+    for (ipv4_filter_cnt = 4; ipv4_filter_cnt <= 4; ipv4_filter_cnt+=4)
+    for (ipv6_filter_cnt = 4; ipv6_filter_cnt <= 4; ipv6_filter_cnt+=4)
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++)
+    for (with_wildcard = 0; with_wildcard < 2; with_wildcard++)
+    for (with_bwm = 0; with_bwm < 2; with_bwm++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < ipv4_filter_cnt; matched_filter_idx_v4++)
+    for (matched_filter_idx_v6 = 0; matched_filter_idx_v6 < ipv6_filter_cnt; matched_filter_idx_v6++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+        utDLOG("ifo(%d) v4Cnt(%d) v6Cnt(%d) v4FltCnt(%d) v6FltCnt(%d) withWC(%d) withBWM(%d) IPType(%d) v4Idx(%d) v6Idx(%d)\r\n",
+                        callback_with_info, ipv4_cnt, ipv6_cnt, ipv4_filter_cnt , ipv6_filter_cnt, with_wildcard, with_bwm, idx, matched_filter_idx_v4, matched_filter_idx_v6);
+
+        total_cnt = ipv4_cnt + ipv6_cnt;
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+
+        /* Install UL filter for each test loop */
+        ipc_ut_install_ul_filters(callback_with_info, KAL_TRUE, ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm, matched_filter_idx_v4, matched_filter_idx_v6, IPC_UT_LHIF_NETID_START);
+
+        /*
+         * ipc_attach()
+         */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = netif_id;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+        net->conf.features = 0;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+            return KAL_FALSE;
+        }
+
+        /*
+         * Before activate, the UL packet from this network interface
+         *   1. CAN be filtered out
+         *   2. CAN NOT be forwarded to UPCM
+         */
+        {
+            kal_uint32          dhcpv4_idx;
+            kal_uint32          dhcpv6_idx;
+            kal_uint32          head_idx;
+            kal_uint32          tail_idx;
+            LHIF_QUEUE_TYPE     q_type;
+
+            test_stage = IPC_UT_STAGE_BEFORE_BINDING;
+
+            for (dhcpv4_idx = 0 ; ((ipv4_cnt == 0 && dhcpv4_idx == 0) || (dhcpv4_idx < ipv4_cnt)) ; dhcpv4_idx+=2)
+            for (dhcpv6_idx = 0 ; ((ipv6_cnt == 0 && dhcpv6_idx == 0) || (dhcpv6_idx < ipv6_cnt)) ; dhcpv6_idx+=2) {
+                kal_uint32 expected_ul_v4_filter_out_cnt;
+                kal_uint32 expected_ul_v6_filter_out_cnt;
+                kal_uint32 expected_ul_filter_out_cnt;
+
+                utDLOG("@ Before activation : dhcpv4Idx(%d), dhcpv6Idx(%d)\r\n",
+                                dhcpv4_idx, dhcpv6_idx);
+
+
+                ipc_ut_prepare_ul_meta_list(KAL_TRUE, ipv4_cnt, dhcpv4_idx, ipv6_cnt, dhcpv6_idx, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_ul_filter_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                /*
+                 *  1. If least 1 IPv4 filter rule & 1 IPv4 gpd -> least 1 packet (DHCPv4) will be filtered out
+                 *  2. If least 1 IPv6 filter rule & 1 IPv6 gpd -> least 1 packet (DHCPv6) will be filtered out
+                 *  3. NO any packet will been forwarded to network before PDN bind
+                 */
+                if (with_wildcard) {
+                    expected_ul_v4_filter_out_cnt = ipv4_cnt - (((ipv4_cnt > 0) && with_bwm)?1:0);
+                    expected_ul_v6_filter_out_cnt = ipv6_cnt - (((ipv6_cnt > 0) && with_bwm)?1:0);
+                } else {
+                    expected_ul_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                      (ipv4_cnt > 0) &&
+                                                      (!with_bwm) )? 1:0;
+                    expected_ul_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                      (ipv6_cnt > 0) &&
+                                                      (!with_bwm) )?1:0;
+                }
+                expected_ul_filter_out_cnt = expected_ul_v4_filter_out_cnt + expected_ul_v6_filter_out_cnt;
+
+                if (callback_with_info && expected_ul_filter_out_cnt > 0) {
+                    if (ipc_ut_ul_filter_info.netif_id != net->conf.netif_id) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != ipc_get_ip_id(net->handle)) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                } else {
+                    if (ipc_ut_ul_filter_info.netif_id != 0) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != -1) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                }
+
+                if (ipc_ut_ul_filter_gpd_cnt != expected_ul_filter_out_cnt) {
+                    utELOG("Filtered-out gpd count is incorrect!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (0 != ipc_ut_ul_meta_non_igr_cnt) ) {
+                    utELOG("UL META is forwarded to network before valid PDN binding!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+         * Activate IPv4/IPv4v6/IPv6 PDN
+         *
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        /*
+         * After PDN binding activate, the UL packet from this network interface
+         *   1. CAN be filtered out
+         *   2. CAN be forwarded to UPCM
+         */
+        {
+            kal_uint32          dhcpv4_idx;
+            kal_uint32          dhcpv6_idx;
+            kal_uint32          head_idx;
+            kal_uint32          tail_idx;
+            LHIF_QUEUE_TYPE     q_type;
+
+            test_stage = IPC_UT_STAGE_BINDING;
+            for (dhcpv4_idx = 0 ; ((ipv4_cnt == 0 && dhcpv4_idx == 0) || (dhcpv4_idx < ipv4_cnt)) ; dhcpv4_idx+=2)
+            for (dhcpv6_idx = 0 ; ((ipv6_cnt == 0 && dhcpv6_idx == 0) || (dhcpv6_idx < ipv6_cnt)) ; dhcpv6_idx+=2) {
+                kal_uint32 expected_ul_v4_filter_out_cnt;
+                kal_uint32 expected_ul_v6_filter_out_cnt;
+                kal_uint32 expected_ul_filter_out_cnt;
+                kal_uint32 expected_ul_cnt;
+
+                utDLOG("@ PDN connected : dhcpv4Idx(%d), dhcpv6Idx(%d)\r\n",
+                                dhcpv4_idx, dhcpv6_idx);
+
+                ipc_ut_prepare_ul_meta_list(KAL_TRUE, ipv4_cnt, dhcpv4_idx, ipv6_cnt, dhcpv6_idx, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_ul_filter_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                /*
+                 *  1. If least 1 IPv4 filter rule & 1 IPv4 gpd -> least 1 packet (DHCPv4) will be filtered out
+                 *  2. If least 1 IPv6 filter rule & 1 IPv6 gpd -> least 1 packet (DHCPv6) will be filtered out
+                 *  3. All non-filtered GPDs with matched IP type will been forwarded to network
+                 */
+                if (with_wildcard) {
+                    expected_ul_v4_filter_out_cnt = ipv4_cnt - (((ipv4_cnt > 0) && with_bwm)?1:0);
+                    expected_ul_v6_filter_out_cnt = ipv6_cnt - (((ipv6_cnt > 0) && with_bwm)?1:0);
+                } else {
+                    expected_ul_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                      (ipv4_cnt > 0) &&
+                                                      (!with_bwm) )? 1:0;
+                    expected_ul_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                      (ipv6_cnt > 0) &&
+                                                      (!with_bwm) )?1:0;
+                }
+                expected_ul_filter_out_cnt = expected_ul_v4_filter_out_cnt + expected_ul_v6_filter_out_cnt;
+
+                if (callback_with_info && expected_ul_filter_out_cnt > 0) {
+                    if (ipc_ut_ul_filter_info.netif_id != net->conf.netif_id) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != ipc_get_ip_id(net->handle)) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                } else {
+                    if (ipc_ut_ul_filter_info.netif_id != 0) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != -1) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                }
+
+                if (ipc_ut_ul_filter_gpd_cnt != expected_ul_filter_out_cnt) {
+                    utELOG("Filtered-out gpd count is incorrect!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                expected_ul_cnt =   (bind_req->ip_addr.ip_addr_type == IPV4_ADDR_TYPE)?(ipv4_cnt - expected_ul_v4_filter_out_cnt):
+                                    (bind_req->ip_addr.ip_addr_type == IPV6_ADDR_TYPE)?(ipv6_cnt - expected_ul_v6_filter_out_cnt):
+                                    ((ipv4_cnt + ipv6_cnt) - (expected_ul_filter_out_cnt));
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (expected_ul_cnt != ipc_ut_ul_meta_non_igr_cnt) ) {
+                    utELOG("UL META is not forwarded to network correctly!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+                if ((expected_ul_cnt > 0) &&
+                    (ipc_ut_ul_pdn_id != bind_req->pdn_id)) {
+                    utELOG("UL META is not forwarded to correct network PDN!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /*
+         * After deactivate, the UL packet from this network interface
+         *   1. CAN be filtered out
+         *   2. CAN NOT be forwarded to UPCM
+         */
+        {
+            kal_uint32          dhcpv4_idx;
+            kal_uint32          dhcpv6_idx;
+            kal_uint32          head_idx;
+            kal_uint32          tail_idx;
+            LHIF_QUEUE_TYPE     q_type;
+
+            test_stage = IPC_UT_STAGE_UNBINDING;
+            for (dhcpv4_idx = 0 ; ((ipv4_cnt == 0 && dhcpv4_idx == 0) || (dhcpv4_idx < ipv4_cnt)) ; dhcpv4_idx+=2)
+            for (dhcpv6_idx = 0 ; ((ipv6_cnt == 0 && dhcpv6_idx == 0) || (dhcpv6_idx < ipv6_cnt)) ; dhcpv6_idx+=2) {
+                kal_uint32 expected_ul_v4_filter_out_cnt;
+                kal_uint32 expected_ul_v6_filter_out_cnt;
+                kal_uint32 expected_ul_filter_out_cnt;
+
+                utDLOG("@ After deactivation : dhcpv4Idx(%d), dhcpv6Idx(%d)\r\n",
+                                dhcpv4_idx, dhcpv6_idx);
+
+                ipc_ut_prepare_ul_meta_list(KAL_TRUE, ipv4_cnt, dhcpv4_idx, ipv6_cnt, dhcpv6_idx, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_ul_filter_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                /*
+                 *  1. If least 1 IPv4 filter rule & 1 IPv4 gpd -> least 1 packet (DHCPv4) will be filtered out
+                 *  2. If least 1 IPv6 filter rule & 1 IPv6 gpd -> least 1 packet (DHCPv6) will be filtered out
+                 *  3. NO any packet will been forwarded to network after PDN deactivation
+                 */
+                if (with_wildcard) {
+                    expected_ul_v4_filter_out_cnt = ipv4_cnt - (((ipv4_cnt > 0) && with_bwm)?1:0);
+                    expected_ul_v6_filter_out_cnt = ipv6_cnt - (((ipv6_cnt > 0) && with_bwm)?1:0);
+                } else {
+                    expected_ul_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                      (ipv4_cnt > 0) &&
+                                                      (!with_bwm) )? 1:0;
+                    expected_ul_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                      (ipv6_cnt > 0) &&
+                                                      (!with_bwm) )?1:0;
+                }
+                expected_ul_filter_out_cnt = expected_ul_v4_filter_out_cnt + expected_ul_v6_filter_out_cnt;
+
+                if (callback_with_info && expected_ul_filter_out_cnt > 0) {
+                    if (ipc_ut_ul_filter_info.netif_id != net->conf.netif_id) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != ipc_get_ip_id(net->handle)) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                } else {
+                    if (ipc_ut_ul_filter_info.netif_id != 0) {
+                        utELOG("Filtered-out netif ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ip_id != -1) {
+                        utELOG("Filtered-out IP ID is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                    if (ipc_ut_ul_filter_info.ebi != -1) {
+                        utELOG("Filtered-out EBI is incorrect!\r\r");
+                        ipc_ut_free_gpd_list(NULL, NULL);
+                        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                        return KAL_FALSE;
+                    }
+                }
+
+                if (ipc_ut_ul_filter_gpd_cnt != expected_ul_filter_out_cnt) {
+                    utELOG("Filtered-out gpd count is incorrect!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (0 != ipc_ut_ul_meta_non_igr_cnt) ) {
+                    utELOG("UL META is forwarded to network before valid PDN binding!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+         * ipc_detach().
+         */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+            return KAL_FALSE;
+        }
+
+
+        /* Uninstall UL filters after test procedure */
+        ipc_ut_uninstall_ul_filters(ipv4_filter_cnt, ipv6_filter_cnt, with_wildcard, with_bwm);
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_did_downlink_wo_dhcp4c(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool          result;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /*
+         * ipc_attach()
+         */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_LHIF_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+        net->conf.features = 0;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+         /*
+          *   Simulate DL traffic to IPCore : Before PDN binding, all DIDs should be silently dropped by IPCore and NO callback is triggered
+          */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+            kal_uint32  did_igr_bit;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Before Bind] ip_type(%d),v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", idx, ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            0,
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL,
+                                            NULL,
+                                            did_cnt,
+                                            did_igr_bit);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded before PDN binding!\r\n", did_igr_bit);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+         /*
+          *   Simulate DL traffic to IPCore : All DIDs should be forward to DL callback regardless of IP types (IPv4/IPv6)
+          */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+            kal_uint32  did_igr_bit;
+            kal_uint32  total_cnt;
+            kal_uint32  i;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Binded] ip_type(%d),v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", idx, ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                total_cnt = ipv4_cnt + ipv6_cnt;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            0,
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL,
+                                            NULL,
+                                            did_cnt,
+                                            did_igr_bit);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+
+                if (1 == did_igr_bit) {
+                    kal_uint32 ipv4_igr_cnt = 0;
+                    kal_uint32 ipv6_igr_cnt = 0;
+
+                    for (i = 0; i < ipv4_cnt; i++) {
+                        ipv4_igr_cnt += ipc_ut_did_packet_igr_s[i];
+                    }
+                    for (i = 0; i < ipv6_cnt; i++) {
+                        ipv6_igr_cnt += ipc_ut_did_packet_igr_s[i];
+                    }
+                    if ( (ipv4_igr_cnt) &&
+                         (ipv4_cnt == ipv4_igr_cnt) ) {
+                        /* All IPv4 DID pkt has been ignored. */
+                        did_cnt --;
+                    }
+                    if ( (ipv6_igr_cnt) &&
+                         (ipv6_cnt == ipv6_igr_cnt) ) {
+                        /* All IPv6 DID pkt has been ignored. */
+                        did_cnt --;
+                    }
+
+                    total_cnt -= (ipv4_igr_cnt + ipv6_igr_cnt);
+                    if (!did_cnt) {
+                        UT_ASSERT(total_cnt == 0);
+                    }
+                }
+
+                if ( (total_cnt != ipc_ut_dl_callback_did_pkt_cnt) ||
+                     (did_cnt != ipc_ut_dl_callback_did_cnt) ) {
+                    utELOG("DL DID is NOT forwarded to bound handler!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* DL callback is correctly called : all GPDs are released */
+            }
+        }
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+         /*
+          *   Simulate DL traffic to IPCore : After PDN deactivation, all DIDs should be silently dropped by IPCore and NO callback is triggered
+          */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  total_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+            kal_uint32  did_igr_bit;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Deactivated] ip_type(%d),v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", idx, ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                total_cnt = ipv4_cnt + ipv6_cnt;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            0,
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL,
+                                            NULL,
+                                            did_cnt,
+                                            did_igr_bit);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded after PDN deactivation!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * ipc_detach().
+         */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_did_downlink_w_dhcp4c(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+/* Note : This test case will trigger NMU to allocate NET_UL GPD,
+          Please be aware of that NET_UL GPD is only used in MD-only load.
+*/
+
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool          result;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /*
+         * ipc_attach()
+         */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_LHIF_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+        net->conf.features = IPC_F_DHCP4C;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+         /*
+          *   Simulate DL traffic to IPCore : Before PDN binding, all DIDs should be silently dropped by IPCore and NO callback is triggered
+          */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+            kal_uint32  did_igr_bit;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Before Bind] ip_type(%d),v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", idx, ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            0,
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL,
+                                            NULL,
+                                            did_cnt,
+                                            did_igr_bit);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        /*
+         *   Simulate DL traffic to IPCore
+         *
+         *   - 1st IPv4 DID is IPv4 DHCP packet and will be sent to DHCP4C module
+         *   - All other DIDs should be forward to DL callback regardless of IP types (IPv4/IPv6)
+         *
+         */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+            kal_uint32  did_igr_bit;
+            kal_uint32  total_cnt;
+            kal_uint32  i;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Binded] ip_type(%d),v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", idx, ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                total_cnt = ipv4_cnt + ipv6_cnt;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+//                                             (unite == 0)?0:10,
+                                            0,
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL,
+                                            NULL,
+                                            did_cnt,
+                                            did_igr_bit);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                /* In Gen97, we add session state in ipc_on_did_downlink() before forwarding data to bound interface.
+                 * If session is not in link up state, then IPCore should not send any packets to bound interface.
+                 * At this case, if there is no IPv4 packets, then the session will stay in bind state.
+                 * So IPCore will drop all packets in this state.
+                 */
+
+                if ((IPV4_ADDR_TYPE == ip_types[idx]) || (IPV4V6_ADDR_TYPE == ip_types[idx])) {
+                    if ((0 != ipc_ut_dl_callback_did_cnt) ||
+                        (0 != ipc_ut_dl_callback_did_pkt_cnt)) {
+                        utELOG("DL DID is forwarded to bound handler!\r\n");
+                        return KAL_FALSE;
+                    }
+                } else {
+                    if ((total_cnt != ipc_ut_dl_callback_did_pkt_cnt) ||
+                        (did_cnt != ipc_ut_dl_callback_did_cnt)) {
+                        utELOG("DL DID is NOT forwarded to bound handler!\r\n");
+                        return KAL_FALSE;
+                    }
+                }
+            }
+        }
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+         /*
+                *   Simulate DL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered
+                */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  total_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+            kal_uint32  did_igr_bit;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Deactivated] ip_type(%d),v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", idx, ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                total_cnt = ipv4_cnt + ipv6_cnt;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+                                            ipv6_cnt,
+                                            0,
+                                            KAL_FALSE,
+                                            KAL_FALSE,
+//                                             (unite == 0)?0:10,
+                                            0,
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL,
+                                            NULL,
+                                            did_cnt,
+                                            did_igr_bit);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded after PDN deactivation!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * ipc_detach().
+         */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+static kal_bool ipc_ut_fin_ack_filter_netif_attach(void) {
+    ipc_conf_t config = {0};
+    ipc_handle_t p_handle = NULL;
+    kal_bool ret = KAL_TRUE;
+
+    config.module_id = MOD_IPCORE;
+    config.netif_id = IPC_UT_LHIF_NETID_START;
+    config.features = 0;
+    config.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    config.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    config.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+
+    UT_ASSERT(KAL_TRUE == ipc_attach(&config, &p_handle));
+    UT_ASSERT(NULL != p_handle);
+    utDLOG("netif id = %d attach successfully", config.netif_id);
+
+    return KAL_TRUE;
+}
+
+static void ipc_ut_fin_ack_filter_did_verification(void) {
+    kal_uint8 *p_packet = NULL;
+    qbm_gpd *p_bd = NULL;
+    qbm_gpd *p_current = ipc_ut_ul_ebi_head_gpd;
+    kal_uint8 i = 0;
+    kal_bool is_check = KAL_FALSE;
+    kal_bool is_ipv4 = KAL_FALSE;
+
+    for (i = 0; i < ipc_ut_gpd_list_count(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd); i++) {
+        if (!QBM_DES_GET_BDP(ipc_ut_ul_ebi_head_gpd)) {
+            p_packet = QBM_DES_GET_DATAPTR(ipc_ut_ul_ebi_head_gpd);
+
+            if (sizeof(ipc_ut_ipv4_tcp_fin_ack_packet) == QBM_DES_GET_DATALEN(ipc_ut_ul_ebi_head_gpd)) {
+                is_check = KAL_TRUE;
+                is_ipv4 = KAL_TRUE;
+            } else if (sizeof(ipc_ut_ipv6_tcp_fin_ack_packet) == QBM_DES_GET_DATALEN(ipc_ut_ul_ebi_head_gpd)) {
+                is_check = KAL_TRUE;
+                is_ipv4 = KAL_FALSE;
+            }
+        } else {
+            p_bd = QBM_DES_GET_DATAPTR(ipc_ut_ul_ebi_head_gpd);
+
+            while (p_bd && (QBM_DES_GET_DATALEN(p_bd) == 0)) {
+                p_bd = (QBM_DES_GET_EOL(p_bd)) ? (NULL) : ((qbm_gpd*) QBM_DES_GET_NEXT(p_bd));
+            }
+
+            if (NULL == p_bd) {
+                ipc_ut_free_gpd_list(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+            }
+            p_packet = QBM_DES_GET_DATAPTR(p_bd);
+
+            if (sizeof(ipc_ut_ipv4_tcp_fin_ack_packet) == QBM_DES_GET_DATALEN(ipc_ut_ul_ebi_head_gpd)) {
+                is_check = KAL_TRUE;
+                is_ipv4 = KAL_TRUE;
+            } else if (sizeof(ipc_ut_ipv6_tcp_fin_ack_packet) == QBM_DES_GET_DATALEN(ipc_ut_ul_ebi_head_gpd)) {
+                is_check = KAL_TRUE;
+                is_ipv4 = KAL_FALSE;
+            }
+            p_packet = QBM_DES_GET_DATAPTR(p_bd);
+        }
+
+        if (is_check) {
+            kal_uint32 ip_header_len = is_ipv4 ? IPC_HDR_V4_HEADER_SIZE : IPC_HDR_V6_HEADER_SIZE;
+            kal_uint8 *src_addr = NULL;
+            kal_uint8 *dst_addr = NULL;
+            kal_uint32 tcp_header_len = 0;
+            kal_uint8 *p_src_tcp_header = NULL;
+            kal_uint8 *tcp_header = NULL;
+            kal_bool is_matched_packet = KAL_FALSE;
+
+            src_addr = IPC_HDR_V4_GET_SRC_ADDR(p_packet);
+            dst_addr = IPC_HDR_V4_GET_DST_ADDR(p_packet);
+
+            if (is_ipv4) {
+                if ((0 == kal_mem_cmp(IPC_HDR_V4_GET_SRC_ADDR(p_packet), IPC_HDR_V4_GET_DST_ADDR(ipc_ut_ipv4_tcp_fin_ack_packet), 4)) &&
+                    (0 == kal_mem_cmp(IPC_HDR_V4_GET_DST_ADDR(p_packet), IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_ipv4_tcp_fin_ack_packet), 4))) {
+                    is_matched_packet = KAL_TRUE;
+                    p_src_tcp_header = ipc_ut_ipv4_tcp_fin_ack_packet + ip_header_len;
+                } else if ((0 == kal_mem_cmp(IPC_HDR_V4_GET_SRC_ADDR(p_packet), IPC_HDR_V4_GET_DST_ADDR(ipc_ut_ipv4_tcp_fin_ack_packet_2), 4)) &&
+                           (0 == kal_mem_cmp(IPC_HDR_V4_GET_DST_ADDR(p_packet), IPC_HDR_V4_GET_SRC_ADDR(ipc_ut_ipv4_tcp_fin_ack_packet_2), 4))) {
+                    is_matched_packet = KAL_TRUE;
+                    p_src_tcp_header = ipc_ut_ipv4_tcp_fin_ack_packet_2 + ip_header_len;
+                }
+
+                if (is_matched_packet) {
+                    tcp_header = p_packet + ip_header_len;
+                    tcp_header_len = IPC_HDR_TCP_HEADER_SIZE;
+
+                    UT_ASSERT((kal_uint8)(kal_uint8 *)IPC_HDR_V4_GET_PROTOCOL(p_packet) == (kal_uint8)IPC_HDR_PROT_TCP);
+                    UT_ASSERT(IPC_HDR_TCP_GET_DST_PORT(tcp_header) == IPC_HDR_TCP_GET_SRC_PORT(p_src_tcp_header));
+                    UT_ASSERT(IPC_HDR_TCP_GET_SRC_PORT(tcp_header) == IPC_HDR_TCP_GET_DST_PORT(p_src_tcp_header));
+                    UT_ASSERT(IPC_HDR_TCP_GET_FLAGS(tcp_header) == (IPC_HDR_TCP_FLAG_RST | IPC_HDR_TCP_FLAG_ACK));
+                }
+            } else {
+                if ((0 == kal_mem_cmp(IPC_HDR_V6_GET_SRC_ADDR(p_packet), IPC_HDR_V6_GET_DST_ADDR(ipc_ut_ipv6_tcp_fin_ack_packet), 16)) &&
+                    (0 == kal_mem_cmp(IPC_HDR_V6_GET_DST_ADDR(p_packet), IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_ipv6_tcp_fin_ack_packet), 16))) {
+                    is_matched_packet = KAL_TRUE;
+                    p_src_tcp_header = ipc_ut_ipv6_tcp_fin_ack_packet + ip_header_len;
+                } else if ((0 == kal_mem_cmp(IPC_HDR_V6_GET_SRC_ADDR(p_packet), IPC_HDR_V6_GET_DST_ADDR(ipc_ut_ipv6_tcp_fin_ack_packet_2), 16)) &&
+                           (0 == kal_mem_cmp(IPC_HDR_V6_GET_DST_ADDR(p_packet), IPC_HDR_V6_GET_SRC_ADDR(ipc_ut_ipv6_tcp_fin_ack_packet_2), 16))) {
+                    is_matched_packet = KAL_TRUE;
+                    p_src_tcp_header = ipc_ut_ipv6_tcp_fin_ack_packet_2 + ip_header_len;
+                }
+
+                if (is_matched_packet) {
+                    tcp_header = p_packet + ip_header_len;
+                    tcp_header_len = IPC_HDR_TCP_HEADER_SIZE;
+                    UT_ASSERT((kal_uint8)(kal_uint8 *)IPC_HDR_V6_GET_NH_TYPE(p_packet) == (kal_uint8)IPC_HDR_PROT_TCP);
+                    UT_ASSERT(IPC_HDR_TCP_GET_DST_PORT(tcp_header) == IPC_HDR_TCP_GET_SRC_PORT(p_src_tcp_header));
+                    UT_ASSERT(IPC_HDR_TCP_GET_SRC_PORT(tcp_header) == IPC_HDR_TCP_GET_DST_PORT(p_src_tcp_header));
+                    UT_ASSERT(IPC_HDR_TCP_GET_FLAGS(tcp_header) == (IPC_HDR_TCP_FLAG_RST | IPC_HDR_TCP_FLAG_ACK));
+                }
+            }
+        }
+        p_current = p_current->p_next;
+    }
+    qbmt_dest_q(ipc_ut_ul_ebi_head_gpd, ipc_ut_ul_ebi_tail_gpd);
+    ipc_ut_ul_ebi_head_gpd = NULL;
+    ipc_ut_ul_ebi_tail_gpd = NULL;
+}
+
+kal_bool ipc_ut_fin_ack_filter_did(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32 i = 0;
+    kal_uint32 ipv4_cnt = 0;
+    kal_uint32 ipv6_cnt = 0;
+    ipcore_upcm_pdn_bind_ind_struct *p_bind_req = NULL;
+    pfmApStatusInd *p_pfm_ap_ind_req = NULL;
+
+    /* initialize before test & reset IPCORE */
+    ipc_ut_init();
+    UT_ASSERT(KAL_TRUE == ipc_reset());
+    ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt = 0;
+    g_received_cnt = 0;
+
+    /* netif attach */
+    UT_ASSERT(KAL_TRUE == ipc_ut_fin_ack_filter_netif_attach());
+
+    /* IPv4 binding */
+    p_bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    p_bind_req->network_interface_id = IPC_UT_LHIF_NETID_START;
+    p_bind_req->pdn_id = IPC_UT_PDN_ID;
+    p_bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *) p_bind_req);
+    free_local_para((local_para_struct *)p_bind_req);
+
+    /* AP send suspend indication */
+    p_pfm_ap_ind_req = (pfmApStatusInd *)construct_local_para(sizeof(pfmApStatusInd), TD_RESET);
+    UT_ASSERT(NULL != p_pfm_ap_ind_req);
+    p_pfm_ap_ind_req->em_ap_status = PFM_AP_STATUS_SUSPEND;
+    p_pfm_ap_ind_req->bm_cmd = PFM_AP_CMD_FIN_ACK_REDUCTION;
+    UT_ASSERT(KAL_TRUE == msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_AP_STATUS_IND, (local_para_struct *)p_pfm_ap_ind_req, NULL));
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /* Simulate DL traffic to IPCore : Before PDN binding, all DIDs should be silently dropped by IPCore and NO callback is triggered */
+    {
+        kal_uint32 did_cnt = 0;
+        upcm_did *did_head = NULL;
+        upcm_did *did_tail = NULL;
+        kal_uint32 alignment = 0;
+        kal_uint32 did_igr_bit = 0;
+        kal_uint32 free_cnt = 0;
+
+        for (alignment = 0; alignment < 4; alignment++)
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+        for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+                continue;
+            }
+
+            utDLOG("@ [Before Bind] v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+            did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_prepare_pfm_fin_ack_dl_did_list(ipv4_cnt,
+                                                   0,
+                                                   KAL_FALSE,
+                                                   KAL_FALSE,
+                                                   ipv6_cnt,
+                                                   0,
+                                                   KAL_FALSE,
+                                                   KAL_FALSE,
+                                                   0,
+                                                   alignment,
+                                                   &did_head,
+                                                   &did_tail,
+                                                   NULL,
+                                                   NULL,
+                                                   did_cnt,
+                                                   did_igr_bit);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            /* verify filter result */
+            if (NULL != ipc_ut_ul_ebi_head_gpd) {
+                ipc_ut_fin_ack_filter_did_verification();
+            }
+        }
+    }
+
+    /* reset received count */
+    UT_ASSERT(g_received_cnt == ipc_ut_garbage_filter_expect_tcp_rst_gpd_cnt);
+    g_received_cnt = 0;
+
+    /* AP send wake up indication */
+    p_pfm_ap_ind_req = (pfmApStatusInd *)construct_local_para(sizeof(pfmApStatusInd), TD_RESET);
+    UT_ASSERT(NULL != p_pfm_ap_ind_req);
+    p_pfm_ap_ind_req->em_ap_status = PFM_AP_STATUS_WAKE_UP;
+    p_pfm_ap_ind_req->bm_cmd = PFM_AP_CMD_NONE;
+    msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_AP_STATUS_IND, (local_para_struct *)p_pfm_ap_ind_req, NULL);
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /* Simulate DL traffic to IPCore : Before PDN binding, all DIDs should be silently dropped by IPCore and NO callback is triggered */
+    {
+        kal_uint32 did_cnt;
+        upcm_did *did_head;
+        upcm_did *did_tail;
+        kal_uint32 alignment;
+        kal_uint32 did_igr_bit;
+        kal_uint32 free_cnt = 0;
+
+        for (alignment = 0; alignment < 4; alignment++)
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+        for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+                continue;
+            }
+
+            utDLOG("@ [Before Bind] v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+            did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_prepare_pfm_fin_ack_dl_did_list(ipv4_cnt,
+                                                   0,
+                                                   KAL_FALSE,
+                                                   KAL_FALSE,
+                                                   ipv6_cnt,
+                                                   0,
+                                                   KAL_FALSE,
+                                                   KAL_FALSE,
+                                                   0,
+                                                   alignment,
+                                                   &did_head,
+                                                   &did_tail,
+                                                   NULL,
+                                                   NULL,
+                                                   did_cnt,
+                                                   did_igr_bit);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if (NULL != ipc_ut_ul_ebi_head_gpd) {
+                ipc_ut_fin_ack_filter_did_verification();
+            }
+        }
+    }
+    UT_ASSERT(0 == g_received_cnt);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+kal_bool ipc_ut_meta_uplink_dpfm(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32                          blocked_cnt = 0;
+    ipc_ut_netif_t                     *net;
+    ipc_ut_netif_t                     *net2;
+    ipc_ut_netif_t                     *net3;
+    kal_bool                            result;
+    kal_uint32                          idx;
+    kal_uint8                           proto_idx[] = {0, 1};
+    ipcore_upcm_pdn_bind_ind_struct    *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct   *deact_req;
+    ilm_struct                          ilm;
+    kal_uint8                           test_stage;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* Activate DPFM */
+    ipc_ut_dpfm_is_activated_g = KAL_TRUE;
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_UT_LHIF_NETID_START;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() (DPFM device) */
+    net2 = &(ipc_ut_nets_s[1]);
+    kal_mem_set(net2, 0, sizeof(ipc_ut_netif_t));
+    net2->conf.module_id = MOD_IPCORE;
+    net2->conf.netif_id = IPC_UT_DPFM_NETID_START;
+    net2->conf.ul_reload_context = net2;
+    net2->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net2->conf.callback_context = net2;
+    net2->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net2->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did_dpfm;
+    net2->conf.features = IPC_F_LAN | IPC_F_TETHERING_ROUTE;
+    result = ipc_attach(&net2->conf, &net2->handle);
+    if (!result) {
+        utELOG("ipc_attach() (DPFM device) returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() (DPFM device 2) */
+    net3 = &(ipc_ut_nets_s[2]);
+    kal_mem_set(net3, 0, sizeof(ipc_ut_netif_t));
+    net3->conf.module_id = MOD_IPCORE;
+    net3->conf.netif_id = IPC_UT_DPFM_NETID_START + 1;
+    net3->conf.ul_reload_context = net3;
+    net3->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net3->conf.callback_context = net3;
+    net3->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net3->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did_dpfm;
+    net3->conf.features = IPC_F_LAN;
+    result = ipc_attach(&net3->conf, &net3->handle);
+    if (!result) {
+        utELOG("ipc_attach() (DPFM device 2) returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Simulate UL traffic to IPCore : Before PDN binding, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32 total_cnt;
+            kal_uint32 ipv4_cnt;
+            kal_uint32 ipv6_cnt;
+            kal_uint32 dpfm_device;
+            kal_uint32 netif_id;
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+            kal_uint8 non_ignore_cnt;
+            kal_uint8 allmatch;
+
+            test_stage = IPC_UT_STAGE_BEFORE_BINDING;
+            for (allmatch = 0; allmatch < 2; allmatch++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 8; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 8; ipv6_cnt++)
+            for (dpfm_device = 0; dpfm_device <= 1; dpfm_device++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                /* It should not generate DPFM related meta result which is comes from LAN NETIF without rounting fearue */
+                if (1 == dpfm_device && (ipv4_cnt >= 4 || ipv6_cnt >= 4)) continue;
+
+                utDLOG("@ [Before Bind] allmatch(%d), proto_idx(%d), v4_cnt(%d), v6_cnt(%d), dpfm_device(%d)\r\n", allmatch, idx, ipv4_cnt, ipv6_cnt, dpfm_device);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                netif_id = (dpfm_device == 0) ? IPC_UT_DPFM_NETID_START
+                                             : IPC_UT_DPFM_NETID_START + 1;
+
+                ipc_ut_prepare_ul_meta_list_dpfm(allmatch, ipv4_cnt, ipv6_cnt, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                non_ignore_cnt = 0;
+                /*
+                 * if pkt_cnt is 8, then the last meta will be DPFM_ADD_CMD.
+                 * And this command should be forwarded to UPCM.
+                 */
+                if(ipv4_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+                if(ipv6_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_dl_callback_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (non_ignore_cnt != ipc_ut_ul_meta_non_igr_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_cnt) ) {
+                    utELOG("Packet is forwarded before PDN binding! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM + idx, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+        free_local_para((local_para_struct *)bind_req);
+
+        /* Bind LAN netifs. */
+        ipc_bind_lan_netif(net2->conf.netif_id, net3->conf.netif_id);
+
+        /* Simulate UL traffic to IPCore : All GPDs should be forward to UL callback regardless of IP types (IPv4/IPv6) */
+        {
+            kal_uint32 total_cnt;
+            kal_uint32 dpfm_pkt_cnt;
+            kal_uint32 lan_pkt_cnt;
+            kal_uint32 lan_did_cnt;
+            kal_uint32 ipv4_cnt;
+            kal_uint32 ipv6_cnt;
+            kal_uint32 dpfm_device;
+            kal_uint32 netif_id;
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+            kal_uint8 dpfm_cmd_cnt;
+            kal_uint8 dpfm_cmd_cnt_v4;
+            kal_uint8 dpfm_cmd_cnt_v6;
+            kal_uint8 non_ignore_cnt;
+            kal_uint8 allmatch;
+
+            test_stage = IPC_UT_STAGE_BINDING;
+            for (allmatch = 0; allmatch < 2; allmatch++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 8; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 8; ipv6_cnt++)
+            for (dpfm_device = 0; dpfm_device <= 1; dpfm_device++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                /* It should not generate DPFM related meta result which is comes from AP LAN NETIF(dpfm_device==1) without rounting fearue */
+                if (1 == dpfm_device && (ipv4_cnt >= 4 || ipv6_cnt >= 4)) continue;
+
+                utDLOG("@ [Binded] allmatch(%d), proto_idx(%d), v4_cnt(%d), v6_cnt(%d), dpfm_device(%d)\r\n", allmatch, idx, ipv4_cnt, ipv6_cnt, dpfm_device);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                netif_id = (dpfm_device == 0) ? IPC_UT_DPFM_NETID_START
+                                             : IPC_UT_DPFM_NETID_START + 1;
+
+                dpfm_cmd_cnt = 0;
+                dpfm_cmd_cnt_v4 = 0;
+                dpfm_cmd_cnt_v6 = 0;
+                if (ipv4_cnt > 5) {
+                    dpfm_cmd_cnt_v4 += (ipv4_cnt-5);
+                }
+                if (ipv6_cnt > 5) {
+                    dpfm_cmd_cnt_v6 += (ipv6_cnt-5);
+                }
+                dpfm_cmd_cnt = dpfm_cmd_cnt_v4 + dpfm_cmd_cnt_v6;
+
+                dpfm_pkt_cnt = 0;
+                if ((dpfm_device == 0) && (total_cnt > 0)) {
+                    if ( allmatch == 1 ) {
+                        if (ipv4_cnt > 4) {
+                            dpfm_pkt_cnt += (ipv4_cnt - dpfm_cmd_cnt_v4 -1); /* minus 1 for DPFM_MATCH_BUT_NO_NAT MR */
+                        } else {
+                            dpfm_pkt_cnt += ipv4_cnt;
+                        }
+                        if (ipv6_cnt > 4) {
+                            dpfm_pkt_cnt += (ipv6_cnt - dpfm_cmd_cnt_v6 -1); /* minus 1 for DPFM_MATCH_BUT_NO_NAT MR */
+                        } else {
+                            dpfm_pkt_cnt += ipv6_cnt;
+                        }
+                    } else if (allmatch == 0 ) {
+                        if (ipv4_cnt >= 4) {
+                            dpfm_pkt_cnt += 1; /*For DPFM_MATCH MR */
+                        }
+                        if (ipv6_cnt >= 4) {
+                            dpfm_pkt_cnt += 1; /*For DPFM_MATCH MR */
+                        }
+                    }
+                }
+
+                non_ignore_cnt = 0;
+                /*
+                 * if pkt_cnt is 8, then the last meta will be DPFM_ADD_CMD.
+                 * And this command should be forwarded to UPCM.
+                 */
+                if(ipv4_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+                if(ipv6_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+
+                lan_pkt_cnt = total_cnt - dpfm_pkt_cnt - dpfm_cmd_cnt;
+                lan_did_cnt = (lan_pkt_cnt == 0) ? 0 : 1;
+
+                ipc_ut_prepare_ul_meta_list_dpfm(allmatch, ipv4_cnt, ipv6_cnt, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_dl_callback_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     ((dpfm_pkt_cnt + non_ignore_cnt) != ipc_ut_ul_meta_non_igr_cnt) ||
+                     (lan_pkt_cnt != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ||
+                     (lan_did_cnt != ipc_ut_dl_callback_did_dpfm_cnt) ) {
+                    utELOG("Packet is not forwarded correctly! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+                if (ipc_ut_ul_meta_non_igr_cnt) {
+                    if (dpfm_pkt_cnt != 0 && IPC_UT_PDN_ID != ipc_ut_ul_pdn_id) {
+                        utELOG("UL META is forwarded with wrong PDN ID! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                        ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                        return KAL_FALSE;
+                    }
+                    if (dpfm_pkt_cnt != 0 && idx != ipc_ut_ul_proto_idx) {
+                        utELOG("UL META is forwarded with wrong Protocol ID! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                        ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                        return KAL_FALSE;
+                    }
+                }
+            }
+        }
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* Unbind LAN netifs. */
+        ipc_unbind_lan_netif(net2->conf.netif_id, net3->conf.netif_id);
+
+        /* Simulate UL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32 total_cnt;
+            kal_uint32 ipv4_cnt;
+            kal_uint32 ipv6_cnt;
+            kal_uint32 dpfm_device;
+            kal_uint32 netif_id;
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+            kal_uint8 allmatch;
+            kal_uint8 non_ignore_cnt;
+
+            test_stage = IPC_UT_STAGE_UNBINDING;
+            for (allmatch = 0; allmatch < 2; allmatch++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 8; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 8; ipv6_cnt++)
+            for (dpfm_device = 0; dpfm_device <= 1; dpfm_device++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                /* It should not generate DPFM related meta result which is comes from LAN NETIF without rounting fearue */
+                if (1 == dpfm_device && (ipv4_cnt >= 4 || ipv6_cnt >= 4)) continue;
+
+                utDLOG("@ [Deactivated] allmatch(%d), proto_idx(%d), v4_cnt(%d), v6_cnt(%d), dpfm_device(%d)\r\n", allmatch, idx, ipv4_cnt, ipv6_cnt, dpfm_device);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                netif_id = (dpfm_device == 0) ? IPC_UT_DPFM_NETID_START
+                                             : IPC_UT_DPFM_NETID_START + 1;
+
+                ipc_ut_prepare_ul_meta_list_dpfm(KAL_TRUE, ipv4_cnt, ipv6_cnt, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                non_ignore_cnt = 0;
+                /*
+                 * if pkt_cnt is 8, then the last meta will be DPFM_ADD_CMD.
+                 * And this command should be forwarded to UPCM.
+                 */
+                if(ipv4_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+                if(ipv6_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_dl_callback_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (non_ignore_cnt != ipc_ut_ul_meta_non_igr_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_cnt) ) {
+                    utELOG("Packet is forwarded after PDN deactivation! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+            }
+        }
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_did_downlink_dpfm(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32        idx;
+    ipc_ut_netif_t   *net;
+    ipc_ut_netif_t   *net2;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_bool          result;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * Activate DPFM
+     */
+    ipc_ut_dpfm_is_activated_g = KAL_TRUE;
+
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /*
+         * ipc_attach()
+         */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = IPC_UT_LHIF_NETID_START + idx;
+        net->conf.ul_reload_context = net;
+        net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+        result = ipc_attach(&net->conf, &net->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * ipc_attach() (DPFM device)
+         */
+        net2 = &(ipc_ut_nets_s[1]);
+        kal_mem_set(net2, 0, sizeof(ipc_ut_netif_t));
+        net2->conf.module_id = MOD_IPCORE;
+        net2->conf.netif_id = IPC_UT_DPFM_NETID_START;
+        net2->conf.ul_reload_context = net2;
+        net2->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        net2->conf.callback_context = net2;
+        net2->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+        net2->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did_dpfm;
+        net2->conf.features = IPC_F_LAN | IPC_F_TETHERING_ROUTE;
+        result = ipc_attach(&net2->conf, &net2->handle);
+        if (!result) {
+            utELOG("ipc_attach() (DPFM device) returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+         /*
+          *   Simulate DL traffic to IPCore : Before PDN binding, all DIDs should be silently dropped by IPCore and NO callback is triggered
+          */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+            kal_uint32  did_igr_bit;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Before Bind] ip_type(%d),v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", idx, ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0, /* dhcpv4_idx */
+                                            KAL_FALSE, /* dnsv4_only */
+                                            KAL_FALSE, /* v4hdr_exist */
+                                            ipv6_cnt,
+                                            0, /* dhcpv6_idx */
+                                            KAL_FALSE, /* dnsv6_only */
+                                            KAL_FALSE, /* v6hdr_exist */
+                                            0, /* additional_bd_cnt */
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL, /* ipv4_invalid_packet_len */
+                                            NULL, /* ipv6_invalid_packet_len */
+                                            did_cnt,
+                                            did_igr_bit);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded before PDN binding!\r\n", did_igr_bit);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Activate IPv4/IPv4v6/IPv6 PDN with unspecified IP address.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        /*
+         *   Simulate DL traffic to IPCore
+         *
+         *   - 1st IPv4 DID is IPv4 DHCP packet and will be sent to DPFM device
+         *   - All other DIDs should be forward to DL callback regardless of IP types (IPv4/IPv6)
+         *
+         */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+            kal_uint32  did_igr_bit;
+            kal_uint32  total_cnt;
+            kal_uint32  dpfm_pkt_cnt;
+            kal_uint32  dpfm_did_cnt;
+            kal_uint32  i;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Binded] ip_type(%d),v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", idx, ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                dpfm_pkt_cnt = 0;
+                dpfm_did_cnt = 0;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0, /* dhcpv4_idx */
+                                            KAL_FALSE, /* dnsv4_only */
+                                            KAL_FALSE, /* v4hdr_exist */
+                                            ipv6_cnt,
+                                            0, /* dhcpv6_idx */
+                                            KAL_FALSE, /* dnsv6_only */
+                                            KAL_FALSE, /* v6hdr_exist */
+                                            0, /* additional_bd_cnt */
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL, /* ipv4_invalid_packet_len */
+                                            NULL, /* ipv6_invalid_packet_len */
+                                            did_cnt,
+                                            did_igr_bit);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if  (ipv4_cnt > 0) {
+                    dpfm_did_cnt = 1;
+                    dpfm_pkt_cnt = 1;
+
+                    if(ipv6_cnt > 0){
+                        dpfm_pkt_cnt++;
+                        dpfm_did_cnt++; /* Because IPv4 and IPv6 are sent by two DIDs. */
+                    }
+
+                    if (1 == did_igr_bit) {
+                        kal_uint32 ipv4_igr_cnt = 0;
+                        kal_uint32 ipv6_igr_cnt = 0;
+
+                        /* the first packet would be filtered out, so add the duplicate substration back. */
+                        total_cnt ++;
+
+                        for (i = 0; i < ipv4_cnt; i++) {
+                            ipv4_igr_cnt += ipc_ut_did_packet_igr_s[i];
+                        }
+                        for (i = 0; i < ipv6_cnt; i++) {
+                            ipv6_igr_cnt += ipc_ut_did_packet_igr_s[i];
+                        }
+                        if ( (ipv4_igr_cnt) &&
+                             (ipv4_cnt == ipv4_igr_cnt) ) {
+                            /* All IPv4 DID pkt has been ignored. */
+                            did_cnt --;
+                        }
+                        if ( (ipv6_igr_cnt) &&
+                             (ipv6_cnt == ipv6_igr_cnt) ) {
+                            /* All IPv6 DID pkt has been ignored. */
+                            did_cnt --;
+                        }
+
+                        total_cnt -= (ipv4_igr_cnt + ipv6_igr_cnt);
+                        if (!did_cnt) {
+                            UT_ASSERT(total_cnt == 0);
+                        }
+                    } else {
+                        total_cnt -= dpfm_did_cnt;
+                        if(ipv4_cnt == 1) {
+                            /* All IPv4 DID pkt has been forward to LAN NETIF */
+                            did_cnt --;
+                        }
+                        if(ipv6_cnt == 1) {
+                            /* All IPv6 DID pkt has been forward to LAN NETIF */
+                            did_cnt --;
+                        }
+                        if (!did_cnt) {
+                            UT_ASSERT(total_cnt == 0);
+                        }
+                    }
+
+                    if ( (total_cnt != ipc_ut_dl_callback_did_pkt_cnt) ||
+                         (did_cnt != ipc_ut_dl_callback_did_cnt) ||
+                         (dpfm_pkt_cnt != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ||
+                         (dpfm_did_cnt != ipc_ut_dl_callback_did_dpfm_cnt) ) {
+                        utELOG("DL DID is NOT forwarded to bound handler!\r\n");
+                        return KAL_FALSE;
+                    }
+                } else {
+                    dpfm_did_cnt = 1;
+                    dpfm_pkt_cnt = 1;
+                    /* All DIDs should be handled by DL network interface */
+                    if (1 == did_igr_bit) {
+                        kal_uint32 ipv4_igr_cnt = 0;
+                        kal_uint32 ipv6_igr_cnt = 0;
+
+                        for (i = 0; i < ipv4_cnt; i++) {
+                            ipv4_igr_cnt += ipc_ut_did_packet_igr_s[i];
+                        }
+                        for (i = 0; i < ipv6_cnt; i++) {
+                            ipv6_igr_cnt += ipc_ut_did_packet_igr_s[i];
+                        }
+                        if ( (ipv4_igr_cnt) &&
+                             (ipv4_cnt == ipv4_igr_cnt) ) {
+                            /* All IPv4 DID pkt has been ignored. */
+                            did_cnt --;
+                        }
+                        if ( (ipv6_igr_cnt) &&
+                             (ipv6_cnt == ipv6_igr_cnt) ) {
+                            /* All IPv6 DID pkt has been ignored. */
+                            did_cnt --;
+                        }
+
+                        total_cnt -= (ipv4_igr_cnt + ipv6_igr_cnt);
+                        if (!did_cnt) {
+                            UT_ASSERT(total_cnt == 0);
+                        }
+                    } else {
+                        total_cnt -= dpfm_did_cnt;
+                        if(!total_cnt)
+                        {
+                            did_cnt--;
+                        }
+                    }
+
+                    if ( (total_cnt != ipc_ut_dl_callback_did_pkt_cnt) ||
+                         (did_cnt != ipc_ut_dl_callback_did_cnt) ||
+                         (dpfm_pkt_cnt != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ||
+                         (dpfm_did_cnt != ipc_ut_dl_callback_did_dpfm_cnt) ) {
+                        utELOG("DL DID is NOT forwarded to bound handler!\r\n");
+                        return KAL_FALSE;
+                    }
+                }
+                /* DL callback or DHCP4C indication are correctly called : all GPDs should be released */
+            }
+        }
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /*
+         * Simulate DL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered
+         */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  total_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+            kal_uint32  did_igr_bit;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Deactivated] ip_type(%d),v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", idx, ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                total_cnt = ipv4_cnt + ipv6_cnt;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_dl_did_list(ipv4_cnt,
+                                            0, /* dhcpv4_idx */
+                                            KAL_FALSE, /* dnsv4_only */
+                                            KAL_FALSE, /* v4hdr_exist */
+                                            ipv6_cnt,
+                                            0, /* dhcpv6_idx */
+                                            KAL_FALSE, /* dnsv6_only */
+                                            KAL_FALSE, /* v6hdr_exist */
+                                            0, /* additional_bd_cnt */
+                                            alignment,
+                                            &did_head,
+                                            &did_tail,
+                                            NULL, /* ipv4_invalid_packet_len */
+                                            NULL, /* ipv6_invalid_packet_len */
+                                            did_cnt,
+                                            did_igr_bit);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded after PDN deactivation!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * ipc_detach().
+         */
+        result = ipc_detach(net->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         * ipc_detach() (DPFM device).
+         */
+        result = ipc_detach(net2->handle);
+        if (!result) {
+            utELOG("ipc_detach() (DPFM device) returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_meta_uplink_dpfm_cmd_after_detach(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32                          blocked_cnt = 0;
+    ipc_ut_netif_t                     *net;
+    ipc_ut_netif_t                     *net2;
+    ipc_ut_netif_t                     *net3;
+    kal_bool                            result;
+    kal_uint32                          idx;
+    kal_uint8                           proto_idx[] = {0, 1};
+    ipcore_upcm_pdn_bind_ind_struct    *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct   *deact_req;
+    ilm_struct                          ilm;
+    kal_uint8                           test_stage;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* Activate DPFM */
+    ipc_ut_dpfm_is_activated_g = KAL_TRUE;
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Simulate UL traffic to IPCore : Before Netif attach, all Metas should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32 total_cnt;
+            kal_uint32 ipv4_cnt;
+            kal_uint32 ipv6_cnt;
+            kal_uint32 dpfm_device;
+            kal_uint32 netif_id;
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+            kal_uint8 non_ignore_cnt;
+            kal_uint8 allmatch;
+
+            test_stage = IPC_UT_STAGE_BEFORE_BINDING;
+            for (allmatch = 0; allmatch < 2; allmatch++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 8; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 8; ipv6_cnt++)
+            for (dpfm_device = 0; dpfm_device <= 1; dpfm_device++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                /* It should not generate DPFM related meta result which is comes from LAN NETIF without rounting fearue */
+                if (1 == dpfm_device && (ipv4_cnt >= 4 || ipv6_cnt >= 4)) continue;
+
+                utDLOG("@ [Before Bind] allmatch(%d), proto_idx(%d), v4_cnt(%d), v6_cnt(%d), dpfm_device(%d)\r\n", allmatch, idx, ipv4_cnt, ipv6_cnt, dpfm_device);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                netif_id = (dpfm_device == 0) ? IPC_UT_DPFM_NETID_START
+                                             : IPC_UT_DPFM_NETID_START + 1;
+
+                ipc_ut_prepare_ul_meta_list_dpfm(allmatch, ipv4_cnt, ipv6_cnt, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                non_ignore_cnt = 0;
+                /*
+                 * if pkt_cnt is 8, then the last meta will be DPFM_ADD_CMD.
+                 * And this command should be forwarded to UPCM.
+                 */
+                if(ipv4_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+                if(ipv6_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_dl_callback_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (non_ignore_cnt != ipc_ut_ul_meta_non_igr_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_cnt) ) {
+                    utELOG("Packet is forwarded before PDN binding! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+
+            }
+        }
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_UT_LHIF_NETID_START;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() (DPFM device) */
+    net2 = &(ipc_ut_nets_s[1]);
+    kal_mem_set(net2, 0, sizeof(ipc_ut_netif_t));
+    net2->conf.module_id = MOD_IPCORE;
+    net2->conf.netif_id = IPC_UT_DPFM_NETID_START;
+    net2->conf.ul_reload_context = net2;
+    net2->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net2->conf.callback_context = net2;
+    net2->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net2->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did_dpfm;
+    net2->conf.features = IPC_F_LAN | IPC_F_TETHERING_ROUTE;
+    result = ipc_attach(&net2->conf, &net2->handle);
+    if (!result) {
+        utELOG("ipc_attach() (DPFM device) returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() (DPFM device 2) */
+    net3 = &(ipc_ut_nets_s[2]);
+    kal_mem_set(net3, 0, sizeof(ipc_ut_netif_t));
+    net3->conf.module_id = MOD_IPCORE;
+    net3->conf.netif_id = IPC_UT_DPFM_NETID_START + 1;
+    net3->conf.ul_reload_context = net3;
+    net3->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net3->conf.callback_context = net3;
+    net3->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net3->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did_dpfm;
+    net3->conf.features = IPC_F_LAN;
+    result = ipc_attach(&net3->conf, &net3->handle);
+    if (!result) {
+        utELOG("ipc_attach() (DPFM device 2) returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        
+        /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM + idx, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+        free_local_para((local_para_struct *)bind_req);
+
+        /* Bind LAN netifs. */
+        ipc_bind_lan_netif(net2->conf.netif_id, net3->conf.netif_id);
+
+        /* Simulate UL traffic to IPCore : All GPDs should be forward to UL callback regardless of IP types (IPv4/IPv6) */
+        {
+            kal_uint32 total_cnt;
+            kal_uint32 dpfm_pkt_cnt;
+            kal_uint32 lan_pkt_cnt;
+            kal_uint32 lan_did_cnt;
+            kal_uint32 ipv4_cnt;
+            kal_uint32 ipv6_cnt;
+            kal_uint32 dpfm_device;
+            kal_uint32 netif_id;
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+            kal_uint8 dpfm_cmd_cnt;
+            kal_uint8 dpfm_cmd_cnt_v4;
+            kal_uint8 dpfm_cmd_cnt_v6;
+            kal_uint8 non_ignore_cnt;
+            kal_uint8 allmatch;
+
+            test_stage = IPC_UT_STAGE_BINDING;
+            for (allmatch = 0; allmatch < 2; allmatch++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 8; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 8; ipv6_cnt++)
+            for (dpfm_device = 0; dpfm_device <= 1; dpfm_device++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                /* It should not generate DPFM related meta result which is comes from AP LAN NETIF(dpfm_device==1) without rounting fearue */
+                if (1 == dpfm_device && (ipv4_cnt >= 4 || ipv6_cnt >= 4)) continue;
+
+                utDLOG("@ [Binded] allmatch(%d), proto_idx(%d), v4_cnt(%d), v6_cnt(%d), dpfm_device(%d)\r\n", allmatch, idx, ipv4_cnt, ipv6_cnt, dpfm_device);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                netif_id = (dpfm_device == 0) ? IPC_UT_DPFM_NETID_START
+                                             : IPC_UT_DPFM_NETID_START + 1;
+
+                dpfm_cmd_cnt = 0;
+                dpfm_cmd_cnt_v4 = 0;
+                dpfm_cmd_cnt_v6 = 0;
+                if (ipv4_cnt > 5) {
+                    dpfm_cmd_cnt_v4 += (ipv4_cnt-5);
+                }
+                if (ipv6_cnt > 5) {
+                    dpfm_cmd_cnt_v6 += (ipv6_cnt-5);
+                }
+                dpfm_cmd_cnt = dpfm_cmd_cnt_v4 + dpfm_cmd_cnt_v6;
+
+                dpfm_pkt_cnt = 0;
+                if ((dpfm_device == 0) && (total_cnt > 0)) {
+                    if ( allmatch == 1 ) {
+                        if (ipv4_cnt > 4) {
+                            dpfm_pkt_cnt += (ipv4_cnt - dpfm_cmd_cnt_v4 -1); /* minus 1 for DPFM_MATCH_BUT_NO_NAT MR */
+                        } else {
+                            dpfm_pkt_cnt += ipv4_cnt;
+                        }
+                        if (ipv6_cnt > 4) {
+                            dpfm_pkt_cnt += (ipv6_cnt - dpfm_cmd_cnt_v6 -1); /* minus 1 for DPFM_MATCH_BUT_NO_NAT MR */
+                        } else {
+                            dpfm_pkt_cnt += ipv6_cnt;
+                        }
+                    } else if (allmatch == 0 ) {
+                        if (ipv4_cnt >= 4) {
+                            dpfm_pkt_cnt += 1; /*For DPFM_MATCH MR */
+                        }
+                        if (ipv6_cnt >= 4) {
+                            dpfm_pkt_cnt += 1; /*For DPFM_MATCH MR */
+                        }
+                    }
+                }
+
+                non_ignore_cnt = 0;
+                /*
+                 * if pkt_cnt is 8, then the last meta will be DPFM_ADD_CMD.
+                 * And this command should be forwarded to UPCM.
+                 */
+                if(ipv4_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+                if(ipv6_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+
+                lan_pkt_cnt = total_cnt - dpfm_pkt_cnt - dpfm_cmd_cnt;
+                lan_did_cnt = (lan_pkt_cnt == 0) ? 0 : 1;
+
+                ipc_ut_prepare_ul_meta_list_dpfm(allmatch, ipv4_cnt, ipv6_cnt, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_dl_callback_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     ((dpfm_pkt_cnt + non_ignore_cnt) != ipc_ut_ul_meta_non_igr_cnt) ||
+                     (lan_pkt_cnt != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ||
+                     (lan_did_cnt != ipc_ut_dl_callback_did_dpfm_cnt) ) {
+                    utELOG("Packet is not forwarded correctly! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+                if (ipc_ut_ul_meta_non_igr_cnt) {
+                    if (dpfm_pkt_cnt != 0 && IPC_UT_PDN_ID != ipc_ut_ul_pdn_id) {
+                        utELOG("UL META is forwarded with wrong PDN ID! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                        ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                        return KAL_FALSE;
+                    }
+                    if (dpfm_pkt_cnt != 0 && idx != ipc_ut_ul_proto_idx) {
+                        utELOG("UL META is forwarded with wrong Protocol ID! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                        ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                        return KAL_FALSE;
+                    }
+                }
+            }
+        }
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* Unbind LAN netifs. */
+        ipc_unbind_lan_netif(net2->conf.netif_id, net3->conf.netif_id);
+
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Simulate UL traffic to IPCore : After Netif Dettach, all Metas should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32 total_cnt;
+            kal_uint32 ipv4_cnt;
+            kal_uint32 ipv6_cnt;
+            kal_uint32 dpfm_device;
+            kal_uint32 netif_id;
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+            kal_uint8 non_ignore_cnt;
+            kal_uint8 allmatch;
+
+            test_stage = IPC_UT_STAGE_UNBINDING;
+            for (allmatch = 0; allmatch < 2; allmatch++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 8; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 8; ipv6_cnt++)
+            for (dpfm_device = 0; dpfm_device <= 1; dpfm_device++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+                /* It should not generate DPFM related meta result which is comes from LAN NETIF without rounting fearue */
+                if (1 == dpfm_device && (ipv4_cnt >= 4 || ipv6_cnt >= 4)) continue;
+
+                utDLOG("@ [After Unbind] allmatch(%d), proto_idx(%d), v4_cnt(%d), v6_cnt(%d), dpfm_device(%d)\r\n", allmatch, idx, ipv4_cnt, ipv6_cnt, dpfm_device);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                netif_id = (dpfm_device == 0) ? IPC_UT_DPFM_NETID_START
+                                             : IPC_UT_DPFM_NETID_START + 1;
+
+                ipc_ut_prepare_ul_meta_list_dpfm(allmatch, ipv4_cnt, ipv6_cnt, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                non_ignore_cnt = 0;
+                /*
+                 * if pkt_cnt is 8, then the last meta will be DPFM_ADD_CMD.
+                 * And this command should be forwarded to UPCM.
+                 */
+                if(ipv4_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+                if(ipv6_cnt == 8)
+                {
+                    non_ignore_cnt++;
+                }
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+                ipc_ut_reset_dl_callback_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_pkt_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_dpfm_cnt) ) {
+                    utELOG("Packet is forwarded after PDN Unbinding! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+
+            }
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+#endif
+
+kal_bool ipc_ut_meta_downlink(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    ipc_ut_netif_t   *net;
+    kal_uint32        netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool          result;
+    ilm_struct        ilm;
+    kal_uint32        ipv4_cnt;
+    kal_uint32        ipv6_cnt;
+    kal_uint32        ipv4_filter_cnt;
+    kal_uint32        ipv6_filter_cnt;
+    kal_uint8         matched_filter_idx_v4;
+    kal_uint8         matched_filter_idx_v6;
+    kal_uint32        callback_with_info;
+    kal_uint32        total_cnt;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * ipc_attach()
+     */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+    for (ipv4_filter_cnt = 0; ipv4_filter_cnt <= 4; ipv4_filter_cnt++)
+    for (ipv6_filter_cnt = 0; ipv6_filter_cnt <= 4; ipv6_filter_cnt++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < ipv4_filter_cnt; matched_filter_idx_v4++)
+    for (matched_filter_idx_v6 = 0; matched_filter_idx_v6 < ipv6_filter_cnt; matched_filter_idx_v6++) {
+        if ((0 == ipv4_cnt) && (0 == ipv6_cnt)) continue;
+
+        utDLOG("ifo(%d) v4Cnt(%d) v6Cnt(%d) v4FltCnt(%d) v6FltCnt(%d) v4Idx(%d) v6Idx(%d)\r\n",
+               callback_with_info, ipv4_cnt, ipv6_cnt, ipv4_filter_cnt , ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6);
+
+        total_cnt = ipv4_cnt + ipv6_cnt;
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Install DL filter for each test loop */
+        ipc_ut_install_dl_filters(callback_with_info, KAL_TRUE, ipv4_filter_cnt, ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6, IPC_UT_LHIF_NETID_START);
+
+        ipc_ut_dl_ipf_match_filter_id_v4_s = matched_filter_idx_v4;
+        ipc_ut_dl_ipf_match_filter_id_v6_s = ipv4_filter_cnt + matched_filter_idx_v6;
+
+        /* Before PDN Binding */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            /* Before PDN Binding, IPF will only report PN not mtach case or NETIF invalid case */
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_pkt_cnt;
+
+                utDLOG("@ Before activation : match_result(%d)\r\n", match_result);
+
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_pkt_cnt = total_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) || (match_result == IPC_IPF_MR_PN_NO_MATCH)) {
+                    expected_pkt_cnt = 0;
+                }
+
+                /* Make sure no DL callback to HIF */
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Check if IPCore will release buffer when NETIF is invalid */
+                /* PN_NO_MATCH & DIRECT_TO_AP no need to free buffer */
+                if ( expected_pkt_cnt != ipc_ut_dl_meta_buf_free_num_s ) {
+                    utELOG("DL buffer is not released before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         *   Simulate DL traffic from IPCore : All meta should be forward to either DL callback or filter callback(IPv4/IPv6)
+         */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            /* Before PDN Binding, IPF will only report PN not mtach case or NETIF invalid case */
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_dl_v4_filter_out_cnt;
+                kal_uint32 expected_dl_v6_filter_out_cnt;
+                kal_uint32 expected_dl_filter_out_cnt;
+                kal_uint32 did_cnt;
+                kal_uint32 expected_dl_forwad_cnt;
+
+                utDLOG("@ PDN connected : match_result(%d)\r\n", match_result);
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_dl_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                  (ipv4_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))? 1:0;
+                expected_dl_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                  (ipv6_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))?1:0;
+
+                expected_dl_filter_out_cnt = expected_dl_v4_filter_out_cnt + expected_dl_v6_filter_out_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) ||
+                    (match_result == IPC_IPF_MR_PN_NO_MATCH) ||
+                    (match_result == IPC_IPF_MR_NET_INVALID)) {
+                    did_cnt = expected_dl_forwad_cnt = 0;
+                }
+                else {
+                    did_cnt = total_cnt-expected_dl_filter_out_cnt; //Supposed one DID only contains one packet
+                    expected_dl_forwad_cnt = total_cnt-expected_dl_filter_out_cnt;
+                }
+
+                if (expected_dl_filter_out_cnt > 0) {
+                    if (callback_with_info) {
+                        if (ipc_ut_dl_filter_info.netif_id != IPC_UT_LHIF_NETID_START) {
+                            utELOG("Filtered-out netif ID is incorrect!\r\n");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                        if (ipc_ut_dl_filter_info.ebi != -1) {
+                            utELOG("Filtered-out EBI is incorrect!\r\r");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                    }
+                    else {
+                        if (ipc_ut_dl_filter_info.netif_id != 0) {
+                            utELOG("Filtered-out netif ID is incorrect!\r\n");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                        if (ipc_ut_dl_filter_info.ip_id != -1) {
+                            utELOG("Filtered-out IP ID is incorrect!\r\r");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                    }
+                }
+
+
+                if (ipc_ut_dl_filter_gpd_cnt != expected_dl_filter_out_cnt) {
+                    utELOG("Filtered-out gpd count is incorrect!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                    return KAL_FALSE;
+                }
+
+                if ( (did_cnt != ipc_ut_dl_callback_did_cnt) ||
+                     (expected_dl_forwad_cnt != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is NOT forwarded to bound handler!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+
+        /*
+         *   Simulate DL traffic to IPCore : After PDN deactivation, all meta should be silently dropped by IPCore and NO callback is triggered
+         */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_pkt_cnt;
+
+                utDLOG("@ PDN deactivated : dhcpv4Idx(%d), dhcpv6Idx(%d), match_result(%d)\r\n",
+                                0, 0, match_result);
+
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_pkt_cnt = total_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) || (match_result == IPC_IPF_MR_PN_NO_MATCH)) {
+                    expected_pkt_cnt = 0;
+                }
+
+                /* Make sure no DL callback to HIF */
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded when PDN deactivated!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Check if IPCore will release buffer when NETIF is invalid */
+                /* PN_NO_MATCH & DIRECT_TO_AP no need to free buffer */
+                if ( expected_pkt_cnt != ipc_ut_dl_meta_buf_free_num_s ) {
+                    utELOG("DL buffer is not released when PDN deactivated!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+    }
+
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+void ipc_ut_prepare_ul_empty_ack_meta_list(kal_bool allValidIpPkt,
+                                           kal_uint32 ipv4_cnt,
+                                           kal_uint8 ipv4_case_num,
+                                           kal_uint32 ipv6_cnt,
+                                           kal_uint8 ipv6_case_num,
+                                           kal_uint8 ip_type,
+                                           kal_uint32 *p_head_idx,
+                                           kal_uint32 *p_tail_idx,
+                                           LHIF_QUEUE_TYPE *q_type,
+                                           kal_uint32 netif_id,
+                                           kal_uint8 proto_idx,
+                                           kal_uint8 test_stage) {
+    kal_uint32 total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32 idx = 0;
+    kal_uint32 curr_meta_idx = 0;
+    lhif_meta_tbl_t *curr_meta = NULL;
+    kal_uint8 *packet_buf = NULL;
+    kal_uint32 packet_len = 0;
+    kal_uint32 netif_id_prefix = (netif_id & 0xFFFFFF00);
+    kal_bool is_ea = KAL_FALSE;
+    kal_bool is_new_matched = KAL_FALSE;
+    kal_uint32 seq_base = 0;
+    kal_uint32 ack_base = 0;
+    kal_bool chk_mr_v4[IPC_UT_EA_MAX_CASE_NUM] = {KAL_FALSE};
+    kal_bool chk_mr_v6[IPC_UT_EA_MAX_CASE_NUM] = {KAL_FALSE};
+    kal_bool chk_mr_matched_v4[IPC_UT_EA_MAX_CASE_NUM] = {KAL_FALSE};
+    kal_bool chk_mr_matched_v6[IPC_UT_EA_MAX_CASE_NUM] = {KAL_FALSE};
+
+    UT_ASSERT(total_cnt == ipc_ut_alloc_meta(IPC_UT_LHIF_META_AP0, total_cnt, p_head_idx, p_tail_idx));
+    UT_ASSERT((ipv4_case_num >= 1) && (ipv4_case_num <= IPC_UT_EA_MAX_CASE_NUM));
+    UT_ASSERT((ipv6_case_num >= 1) && (ipv6_case_num <= IPC_UT_EA_MAX_CASE_NUM));
+
+    *q_type = LHIF_HWQ_AP_UL_Q0;
+    curr_meta_idx = *p_head_idx;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        curr_meta = &ipc_ut_meta_tbl_s[curr_meta_idx];
+        curr_meta->net_type = ((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS;
+        curr_meta->channel_id = netif_id & 0x0000001F;
+        is_ea = KAL_FALSE;
+        is_new_matched = KAL_FALSE;
+
+        seq_base = IPC_HDR_TCP_GET_SEQ_NUM(ipc_ut_ipv4_tcp_empty_ack_packet + IPC_HDR_V4_HEADER_SIZE);
+        ack_base = IPC_HDR_TCP_GET_ACK_NUM(ipc_ut_ipv4_tcp_empty_ack_packet + IPC_HDR_V4_HEADER_SIZE);
+        packet_buf = ipc_ut_ipv4_tcp_empty_ack_packet;
+
+        is_ea = KAL_TRUE;
+        g_ipc_ut_ea_cnt++;
+        packet_len = sizeof(ipc_ut_ipv4_tcp_empty_ack_packet);
+        kal_mem_cpy(curr_meta->vrb_addr, packet_buf, packet_len);
+        curr_meta->length = packet_len;
+        curr_meta->ignore = KAL_FALSE;
+
+        if (1 < ipv4_case_num) {
+            switch (idx % ipv4_case_num) {
+                case 0:
+                    curr_meta->match_index = IPC_UT_META_MATCH_IDX;
+                    break;
+                case 1:
+                    curr_meta->vrb_addr[15] += ipv4_case_num;
+                    curr_meta->match_index = IPC_UT_META_MATCH_IDX + 1;
+                    break;
+                case 2:
+                    curr_meta->vrb_addr[15] += ipv4_case_num + 2;
+                    curr_meta->match_index = IPC_UT_META_MATCH_IDX + 1;
+                    break;
+                default:
+                    /* invalid case */
+                    UT_ASSERT(KAL_FALSE);
+                    break;
+            }
+        } else {
+            curr_meta->match_index = IPC_UT_META_MATCH_IDX + 6;
+        }
+
+        if (KAL_FALSE == chk_mr_v4[(idx % ipv4_case_num)]) {
+            chk_mr_v4[(idx % ipv4_case_num)] = KAL_TRUE;
+            is_new_matched = KAL_TRUE;
+        } else {
+            if (KAL_FALSE == chk_mr_matched_v4[(idx % ipv4_case_num)]) {
+                chk_mr_matched_v4[(idx % ipv4_case_num)] = KAL_TRUE;
+            } else {
+                if (IPV6_ADDR_TYPE != ip_type) {
+                    g_ipc_ut_ea_drop_cnt++;
+                }
+            }
+        }
+
+        if (is_ea) {
+            curr_meta->ea = KAL_TRUE;
+            IPC_HDR_TCP_SET_SEQ_NUM(curr_meta->vrb_addr + 20, seq_base + idx);
+            IPC_HDR_TCP_SET_ACK_NUM(curr_meta->vrb_addr + 20, ack_base + idx);
+        }
+
+#if defined(__IPF_SUPPORT__)
+        if (!((IPC_UT_STAGE_BEFORE_BINDING == test_stage) || (IPC_UT_STAGE_UNBINDING == test_stage))) {
+            curr_meta->protocol_idx = proto_idx;
+            curr_meta->pdn = IPC_UT_PDN_ID;
+        }
+
+        curr_meta->ip = KAL_FALSE;
+
+        if (is_new_matched) {
+            curr_meta->mr = IPC_HPC_MR_NEW;
+        } else {
+            curr_meta->mr = IPC_HPC_MR_MATCH;
+        }
+#endif
+        curr_meta_idx++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        curr_meta = &ipc_ut_meta_tbl_s[curr_meta_idx];
+        curr_meta->net_type = ((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS;
+        curr_meta->channel_id = netif_id & 0x0000001F;
+        is_ea = KAL_FALSE;
+        is_new_matched = KAL_FALSE;
+
+        seq_base = IPC_HDR_TCP_GET_SEQ_NUM(ipc_ut_ipv6_tcp_empty_ack_packet + IPC_HDR_V6_HEADER_SIZE);
+        ack_base = IPC_HDR_TCP_GET_ACK_NUM(ipc_ut_ipv6_tcp_empty_ack_packet + IPC_HDR_V6_HEADER_SIZE);
+        packet_buf = ipc_ut_ipv6_tcp_empty_ack_packet;
+
+        is_ea = KAL_TRUE;
+        g_ipc_ut_ea_cnt++;
+        packet_len = sizeof(ipc_ut_ipv6_tcp_empty_ack_packet);
+        kal_mem_cpy(curr_meta->vrb_addr, packet_buf, packet_len);
+        curr_meta->length = packet_len;
+        curr_meta->ignore = KAL_FALSE;
+        curr_meta->ip = KAL_TRUE;
+
+        if (1 < ipv6_case_num) {
+            switch (idx % ipv6_case_num) {
+                case 0:
+                    curr_meta->match_index = IPC_UT_META_MATCH_IDX + 3;
+                    break;
+                case 1:
+                    curr_meta->vrb_addr[15] += ipv6_case_num;
+                    curr_meta->match_index = IPC_UT_META_MATCH_IDX + 4;
+                    break;
+                case 2:
+                    curr_meta->vrb_addr[15] += ipv6_case_num + 3;
+                    curr_meta->match_index = IPC_UT_META_MATCH_IDX + 5;
+                    break;
+                default:
+                    /* invalid case */
+                    UT_ASSERT(KAL_FALSE);
+                    break;
+            }
+        } else {
+            curr_meta->match_index = IPC_UT_META_MATCH_IDX + 7;
+        }
+
+        if (KAL_FALSE == chk_mr_v6[(idx % ipv6_case_num)]) {
+            chk_mr_v6[(idx % ipv6_case_num)] = KAL_TRUE;
+            is_new_matched = KAL_TRUE;
+        } else {
+            if (KAL_FALSE == chk_mr_matched_v6[(idx % ipv6_case_num)]) {
+                chk_mr_matched_v6[(idx % ipv6_case_num)] = KAL_TRUE;
+            } else {
+                if (IPV4_ADDR_TYPE != ip_type) {
+                    g_ipc_ut_ea_drop_cnt++;
+                }
+            }
+        }
+
+        if (is_ea) {
+            curr_meta->ea = KAL_TRUE;
+            IPC_HDR_TCP_SET_SEQ_NUM(curr_meta->vrb_addr + 20, seq_base + idx);
+            IPC_HDR_TCP_SET_ACK_NUM(curr_meta->vrb_addr + 20, ack_base + idx);
+        }
+
+        if (!((IPC_UT_STAGE_BEFORE_BINDING == test_stage) || (IPC_UT_STAGE_UNBINDING == test_stage))) {
+            curr_meta->protocol_idx = proto_idx;
+            curr_meta->pdn = IPC_UT_PDN_ID;
+        }
+
+        if (is_new_matched) {
+            curr_meta->mr = IPC_HPC_MR_NEW;
+        } else {
+            curr_meta->mr = IPC_HPC_MR_MATCH;
+        }
+
+        curr_meta_idx++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+    UT_ASSERT(g_ipc_ut_ea_cnt == ipv4_case_num + ipv6_case_num + g_ipc_ut_ea_drop_cnt);
+    return;
+}
+
+kal_bool ipc_ut_uplink_ack_reduction(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32                          idx = 0;
+    ipc_ut_netif_t                      *net = NULL;
+    kal_uint32                          netif_id = IPC_UT_LHIF_NETID_START;
+    ipcore_upcm_pdn_bind_ind_struct     *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct   *deact_req = NULL;
+    kal_uint8                           ip_types[] = {IPV4_ADDR_TYPE, IPV4V6_ADDR_TYPE, IPV6_ADDR_TYPE};
+    kal_uint32                          total_cnt = 0;
+    kal_uint32                          ipv4_cnt = 0;
+    kal_uint32                          ipv6_cnt = 0;
+    kal_uint32                          ipv4_case_num = 0;
+    kal_uint32                          ipv6_case_num = 0;
+    kal_uint32                          with_wildcard = 0;
+    kal_uint32                          with_bwm = 0;
+    kal_uint8                           matched_filter_idx_v4 = 0;
+    kal_uint8                           matched_filter_idx_v6 = 0;
+    kal_uint8                           test_stage;
+    kal_uint32                          expected_ul_v4_filter_out_cnt = 0;
+    kal_uint32                          expected_ul_v6_filter_out_cnt = 0;
+    kal_uint32                          expected_ul_filter_out_cnt = 0;
+
+    /* Init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    UT_ASSERT(KAL_TRUE == ipc_reset());
+
+    for (ipv4_cnt = 0; ipv4_cnt <= 4; ipv4_cnt+=2)
+    for (ipv6_cnt = 0; ipv6_cnt <= 4; ipv6_cnt+=2)
+    for (ipv4_case_num = 1; ipv4_case_num <= IPC_UT_EA_MAX_CASE_NUM; ipv4_case_num++)
+    for (ipv6_case_num = 1; ipv6_case_num <= IPC_UT_EA_MAX_CASE_NUM; ipv6_case_num++)
+    for (idx = 0; idx < sizeof(ip_types)/sizeof(ip_types[0]); idx++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+            continue;
+        }
+
+        utDLOG("v4Cnt(%d) v6Cnt(%d) IPType(%d)",ipv4_cnt, ipv6_cnt, idx);
+        utDLOG("ipv4_case_num(%d) ipv6_case_num(%d)",ipv4_case_num, ipv6_case_num);
+
+        total_cnt = ipv4_cnt + ipv6_cnt;
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* ipc_attach() */
+        net = &(ipc_ut_nets_s[0]);
+        kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+        net->conf.module_id = MOD_IPCORE;
+        net->conf.netif_id = netif_id;
+        net->conf.callback_context = net;
+        net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+        net->conf.features = 0;
+        UT_ASSERT(KAL_TRUE == ipc_attach(&net->conf, &net->handle));
+
+        /*
+         * Before activate, the UL packet from this network interface
+         *   1. CAN be filtered out
+         *   2. CAN NOT be forwarded to UPCM
+         */
+        {
+            kal_uint32          head_idx = 0;
+            kal_uint32          tail_idx = 0;
+            LHIF_QUEUE_TYPE     q_type = LHIF_HWQ_AP_UL_Q0;
+
+            test_stage = IPC_UT_STAGE_BEFORE_BINDING;
+            expected_ul_v4_filter_out_cnt = 0;
+            expected_ul_v6_filter_out_cnt = 0;
+            expected_ul_filter_out_cnt = 0;
+            g_ipc_ut_ea_cnt = 0;
+            g_ipc_ut_ea_drop_cnt = 0;
+
+            ipc_ut_prepare_ul_empty_ack_meta_list(KAL_TRUE, ipv4_cnt, ipv4_case_num, ipv6_cnt, ipv6_case_num, ip_types[idx], &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+            /* Send IOR into IPCore */
+            ipc_ut_reset_ul_info();
+            ipc_ut_reset_ul_filter_info();
+
+            UT_ASSERT(ipc_meta_uplink(head_idx, tail_idx, q_type));
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            UT_ASSERT(0 == expected_ul_filter_out_cnt);
+            UT_ASSERT(ipc_ut_ul_filter_gpd_cnt == expected_ul_filter_out_cnt);
+            UT_ASSERT(total_cnt == (ipc_ut_ul_meta_cnt + ipc_ut_ul_meta_non_igr_cnt));
+        }
+
+        /* Activate IPv4/IPv4v6/IPv6 PDN */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = ip_types[idx];
+        ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+        free_local_para((local_para_struct *)bind_req);
+
+        /*
+         * After PDN binding activate, the UL packet from this network interface
+         *   1. CAN be filtered out
+         *   2. CAN be forwarded to UPCM
+         */
+        {
+            kal_uint32          head_idx = 0;
+            kal_uint32          tail_idx = 0;
+            LHIF_QUEUE_TYPE     q_type = LHIF_HWQ_AP_UL_Q0;
+
+            test_stage = IPC_UT_STAGE_BINDING;
+            expected_ul_v4_filter_out_cnt = 0;
+            expected_ul_v6_filter_out_cnt = 0;
+            expected_ul_filter_out_cnt = 0;
+            g_ipc_ut_ea_cnt = 0;
+            g_ipc_ut_ea_drop_cnt = 0;
+
+            utDLOG("@ PDN connected : total_cnt(%u), ipv4(%d) ipv6(%d)\r\n", total_cnt, ipv4_cnt, ipv6_cnt);
+
+            ipc_ut_prepare_ul_empty_ack_meta_list(KAL_TRUE, ipv4_cnt, ipv4_case_num, ipv6_cnt, ipv6_case_num, ip_types[idx], &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+            /* Send IOR into IPCore */
+            ipc_ut_reset_ul_info();
+            ipc_ut_reset_ul_filter_info();
+
+            UT_ASSERT(ipc_meta_uplink(head_idx, tail_idx, q_type));
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            UT_ASSERT(0 == expected_ul_filter_out_cnt);
+            UT_ASSERT(ipc_ut_ul_filter_gpd_cnt == expected_ul_filter_out_cnt);
+            UT_ASSERT(total_cnt == ipc_ut_ul_meta_cnt);
+
+            if (IPV4_ADDR_TYPE == ip_types[idx]) {
+                if (2 >= ipv4_cnt) {
+                    g_ipc_ut_ea_drop_cnt = ipv6_cnt;
+                } else {
+                    g_ipc_ut_ea_drop_cnt += ipv6_cnt;
+                }
+            }
+
+            if (IPV6_ADDR_TYPE == ip_types[idx]) {
+                if (2 >= ipv6_cnt) {
+                    g_ipc_ut_ea_drop_cnt = ipv4_cnt;
+                } else {
+                    g_ipc_ut_ea_drop_cnt += ipv4_cnt;
+                }
+            }
+
+            UT_ASSERT(g_ipc_ut_received_ignore_ea_cnt == g_ipc_ut_ea_drop_cnt);
+            UT_ASSERT(ipc_ut_ul_meta_cnt == (ipc_ut_ul_meta_non_igr_cnt + g_ipc_ut_igr_meta_cnt));
+        }
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+        ipc_on_pdn_unbind((local_para_struct *)deact_req);
+        free_local_para((local_para_struct *)deact_req);
+
+        /*
+         * After deactivate, the UL packet from this network interface
+         *   1. CAN be filtered out
+         *   2. CAN NOT be forwarded to UPCM
+         */
+        {
+            kal_uint32          head_idx = 0;
+            kal_uint32          tail_idx = 0;
+            LHIF_QUEUE_TYPE     q_type = LHIF_HWQ_AP_UL_Q0;
+
+            test_stage = IPC_UT_STAGE_UNBINDING;
+            expected_ul_v4_filter_out_cnt = 0;
+            expected_ul_v6_filter_out_cnt = 0;
+            expected_ul_filter_out_cnt = 0;
+
+            ipc_ut_prepare_ul_empty_ack_meta_list(KAL_TRUE, ipv4_cnt, 1, ipv6_cnt, 1, ip_types[idx], &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+            /* Send IOR into IPCore */
+            ipc_ut_reset_ul_info();
+            ipc_ut_reset_ul_filter_info();
+
+            UT_ASSERT(ipc_meta_uplink(head_idx, tail_idx, q_type));
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            UT_ASSERT(0 == expected_ul_filter_out_cnt);
+            UT_ASSERT(ipc_ut_ul_filter_gpd_cnt == expected_ul_filter_out_cnt);
+            UT_ASSERT(total_cnt == (ipc_ut_ul_meta_cnt + ipc_ut_ul_meta_non_igr_cnt));
+        }
+
+        /* ipc_detach(). */
+        UT_ASSERT(KAL_TRUE == ipc_detach(net->handle));
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_int32 ipc_ut_ipf_query_filter_id_by_index(kal_uint32 ipf_index) {
+    kal_int32 filter_id = -1;
+
+    if (0 == ipf_index) {
+        filter_id = ipc_ut_dl_ipf_match_filter_id_v4_s;
+    }
+    else {
+        filter_id = ipc_ut_dl_ipf_match_filter_id_v6_s;
+    }
+    return filter_id;
+}
+
+void ipc_ut_query_ipf_meta_info(void** base, kal_uint16* entry_num, kal_uint32 ipf_meta_q_type) {
+    *base = (void *)ipc_ut_dl_meta_tbl_s;
+    *entry_num = IPC_UT_META_TABLE_SIZE;
+
+    return;
+}
+
+void ipc_ut_ipf_pn_match_setting(kal_uint8 pdn_sim_id, kal_uint16 nc_id, kal_uint8 ipv4, kal_uint8 ipv6) {
+    return;
+}
+
+kal_bool ipc_ut_ipf_take_filter_tlb(void** buff_base, kal_uint32* max_entry_num) {
+    *buff_base = ipc_ut_hw_filter_buf_s;
+    *max_entry_num = IPC_UT_HW_FLTR_TOTAL_NUM;
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ipf_submit_filter_tlb(kal_uint32 filter_num, kal_uint32 v6_unknow_pro_ck) {
+    return KAL_TRUE;
+}
+
+void ipc_ut_free_ipf_meta_buf(void* meta, kal_uint32 len) {
+    ipc_ut_dl_meta_buf_free_num_s++;
+    return;
+}
+
+kal_bool ipc_ut_ul_throttle_plmn(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    ipc_ut_netif_t *net = NULL;
+    kal_uint32 netif_id = IPC_UT_LHIF_NETID_START;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    ilm_struct ilm = {0};
+    kal_bool result = KAL_FALSE;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = net->conf.netif_id;
+    bind_req->pdn_id = IPC_UT_PDN_ID;
+    bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+    ilm.src_mod_id = MOD_UPCM;
+    ilm.dest_mod_id = MOD_IPCORE;
+    ilm.sap_id = IPCORE_SAP;
+    ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+    ilm.local_para_ptr = (local_para_struct *)bind_req;
+    ilm.peer_buff_ptr = NULL;
+    ipc_on_ilm(&ilm);
+    free_local_para((local_para_struct *)bind_req);
+
+    /* Case 1 PLMN LIST is on-going, UL should be blocked; PLMN LIST is no action, UL should be resumed.*/
+    {
+        kal_uint32 total_cnt;
+        kal_uint32 ipv4_cnt;
+        kal_uint32 ipv6_cnt;
+        kal_uint32 head_idx;
+        kal_uint32 tail_idx;
+        LHIF_QUEUE_TYPE q_type;
+        l4c_ipcore_ul_throttle_req_struct *p_ind;
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Prepare UL meta */
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+            utDLOG("@ v4_cnt(%d),v6_cnt(%d)\r\n", ipv4_cnt, ipv6_cnt);
+
+            /* Set PLMN LIST on-going */
+            p_ind = construct_local_para(sizeof(l4c_ipcore_ul_throttle_req_struct), TD_RESET);
+            p_ind->ul_throttle_action = UL_THROTTLE_ONGOING;
+            ilm.src_mod_id = MOD_L4C;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = L4C_IPCORE_SAP;
+            ilm.msg_id = MSG_ID_L4C_IPCORE_UL_THROTTLE_REQ;
+            ilm.local_para_ptr = (local_para_struct *)p_ind;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)p_ind);
+
+            total_cnt = ipv4_cnt + ipv6_cnt;
+
+            ipc_ut_prepare_ul_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, 0, IPC_UT_STAGE_BINDING);
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            ipc_meta_uplink(head_idx, tail_idx, q_type);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if ( (0 != ipc_ut_ul_meta_cnt) ||
+                 (0 != ipc_ut_ul_meta_non_igr_cnt) ) {
+                utELOG("UL META is forwarded to UPCM when PLMN LIST is on-going! (ipv4:%d, ipv6:%d)\r\n", ipv4_cnt, ipv6_cnt);
+                ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                return KAL_FALSE;
+            }
+
+            /* Set PLMN LIST no action */
+            p_ind = construct_local_para(sizeof(l4c_ipcore_ul_throttle_req_struct), TD_RESET);
+            p_ind->ul_throttle_action = UL_THROTTLE_NO_ACTION;
+            ilm.src_mod_id = MOD_L4C;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = L4C_IPCORE_SAP;
+            ilm.msg_id = MSG_ID_L4C_IPCORE_UL_THROTTLE_REQ;
+            ilm.local_para_ptr = (local_para_struct *)p_ind;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)p_ind);
+
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                 (total_cnt != ipc_ut_ul_meta_non_igr_cnt) ) {
+                utELOG("UL META is forwarded to UPCM with wrong number! (ipv4:%d, ipv6:%d, ipc_ut_ul_meta_cnt:%d, ipc_ut_ul_meta_non_igr_cnt:%d)\r\n",
+                        ipv4_cnt, ipv6_cnt, ipc_ut_ul_meta_cnt, ipc_ut_ul_meta_non_igr_cnt);
+                ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                return KAL_FALSE;
+            }
+        }
+    }
+
+    /* PDN deactivation. */
+    deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+    deact_req->pdn_id = IPC_UT_PDN_ID;
+
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ilm.src_mod_id = MOD_UPCM;
+    ilm.dest_mod_id = MOD_IPCORE;
+    ilm.sap_id = IPCORE_SAP;
+    ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+    ilm.local_para_ptr = (local_para_struct *)deact_req;
+    ilm.peer_buff_ptr = NULL;
+    ipc_on_ilm(&ilm);
+    free_local_para((local_para_struct *)deact_req);
+
+    /* Case 2 if PDN is unbind when PLMN LIST is on-going, UL meta should be dropped */
+    {
+        l4c_ipcore_ul_throttle_req_struct *p_ind;
+        kal_uint32 ipv4_cnt = 3;
+        kal_uint32 ipv6_cnt = 3;
+        kal_uint32 total_cnt = ipv4_cnt + ipv6_cnt;
+        kal_uint32 head_idx;
+        kal_uint32 tail_idx;
+        LHIF_QUEUE_TYPE q_type;
+        kal_uint32 idx;
+        kal_uint8 proto_idx[] = {0, 1};
+
+        for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+
+            utDLOG("@ [after Bind] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+            /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+            bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+            bind_req->network_interface_id = net->conf.netif_id;
+            bind_req->pdn_id = IPC_UT_PDN_ID;
+            bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+            ilm.src_mod_id = MOD_UPCM + idx;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+            ilm.local_para_ptr = (local_para_struct *)bind_req;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)bind_req);
+
+            /* Set PLMN LIST on-going */
+            p_ind = construct_local_para(sizeof(l4c_ipcore_ul_throttle_req_struct), TD_RESET);
+            p_ind->ul_throttle_action = UL_THROTTLE_ONGOING;
+            ilm.src_mod_id = MOD_L4C;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = L4C_IPCORE_SAP;
+            ilm.msg_id = MSG_ID_L4C_IPCORE_UL_THROTTLE_REQ;
+            ilm.local_para_ptr = (local_para_struct *)p_ind;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)p_ind);
+
+            ipc_ut_prepare_ul_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, idx, IPC_UT_STAGE_BINDING);
+
+            /* Send IOR into IP Core */
+            ipc_ut_reset_ul_info();
+
+            ipc_meta_uplink(head_idx, tail_idx, q_type);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            /* PDN deactivation. */
+            deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+            deact_req->pdn_id = IPC_UT_PDN_ID;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_UPCM + idx;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+            ilm.local_para_ptr = (local_para_struct *)deact_req;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)deact_req);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            /* Set PLMN LIST no action */
+            p_ind = construct_local_para(sizeof(l4c_ipcore_ul_throttle_req_struct), TD_RESET);
+            p_ind->ul_throttle_action = UL_THROTTLE_NO_ACTION;
+            ilm.src_mod_id = MOD_L4C;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = L4C_IPCORE_SAP;
+            ilm.msg_id = MSG_ID_L4C_IPCORE_UL_THROTTLE_REQ;
+            ilm.local_para_ptr = (local_para_struct *)p_ind;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)p_ind);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                 (0 != ipc_ut_ul_meta_non_igr_cnt) ) {
+                utELOG("UL META should be dropped because of PDN deactivation! (ipv4:%d, ipv6:%d, ipc_ut_ul_meta_cnt:%d, ipc_ut_ul_meta_non_igr_cnt:%d)\r\n",
+                        ipv4_cnt, ipv6_cnt, ipc_ut_ul_meta_cnt, ipc_ut_ul_meta_non_igr_cnt);
+                ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                return KAL_FALSE;
+            }
+        }
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+#if defined(__MD97__)
+
+kal_bool ipc_ut_rq_info_verification(ipc_data_rq_info_list *p_pre_list, ipc_data_rq_info_list *p_rcv_list)
+{
+    return !kal_mem_cmp(p_pre_list, p_rcv_list, sizeof(ipc_data_rq_info_list));
+}
+
+void ipc_ut_rcv_rq_info(ipc_rq_info_t *p_rq_info)
+{
+    g_ipc_ut_sdap_pkt_received_cnt++;
+    ipc_data_saved_rq_info_list(&g_rq_info_list, p_rq_info);
+}
+
+void ipc_ut_set_prepare_rq_info_list(ipc_data_rq_info_list *p_list, kal_uint8 *p_pkt, kal_uint8 qfi)
+{
+    kal_uint32 idx = p_list->cnt;
+
+    UT_ASSERT(NULL != p_list);
+    UT_ASSERT(NULL != p_pkt);
+
+    if (IPC_HDR_IS_V4(p_pkt)) {
+        p_list->rq_info_list[idx].is_ipv4 = KAL_TRUE;
+        p_list->rq_info_list[idx].protocol = IPC_HDR_V4_GET_PROTOCOL(p_pkt);
+
+        kal_mem_cpy(&p_list->rq_info_list[idx].dst_ipv4.addr32, (kal_uint8 *)IPC_HDR_V4_GET_DST_ADDR(p_pkt), 4);
+        kal_mem_cpy(&p_list->rq_info_list[idx].src_ipv4.addr32, (kal_uint8 *)IPC_HDR_V4_GET_SRC_ADDR(p_pkt), 4);
+
+        p_list->rq_info_list[idx].valid_field = IPC_RQ_INFO_3_TUPLE;
+        if (IPC_HDR_PROT_TCP == p_list->rq_info_list[idx].protocol) {
+            p_list->rq_info_list[idx].dst_port = IPC_HDR_TCP_GET_DST_PORT(p_pkt + IPC_HDR_V4_HEADER_SIZE);
+            p_list->rq_info_list[idx].src_port = IPC_HDR_TCP_GET_SRC_PORT(p_pkt + IPC_HDR_V4_HEADER_SIZE);
+            p_list->rq_info_list[idx].valid_field = IPC_RQ_INFO_5_TUPLE;
+        } else if (IPC_HDR_PROT_UDP == p_list->rq_info_list[idx].protocol) {
+            p_list->rq_info_list[idx].dst_port = IPC_HDR_UDP_GET_DST_PORT(p_pkt + IPC_HDR_V4_HEADER_SIZE);
+            p_list->rq_info_list[idx].src_port = IPC_HDR_UDP_GET_SRC_PORT(p_pkt + IPC_HDR_V4_HEADER_SIZE);
+            p_list->rq_info_list[idx].valid_field = IPC_RQ_INFO_5_TUPLE;
+        }
+    } else if (IPC_HDR_IS_V6(p_pkt)) {
+        p_list->rq_info_list[idx].is_ipv4 = KAL_FALSE;
+        p_list->rq_info_list[idx].protocol = (kal_uint8)(kal_uint8 *)IPC_HDR_V6_GET_NH_TYPE(p_pkt);
+
+        kal_mem_cpy(p_list->rq_info_list[idx].dst_ipv6.addr32, (kal_uint8 *)IPC_HDR_V6_GET_DST_ADDR(p_pkt), 16);
+        kal_mem_cpy(p_list->rq_info_list[idx].src_ipv6.addr32, (kal_uint8 *)IPC_HDR_V6_GET_SRC_ADDR(p_pkt), 16);
+
+        p_list->rq_info_list[idx].valid_field = IPC_RQ_INFO_3_TUPLE;
+        if (IPC_HDR_PROT_TCP == p_list->rq_info_list[idx].protocol) {
+            p_list->rq_info_list[idx].dst_port = IPC_HDR_TCP_GET_DST_PORT(p_pkt + IPC_HDR_V6_HEADER_SIZE);
+            p_list->rq_info_list[idx].src_port = IPC_HDR_TCP_GET_SRC_PORT(p_pkt + IPC_HDR_V6_HEADER_SIZE);
+            p_list->rq_info_list[idx].valid_field = IPC_RQ_INFO_5_TUPLE;
+        } else if (IPC_HDR_PROT_UDP == p_list->rq_info_list[idx].protocol) {
+            p_list->rq_info_list[idx].dst_port = IPC_HDR_UDP_GET_DST_PORT(p_pkt + IPC_HDR_V6_HEADER_SIZE);
+            p_list->rq_info_list[idx].src_port = IPC_HDR_UDP_GET_SRC_PORT(p_pkt + IPC_HDR_V6_HEADER_SIZE);
+            p_list->rq_info_list[idx].valid_field = IPC_RQ_INFO_5_TUPLE;
+        }
+    } else {
+        utELOG("unsupported case");
+    }
+
+    p_list->rq_info_list[idx].qfi = qfi;
+    p_list->cnt++;
+    return;
+}
+
+void ipc_ut_prepare_dl_sdap_meta_list(kal_bool allValidIpPkt,
+                                      kal_uint32 ipv4_cnt,
+                                      kal_uint32 dhcpv4_idx,
+                                      kal_uint32 ipv6_cnt,
+                                      kal_uint32 dhcpv6_idx,
+                                      kal_uint32 *p_head_idx,
+                                      kal_uint32 *p_tail_idx,
+                                      ipfc_dl_filter_queue_type *q_type,
+                                      kal_uint32 netif_id,
+                                      kal_uint8 match_result)
+{
+    kal_uint32    total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32    idx = 0;
+    kal_uint32    curr_meta_idx = 0;
+    ipf_dl_meta  *curr_meta = NULL;
+    kal_uint8    *packet_buf = NULL;
+    kal_uint32    packet_len = 0;
+    kal_uint32    netif_id_prefix = (netif_id & 0xFFFFFF00);
+    kal_bool      is_add = KAL_FALSE;
+
+    if (total_cnt != ipc_ut_alloc_meta(IPC_UT_IPF_DL_0, //LHIF_HWQ_AP_UL_Q0,
+                                       total_cnt,
+                                       p_head_idx,
+                                       p_tail_idx)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    *q_type = IPFC_META_QUEUE_DL;
+    curr_meta_idx = *p_head_idx;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        is_add = KAL_FALSE;
+        curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+        curr_meta->channel_id = ((((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS) <<8 )
+                                |(netif_id & 0x000000FF) ;
+
+        switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv4_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                is_add = KAL_TRUE;
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv4_incomplete_ip_header_packet);
+                break;
+            case 2:
+                /* repeated the same 5-tuple packet */
+                packet_buf = ipc_ut_ipv4_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                is_add = KAL_FALSE;
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv4_frag0_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag0_packet);
+                is_add = KAL_TRUE;
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv4_frag1_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag1_packet);
+                is_add = KAL_TRUE;
+                break;
+            default:
+                UT_ASSERT(KAL_FALSE);
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                break;
+        }
+
+        if (IPC_IPF_MR_UNKNOWN_HEADER == match_result && is_add) {
+            /* 11011010 */
+            curr_meta->tcp_flag = 0xDA;
+            ipc_ut_set_prepare_rq_info_list(&g_prepare_rq_info_list, packet_buf, IPC_DATA_GET_QFI(curr_meta->tcp_flag));
+            g_ipc_ut_sdap_pkt_alloc_cnt++;
+        } else {
+            curr_meta->tcp_flag = 0;
+        }
+
+        kal_mem_cpy((kal_uint8*)curr_meta->addr, packet_buf, packet_len);
+        curr_meta->len = packet_len;
+        curr_meta->ip = 0;
+
+        /* Fill Match index (don't care value) */
+        /* we assgin the same value as ip type. it will be reused for querey filter id. */
+
+        curr_meta->match_idx = 0;
+        curr_meta->mr = (match_result & 0x07);
+        curr_meta->pdn_sim_id = IPC_UT_PDN_ID;
+        curr_meta_idx ++;
+
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        is_add = KAL_FALSE;
+        curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+        curr_meta->channel_id = ((((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS) <<8 )
+                                |(netif_id & 0x000000FF) ;
+
+        switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv6_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_dhcp_ul_packet);
+                is_add = KAL_TRUE;
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv6_dhcp_packet);
+                is_add = KAL_TRUE;
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv6_tcp_fin_ack_packet;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_fin_ack_packet);
+                is_add = KAL_TRUE;
+                break;
+            case 3:
+                /* repeated 5-tuple packet */
+                packet_buf = ipc_ut_ipv6_tcp_empty_ack_packet;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_empty_ack_packet);
+                is_add = KAL_FALSE;
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv6_unknown_ext_packet;
+                packet_len = sizeof(ipc_ut_ipv6_unknown_ext_packet);
+                break;
+            case 5:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv4enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv4enc_packet);
+                break;
+            case 6:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv6enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv6enc_packet);
+                break;
+            case 7:
+                /* TODO : AH header case */
+                if (ipv6_cnt <= 10) {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag0_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag0_packet);
+                } else {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag1_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag1_packet);
+                }
+                is_add = KAL_TRUE;
+                break;
+            case 8:
+                packet_buf = ipc_ut_ipv6_frag_packet;
+                packet_len = sizeof(ipc_ut_ipv6_frag_packet);
+                is_add = KAL_TRUE;
+                break;
+            case 9:
+                packet_buf = ipc_ut_ipv6_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ip_header_packet);
+                break;
+            case 10:
+                packet_buf = ipc_ut_ipv6_incomplete_hop_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_hop_packet);
+                break;
+            case 11:
+                packet_buf = ipc_ut_ipv6_incomplete_ah_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ah_packet);
+                break;
+            default:
+                UT_ASSERT(KAL_FALSE);
+                packet_buf = ipc_ut_ipv6_mdns_packet;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                break;
+        }
+
+        kal_mem_cpy((kal_uint8*)curr_meta->addr, packet_buf, packet_len);
+        curr_meta->len = packet_len;
+
+        if (IPC_IPF_MR_UNKNOWN_HEADER == match_result && is_add) {
+            /* 11011010 */
+            curr_meta->tcp_flag = 0xDB;
+            ipc_ut_set_prepare_rq_info_list(&g_prepare_rq_info_list, packet_buf, IPC_DATA_GET_QFI(curr_meta->tcp_flag));
+            g_ipc_ut_sdap_pkt_alloc_cnt++;
+        } else {
+            curr_meta->tcp_flag = 0;
+        }
+
+        curr_meta->ip = 1;
+
+        /* Fill Match index (don't care value) */
+        /* we assgin the same value as ip type. it will be reused for querey filter id. */
+
+        curr_meta->match_idx = 1;
+        curr_meta->mr = (match_result & 0x07);
+        curr_meta->pdn_sim_id = IPC_UT_PDN_ID;
+        curr_meta_idx ++;
+
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+}
+
+kal_bool ipc_ut_sdap_meta_downlink(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    ipc_ut_netif_t   *net = NULL;
+    kal_uint32        netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool          result = KAL_FALSE;
+    ilm_struct        ilm = {0};
+    kal_uint32        ipv4_cnt = 0;
+    kal_uint32        ipv6_cnt = 0;
+    kal_uint32        ipv4_filter_cnt = 0;
+    kal_uint32        ipv6_filter_cnt = 0;
+    kal_uint8         matched_filter_idx_v4 = 0;
+    kal_uint8         matched_filter_idx_v6 = 0;
+    kal_uint32        callback_with_info = 0;
+    kal_uint32        total_cnt = 0;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 4; ipv6_cnt++)
+    for (ipv4_filter_cnt = 0; ipv4_filter_cnt <= 4; ipv4_filter_cnt++)
+    for (ipv6_filter_cnt = 0; ipv6_filter_cnt <= 1; ipv6_filter_cnt++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < ipv4_filter_cnt; matched_filter_idx_v4++)
+    for (matched_filter_idx_v6 = 0; matched_filter_idx_v6 < ipv6_filter_cnt; matched_filter_idx_v6++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+        utDLOG("ifo(%d) v4Cnt(%d) v6Cnt(%d) v4FltCnt(%d) v6FltCnt(%d) v4Idx(%d) v6Idx(%d)\r\n",
+               callback_with_info, ipv4_cnt, ipv6_cnt, ipv4_filter_cnt , ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6);
+
+        total_cnt = ipv4_cnt + ipv6_cnt;
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Install DL filter for each test loop */
+        ipc_ut_install_dl_filters(callback_with_info, KAL_TRUE, ipv4_filter_cnt, ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6, IPC_UT_LHIF_NETID_START);
+
+        ipc_ut_dl_ipf_match_filter_id_v4_s = matched_filter_idx_v4;
+        ipc_ut_dl_ipf_match_filter_id_v6_s = ipv4_filter_cnt + matched_filter_idx_v6;
+
+        /* Before PDN Binding */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            /* Before PDN Binding, IPF will only report PN not mtach case or NETIF invalid case */
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DIRECT_TO_AP ; match_result++) {
+                kal_uint32 expected_pkt_cnt;
+
+                utDLOG("@ Before activation : match_result(%d)\r\n", match_result);
+
+                ipc_ut_prepare_dl_sdap_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_pkt_cnt = total_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) || (match_result == IPC_IPF_MR_PN_NO_MATCH)) {
+                    expected_pkt_cnt = 0;
+                }
+
+                /* Make sure no DL callback to HIF */
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Check if IPCore will release buffer when NETIF is invalid */
+                /* PN_NO_MATCH & DIRECT_TO_AP no need to free buffer */
+                if ( expected_pkt_cnt != ipc_ut_dl_meta_buf_free_num_s ) {
+                    utELOG("DL buffer is not released before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         *   Simulate DL traffic from IPCore : All meta should be forward to either DL callback or filter callback(IPv4/IPv6)
+         */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            /* Before PDN Binding, IPF will only report PN not mtach case or NETIF invalid case */
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_dl_v4_filter_out_cnt;
+                kal_uint32 expected_dl_v6_filter_out_cnt;
+                kal_uint32 expected_dl_filter_out_cnt;
+                kal_uint32 did_cnt;
+                kal_uint32 expected_dl_forwad_cnt;
+
+                kal_mem_set(&g_prepare_rq_info_list, 0, sizeof(ipc_data_rq_info_list));
+                kal_mem_set(&g_rq_info_list, 0, sizeof(ipc_data_rq_info_list));
+                g_ipc_ut_sdap_pkt_alloc_cnt = 0;
+                g_ipc_ut_sdap_pkt_received_cnt = 0;
+                UT_ASSERT(0 == kal_mem_cmp(&g_prepare_rq_info_list, &g_rq_info_list, sizeof(ipc_data_rq_info_list)));
+
+                utDLOG("@ PDN connected : match_result(%d)\r\n", match_result);
+                ipc_ut_prepare_dl_sdap_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_dl_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                  (ipv4_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))? 1:0;
+                expected_dl_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                  (ipv6_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))?1:0;
+
+                expected_dl_filter_out_cnt = expected_dl_v4_filter_out_cnt + expected_dl_v6_filter_out_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) ||
+                    (match_result == IPC_IPF_MR_PN_NO_MATCH) ||
+                    (match_result == IPC_IPF_MR_NET_INVALID)) {
+                    did_cnt = expected_dl_forwad_cnt = 0;
+                } else {
+                    did_cnt = total_cnt-expected_dl_filter_out_cnt; //Supposed one DID only contains one packet
+                    expected_dl_forwad_cnt = total_cnt-expected_dl_filter_out_cnt;
+                }
+
+                UT_ASSERT(0 == kal_mem_cmp(&g_prepare_rq_info_list, &g_rq_info_list, sizeof(ipc_data_rq_info_list)));
+                UT_ASSERT(ipc_ut_rq_info_verification(&g_prepare_rq_info_list, &g_rq_info_list));
+                UT_ASSERT(g_ipc_ut_sdap_pkt_alloc_cnt == g_ipc_ut_sdap_pkt_received_cnt);
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+
+        /*
+         *   Simulate DL traffic to IPCore : After PDN deactivation, all meta should be silently dropped by IPCore and NO callback is triggered
+         */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_pkt_cnt;
+
+                utDLOG("@ PDN deactivated : dhcpv4Idx(%d), dhcpv6Idx(%d), match_result(%d)\r\n",
+                                0, 0, match_result);
+
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_pkt_cnt = total_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) || (match_result == IPC_IPF_MR_PN_NO_MATCH)) {
+                    expected_pkt_cnt = 0;
+                }
+
+                /* Make sure no DL callback to HIF */
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded when PDN deactivated!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Check if IPCore will release buffer when NETIF is invalid */
+                /* PN_NO_MATCH & DIRECT_TO_AP no need to free buffer */
+                if ( expected_pkt_cnt != ipc_ut_dl_meta_buf_free_num_s ) {
+                    utELOG("DL buffer is not released when PDN deactivated!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+    }
+
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+static LHIF_NET_TYPE ipc_ut_get_net_type_from_netif_id(kal_uint32 netif_id)
+{
+
+    UT_ASSERT(IPC_INVALID_NETIF_ID != netif_id);
+
+    switch (netif_id & 0xFFFFFF00) {
+        case IPC_NETIF_ID_LHIF_BEGIN:
+            return LHIF_NET_TYPE_LHIF;
+        case IPC_NETIF_ID_ETH_BEGIN:
+            return LHIF_NET_TYPE_RNDIS;
+        default:
+            /*can't reach here*/
+            UT_ASSERT(KAL_FALSE);
+            return LHIF_NET_TYPE_IGNORE;
+    }
+}
+
+void ipc_ut_prepare_send_did_by_ch_id_dl_list(kal_uint32 ipv4_cnt,
+                                              kal_uint32 dhcpv4_idx,
+                                              kal_bool dnsv4_only,
+                                              kal_bool v4hdr_exist,
+                                              kal_uint32 ipv6_cnt,
+                                              kal_uint32 dhcpv6_idx,
+                                              kal_bool dnsv6_only,
+                                              kal_bool v6hdr_exist,
+                                              kal_uint32 additional_bd_cnt,
+                                              kal_uint32 align_offset,
+                                              upcm_did **did_head,
+                                              upcm_did **did_tail,
+                                              kal_uint16 *ipv4_invalid_packet_len,
+                                              kal_uint16 *ipv6_invalid_packet_len,
+                                              kal_uint32 did_cnt,
+                                              kal_bool did_igr_enable)
+{
+    kal_uint32 total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32 idx;
+    upcm_did *curr_did;
+    upcm_did_si *curr_sit;
+    upcm_did_si *curr_si;
+    kal_uint32 curr_si_idx;
+    kal_uint32 pkt_start_si_idx;
+    kal_uint8 *packet_buf;
+    kal_uint32 packet_len;
+    kal_uint32 pkt_num;
+    kal_uint32 seg_num;
+
+    if (did_cnt != ipc_ut_alloc_did(did_cnt, did_head, did_tail)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did *next_did;
+        kal_bool end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (curr_did = *did_head; curr_did && (end_of_list == KAL_FALSE);
+                curr_did = next_did) {
+            kal_uint32 i;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si *si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+
+    /* Set SIT to the first SIT in DID for data configuration */
+    curr_did = *did_head;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        switch (idx % 3) {
+            case 0 :
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_3;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_3);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+            case 1 :
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_1;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_1);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+            case 2 :
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_2;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_2);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+            default :
+                packet_buf = ipc_ut_ipv4_tcp_empty_ack_packet;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_empty_ack_packet);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        if (ipv4_invalid_packet_len) {
+            if (ipv4_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv4_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv4_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) { /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else { /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt++;
+            }
+        }
+
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv4_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        packet_buf = ipc_ut_ipv6_ext0_dhcp_packet;
+        packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_packet);
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        // invalid len packet
+        if (ipv6_invalid_packet_len) {
+            if (ipv6_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv6_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv6_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) { /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else { /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt++;
+            }
+        }
+
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv6_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+}
+
+kal_bool ipc_ut_send_did_by_ch_id(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32 i = 0;
+    kal_uint32 ipv4_cnt = 0;
+    kal_uint32 ipv6_cnt = 0;
+    ipcore_upcm_pdn_bind_ind_struct *p_bind_req = NULL;
+    ipc_filter_rules_t rules = {0};
+    kal_int32 filter_id = 0;
+    kal_uint32 pdn_id = 0;
+    ipc_session_t *p_session = NULL;
+    kal_uint32 netif_id = IPC_UT_LHIF_NETID_START;
+    kal_uint8 net_type = 0;
+    kal_uint8 nc_id = 0;
+    kal_bool result = KAL_FALSE;
+
+    /* initialize before test & reset IPCORE  */
+    ipc_ut_init();
+    UT_ASSERT(KAL_TRUE == ipc_reset());
+    g_received_cnt = 0;
+
+    /* netif attach */
+    UT_ASSERT(KAL_TRUE == ipc_ut_fin_ack_filter_netif_attach());
+
+    /* IPv4 binding */
+    p_bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    p_bind_req->network_interface_id = IPC_UT_LHIF_NETID_START;
+    p_bind_req->pdn_id = IPC_UT_PDN_ID;
+    p_bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *) p_bind_req);
+    free_local_para((local_para_struct * )p_bind_req);
+
+    /* net_type and channel id test */
+    net_type = ipc_ut_get_net_type_from_netif_id(IPC_UT_LHIF_NETID_START);
+    nc_id = (net_type << 8) | ((0xFF) & IPC_UT_LHIF_NETID_START);
+
+    /* Simulate DL traffic to IPCore : PDN binding */
+    {
+        kal_uint32 did_cnt = 0;
+        upcm_did *did_head = NULL;
+        upcm_did *did_tail = NULL;
+        kal_uint32 alignment = 0;
+        kal_uint32 did_igr_bit = 0;
+        kal_uint32 free_cnt = 0;
+
+        for (alignment = 0; alignment < 4; alignment++)
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+        for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+                continue;
+            }
+
+            utDLOG("@[Binding] v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+
+            did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_prepare_send_did_by_ch_id_dl_list(ipv4_cnt,
+                                                     0,
+                                                     KAL_FALSE,
+                                                     KAL_FALSE,
+                                                     ipv6_cnt,
+                                                     0,
+                                                     KAL_FALSE,
+                                                     KAL_FALSE,
+                                                     0,
+                                                     alignment,
+                                                     &did_head,
+                                                     &did_tail,
+                                                     NULL,
+                                                     NULL,
+                                                     did_cnt,
+                                                     did_igr_bit);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            UT_ASSERT(ipc_send_dl_did_by_ch_id(net_type, nc_id, did_head, did_tail));
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+            /* verify filter result */
+            UT_ASSERT(ipc_ut_dl_callback_did_cnt == did_cnt);
+            UT_ASSERT(ipc_ut_dl_callback_did_pkt_cnt == ipv4_cnt + ipv6_cnt);
+        }
+   }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+void ipc_ut_prepare_nr_dl_did_list(kal_uint32 ipv4_cnt,
+                                   kal_uint32 dhcpv4_idx,
+                                   kal_bool   dnsv4_only,
+                                   kal_bool   v4hdr_exist,
+                                   kal_uint32 ipv6_cnt,
+                                   kal_uint32 dhcpv6_idx,
+                                   kal_bool   dnsv6_only,
+                                   kal_bool   v6hdr_exist,
+                                   kal_uint32 additional_bd_cnt,
+                                   kal_uint32 align_offset,
+                                   upcm_did   **did_head,
+                                   upcm_did   **did_tail,
+                                   kal_uint16 *ipv4_invalid_packet_len,
+                                   kal_uint16 *ipv6_invalid_packet_len,
+                                   kal_uint32 did_cnt,
+                                   kal_bool   did_igr_enable)
+{
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx;
+    upcm_did           *curr_did;
+    upcm_did_si        *curr_sit;
+    upcm_did_si        *curr_si;
+    kal_uint32          curr_si_idx;
+    kal_uint32          pkt_start_si_idx;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          pkt_num;
+    kal_uint32          seg_num;
+    kal_bool            is_add = KAL_FALSE;
+
+    if (did_cnt != ipc_ut_alloc_did(did_cnt, did_head, did_tail)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did   *next_did;
+        kal_bool    end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (curr_did = *did_head; curr_did && (end_of_list == KAL_FALSE); curr_did = next_did) {
+            kal_uint32 i = 0;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si    *si = &curr_sit[i];
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+
+    /* Set SIT to the first SIT in DID for data configuration */
+    /* use did rsv2 instead of sit qfi */
+    /* use did rsv3 instead of sit nrqi */
+    curr_did = *did_head;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        is_add = KAL_FALSE;
+        switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv4_tcp_syn_packet;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_syn_packet);
+                is_add = KAL_TRUE;
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_tcp_syn_packet;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_syn_packet);
+                is_add = KAL_FALSE;
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv4_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv4_incomplete_ip_header_packet);
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv4_frag0_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag0_packet);
+                is_add = KAL_TRUE;
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv4_frag1_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag1_packet);
+                is_add = KAL_TRUE;
+                break;
+            default:
+                UT_ASSERT(KAL_FALSE);
+                break;
+        }
+
+        if (is_add) {
+            /* 11011010 */
+            curr_si->qfi = 0xDA;
+            curr_si->nrqi = KAL_TRUE;
+            ipc_ut_set_prepare_rq_info_list(&g_prepare_rq_info_list, packet_buf, curr_si->qfi);
+            g_ipc_ut_sdap_pkt_alloc_cnt++;
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        if (ipv4_invalid_packet_len) {
+            if (ipv4_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv4_invalid_packet_len[idx]>IPC_INVALID_MAX_PKT_LEN)?IPC_INVALID_MAX_PKT_LEN:ipv4_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len = 0;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+                cont_loop_cnt ++;
+            }
+        }
+
+        if ( (did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx]) ) {
+            kal_uint32 i = 0;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num --;
+            }
+        } else {
+            pkt_num ++;
+        }
+    }
+
+    if (ipv4_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        is_add = KAL_FALSE;
+        switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv6_tcp_fin_ack_packet_2;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_fin_ack_packet_2);
+                is_add = KAL_TRUE;
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_dhcp_ul_packet);
+                is_add = KAL_TRUE;
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv6_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_dhcp_ul_packet);
+                is_add = KAL_FALSE;
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv6_incomplete_ah_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ah_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv6_unknown_ext_packet;
+                packet_len = sizeof(ipc_ut_ipv6_unknown_ext_packet);
+                break;
+            case 5:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv4enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv4enc_packet);
+                break;
+            case 6:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv6enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv6enc_packet);
+                break;
+            case 7:
+                if (ipv6_cnt <= 10) {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag0_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag0_packet);
+                } else {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag1_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag1_packet);
+                }
+                break;
+            case 8:
+                packet_buf = ipc_ut_ipv6_frag_packet;
+                packet_len = sizeof(ipc_ut_ipv6_frag_packet);
+                break;
+            default:
+                UT_ASSERT(KAL_FALSE);
+                break;
+        }
+
+        if (is_add) {
+            /* 11011010 */
+            curr_si->qfi= 0xDA;
+            curr_si->nrqi= KAL_TRUE;
+            ipc_ut_set_prepare_rq_info_list(&g_prepare_rq_info_list, packet_buf, curr_si->qfi);
+            g_ipc_ut_sdap_pkt_alloc_cnt++;
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        if (ipv6_invalid_packet_len) {
+            if (ipv6_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv6_invalid_packet_len[idx]>IPC_INVALID_MAX_PKT_LEN)?IPC_INVALID_MAX_PKT_LEN:ipv6_invalid_packet_len[idx];
+            }
+        }
+#endif
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+                cont_loop_cnt ++;
+            }
+        }
+
+        if ( (did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx]) ) {
+            kal_uint32 i = 0;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num --;
+            }
+        } else {
+            pkt_num ++;
+        }
+    }
+
+    if (ipv6_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+}
+
+static void ipc_ut_nr_did_downlink_cbk(ipc_filter_info_t *p_filter_info,
+                                       void *p_args,
+                                       kal_int32 filter_id,
+                                       qbm_gpd *p_head,
+                                       qbm_gpd *p_tail,
+                                       kal_uint32 length)
+{
+    utDLOG("ipc_ut_nr_did_downlink_cbk !!!");
+    return;
+}
+
+kal_bool ipc_ut_nr_did_downlink(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32        idx = 0;
+    ipc_ut_netif_t   *net = NULL;
+    kal_uint32        netif_id = IPC_UT_LHIF_NETID_START;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    kal_uint8         proto_idx[] = {0, 1};
+    kal_bool          result = KAL_FALSE;
+    ilm_struct        ilm = {0};
+    ipc_filter_rules_t rules = {0};
+    kal_int32 filter_id = 0;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* IPCORE may send UL traffic in disconnected state */
+        ipc_ut_reset_ul_info();
+
+        /* Simulate DL traffic to IPCore : Before PDN binding, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Before Bind] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                kal_mem_set(&g_prepare_rq_info_list, 0, sizeof(ipc_data_rq_info_list));
+                kal_mem_set(&g_rq_info_list, 0, sizeof(ipc_data_rq_info_list));
+                g_ipc_ut_sdap_pkt_alloc_cnt = 0;
+                g_ipc_ut_sdap_pkt_received_cnt = 0;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_nr_dl_did_list(ipv4_cnt,
+                                              0,
+                                              KAL_FALSE,
+                                              KAL_FALSE,
+                                              ipv6_cnt,
+                                              0,
+                                              KAL_FALSE,
+                                              KAL_FALSE,
+                                              0,
+                                              alignment,
+                                              &did_head,
+                                              &did_tail,
+                                              NULL,
+                                              NULL,
+                                              did_cnt,
+                                              KAL_FALSE);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM + idx, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+        free_local_para((local_para_struct *)bind_req);
+
+        /* Registered DL filter to filter out TCP SYN packets*/
+        rules.valid_fields = IPC_FILTER_BY_PDN_ID |
+                             IPC_FILTER_BY_PROTOCOL |
+                             IPC_FILTER_BY_TCP_FLAGS;
+        rules.ip_type = IPC_IP_TYPE_IPV6;
+        rules.protocol = IPC_HDR_PROT_TCP;
+        rules.pdn_id = IPC_UT_PDN_ID;
+        rules.tcp_flags = IPC_HDR_TCP_FLAG_SYN;
+
+        filter_id = ipc_register_dl_filter_with_info_cbk(&rules, ipc_ut_nr_did_downlink_cbk, NULL);
+        UT_ASSERT(0 == filter_id);
+
+        /* Simulate DL traffic to IPCore : All GPDs should be forward to DL callback regardless of IP types (IPv4/IPv6) */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  total_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Binded] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                kal_mem_set(&g_prepare_rq_info_list, 0, sizeof(ipc_data_rq_info_list));
+                kal_mem_set(&g_rq_info_list, 0, sizeof(ipc_data_rq_info_list));
+                g_ipc_ut_sdap_pkt_alloc_cnt = 0;
+                g_ipc_ut_sdap_pkt_received_cnt = 0;
+                UT_ASSERT(0 == kal_mem_cmp(&g_prepare_rq_info_list, &g_rq_info_list, sizeof(ipc_data_rq_info_list)));
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_nr_dl_did_list(ipv4_cnt,
+                                              0,
+                                              KAL_FALSE,
+                                              KAL_FALSE,
+                                              ipv6_cnt,
+                                              0,
+                                              KAL_FALSE,
+                                              KAL_FALSE,
+                                              0,
+                                              alignment,
+                                              &did_head,
+                                              &did_tail,
+                                              NULL,
+                                              NULL,
+                                              did_cnt,
+                                              KAL_FALSE);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx);
+
+                if ( (did_cnt != ipc_ut_dl_callback_did_cnt) ||
+                     (total_cnt != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is NOT forwarded to bound handler!\r\n");
+                    return KAL_FALSE;
+                }
+
+                UT_ASSERT(0 == kal_mem_cmp(&g_prepare_rq_info_list, &g_rq_info_list, sizeof(ipc_data_rq_info_list)));
+                /* DL callback is correctly called : all GPDs are released */
+            }
+        }
+
+        ipc_deregister_dl_filter(filter_id);
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* Simulate DL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  did_cnt;
+            upcm_did   *did_head;
+            upcm_did   *did_tail;
+            kal_uint32  alignment;
+
+            for (alignment = 0 ; alignment < 4 ; alignment ++)
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+                utDLOG("@ [Deactivated] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+                kal_mem_set(&g_prepare_rq_info_list, 0, sizeof(ipc_data_rq_info_list));
+                kal_mem_set(&g_rq_info_list, 0, sizeof(ipc_data_rq_info_list));
+                g_ipc_ut_sdap_pkt_alloc_cnt = 0;
+                g_ipc_ut_sdap_pkt_received_cnt = 0;
+
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+                ipc_ut_prepare_nr_dl_did_list(ipv4_cnt,
+                                              0,
+                                              KAL_FALSE,
+                                              KAL_FALSE,
+                                              ipv6_cnt,
+                                              0,
+                                              KAL_FALSE,
+                                              KAL_FALSE,
+                                              0,
+                                              alignment,
+                                              &did_head,
+                                              &did_tail,
+                                              NULL,
+                                              NULL,
+                                              did_cnt,
+                                              KAL_FALSE);
+
+                /* simulate DL traffic from IPC_UT_PDN_ID */
+                ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx);
+
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded after PDN deactivation!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+#endif
+
+static kal_bool ipc_ut_rebind_pdn_verification(ps_cause_enum result,
+                                               ipcore_upcm_pdn_rebind_ind_struct *p_rebind_req,
+                                               ipc_ut_msg_t *p_recv_ilm)
+{
+    ipcore_upcm_pdn_rebind_rsp_struct *p_rcv_rebind = NULL;
+    ipcore_upcm_pdn_rebind_rsp_struct *p_rebind_rsp = NULL;
+
+    UT_ASSERT(NULL != p_rebind_req);
+    UT_ASSERT(NULL != p_recv_ilm);
+
+    p_rebind_rsp = (ipcore_upcm_pdn_rebind_rsp_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_rebind_rsp_struct), TD_RESET);
+    p_rebind_rsp->network_interface_id = IPC_UT_LHIF_NETID_START;
+    p_rebind_rsp->old_pdn_id = p_rebind_req->old_pdn_id;
+    p_rebind_rsp->new_pdn_id = p_rebind_req->new_pdn_id;
+    kal_mem_cpy(&p_rebind_rsp->dns, &p_rebind_req->dns, sizeof(dns_struct));
+    kal_mem_cpy(&p_rebind_rsp->ip_addr, &p_rebind_req->ip_addr, sizeof(ip_addr_struct));
+    p_rebind_rsp->result = result;
+
+    p_rcv_rebind = (ipcore_upcm_pdn_rebind_rsp_struct *)p_recv_ilm->_local_para_ptr;
+    UT_ASSERT(MOD_IPCORE == ipc_ut_msg_sent._dest_mod_id);
+    UT_ASSERT(MOD_NIL == ipc_ut_msg_sent._src_mod_id);
+    UT_ASSERT(MSG_ID_IPCORE_UPCM_PDN_REBIND_RSP == ipc_ut_msg_sent._msg_id);
+    UT_ASSERT(IPCORE_SAP == ipc_ut_msg_sent._sap_id);
+    UT_ASSERT(p_rebind_rsp->network_interface_id == p_rcv_rebind->network_interface_id);
+    UT_ASSERT(p_rebind_rsp->new_pdn_id == p_rcv_rebind->new_pdn_id);
+    UT_ASSERT(p_rebind_rsp->old_pdn_id == p_rcv_rebind->old_pdn_id);
+    UT_ASSERT(p_rebind_rsp->result == p_rcv_rebind->result);
+    UT_ASSERT(0 == kal_mem_cmp(&p_rebind_rsp->dns, &p_rcv_rebind->dns, sizeof(dns_struct)));
+    UT_ASSERT(0 == kal_mem_cmp(&p_rebind_rsp->ip_addr, &p_rcv_rebind->ip_addr, sizeof(ip_addr_struct)));
+    UT_ASSERT(NULL == ipc_ut_msg_sent._peer_buff_ptr);
+
+    free_local_para((local_para_struct *)p_rebind_rsp);
+    return KAL_TRUE;
+}
+
+static kal_bool ipc_ut_unbind_pdn_req(kal_uint8 unbind_pdn)
+{
+    ilm_struct ilm = {0};
+    ipcore_upcm_pdn_unbind_ind_struct *p_unbind_req = NULL;
+
+    p_unbind_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+    UT_ASSERT(NULL != p_unbind_req);
+    p_unbind_req->pdn_id = unbind_pdn;
+
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ilm.src_mod_id = MOD_UPCM;
+    ilm.dest_mod_id = MOD_IPCORE;
+    ilm.sap_id = IPCORE_SAP;
+    ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+    ilm.local_para_ptr = (local_para_struct *)p_unbind_req;
+    ilm.peer_buff_ptr = NULL;
+    ipc_on_ilm(&ilm);
+    free_local_para((local_para_struct *)p_unbind_req);
+
+    return KAL_TRUE;
+}
+
+static kal_bool ipc_ut_bind_pdn_req(pdp_addr_type_enum pdn_ip_type,
+                                    kal_uint8 pdn_id,
+                                    kal_uint32 netif_id)
+{
+    ilm_struct ilm = {0};
+    ipcore_upcm_pdn_bind_ind_struct *p_bind_req = NULL;
+
+    p_bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    p_bind_req->network_interface_id = netif_id;
+    p_bind_req->pdn_id = pdn_id;
+
+    switch (pdn_ip_type) {
+        case IPV4_ADDR_TYPE:
+            p_bind_req->dns.v4[0].is_dnsv4_present = KAL_TRUE;
+            p_bind_req->dns.v4[0].dnsv4[0] = 8;
+            p_bind_req->dns.v4[0].dnsv4[1] = 8;
+            p_bind_req->dns.v4[0].dnsv4[2] = 8;
+            p_bind_req->dns.v4[0].dnsv4[3] = 8;
+            p_bind_req->ip_addr.ip_addr_type = IPV4_ADDR_TYPE;
+            p_bind_req->ip_addr.ipv4[0] = 192;
+            p_bind_req->ip_addr.ipv4[1] = 168;
+            p_bind_req->ip_addr.ipv4[2] = 0;
+            p_bind_req->ip_addr.ipv4[3] = 2;
+            break;
+        case IPV6_ADDR_TYPE:
+            p_bind_req->dns.v6[0].is_dnsv6_present = KAL_TRUE;
+            p_bind_req->dns.v6[0].dnsv6[0] = 1;
+            p_bind_req->dns.v6[0].dnsv6[1] = 2;
+            p_bind_req->dns.v6[0].dnsv6[2] = 3;
+            p_bind_req->dns.v6[0].dnsv6[3] = 4;
+            p_bind_req->dns.v6[0].dnsv6[4] = 5;
+            p_bind_req->dns.v6[0].dnsv6[5] = 6;
+            p_bind_req->dns.v6[0].dnsv6[6] = 7;
+            p_bind_req->dns.v6[0].dnsv6[7] = 8;
+
+            p_bind_req->ip_addr.ip_addr_type = IPV6_ADDR_TYPE;
+            p_bind_req->ip_addr.ipv6[0] = 0xfd;
+            p_bind_req->ip_addr.ipv6[1] = 0xf1;
+            p_bind_req->ip_addr.ipv6[2] = 0x03;
+            p_bind_req->ip_addr.ipv6[3] = 0x04;
+            p_bind_req->ip_addr.ipv6[4] = 0x05;
+            p_bind_req->ip_addr.ipv6[5] = 0x06;
+            p_bind_req->ip_addr.ipv6[6] = 0x07;
+            p_bind_req->ip_addr.ipv6[7] = 0x08;
+            break;
+        case IPV4V6_ADDR_TYPE:
+            p_bind_req->dns.v4[0].is_dnsv4_present = KAL_TRUE;
+            p_bind_req->dns.v4[0].dnsv4[0] = 8;
+            p_bind_req->dns.v4[0].dnsv4[1] = 8;
+            p_bind_req->dns.v4[0].dnsv4[2] = 8;
+            p_bind_req->dns.v4[0].dnsv4[3] = 8;
+            p_bind_req->ip_addr.ip_addr_type = IPV4_ADDR_TYPE;
+            p_bind_req->ip_addr.ipv4[0] = 192;
+            p_bind_req->ip_addr.ipv4[1] = 168;
+            p_bind_req->ip_addr.ipv4[2] = 0;
+            p_bind_req->ip_addr.ipv4[3] = 2;
+            break;
+        default:
+            utELOG("unsupported pdn ip type");
+            return KAL_FALSE;
+            break;
+    }
+
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ilm.src_mod_id = MOD_UPCM;
+    ilm.dest_mod_id = MOD_IPCORE;
+    ilm.sap_id = IPCORE_SAP;
+    ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+    ilm.local_para_ptr = (local_para_struct *)p_bind_req;
+    ilm.peer_buff_ptr = NULL;
+    ipc_on_ilm(&ilm);
+    free_local_para((local_para_struct *)p_bind_req);
+
+    return KAL_TRUE;
+}
+
+static kal_bool ipc_ut_rebind_pdn_req(ipcore_upcm_pdn_rebind_ind_struct **p_rebind_req2,
+                                      pdp_addr_type_enum pdn_ip_type,
+                                      kal_uint8 old_pdn_id,
+                                      kal_uint8 new_pdn_id,
+                                      kal_uint32 netif_id)
+{
+    ilm_struct ilm = {0};
+    ipcore_upcm_pdn_rebind_ind_struct *p_rebind_req = NULL;
+
+    p_rebind_req = (ipcore_upcm_pdn_rebind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_rebind_ind_struct), TD_RESET);
+    p_rebind_req->network_interface_id = IPC_UT_LHIF_NETID_START;
+    p_rebind_req->old_pdn_id = old_pdn_id;
+    p_rebind_req->new_pdn_id = new_pdn_id;
+
+    switch (pdn_ip_type) {
+        case IPV4_ADDR_TYPE:
+            p_rebind_req->dns.v4[0].is_dnsv4_present = KAL_TRUE;
+            p_rebind_req->dns.v4[0].dnsv4[0] = 8;
+            p_rebind_req->dns.v4[0].dnsv4[1] = 8;
+            p_rebind_req->dns.v4[0].dnsv4[2] = 8;
+            p_rebind_req->dns.v4[0].dnsv4[3] = 8;
+            p_rebind_req->ip_addr.ip_addr_type = IPV4_ADDR_TYPE;
+            p_rebind_req->ip_addr.ipv4[0] = 192;
+            p_rebind_req->ip_addr.ipv4[1] = 168;
+            p_rebind_req->ip_addr.ipv4[2] = 0;
+            p_rebind_req->ip_addr.ipv4[3] = 1;
+            break;
+        case IPV6_ADDR_TYPE:
+            p_rebind_req->dns.v6[0].is_dnsv6_present = KAL_TRUE;
+            p_rebind_req->dns.v6[0].dnsv6[0] = 8;
+            p_rebind_req->dns.v6[0].dnsv6[1] = 7;
+            p_rebind_req->dns.v6[0].dnsv6[2] = 6;
+            p_rebind_req->dns.v6[0].dnsv6[3] = 5;
+            p_rebind_req->dns.v6[0].dnsv6[4] = 4;
+            p_rebind_req->dns.v6[0].dnsv6[5] = 3;
+            p_rebind_req->dns.v6[0].dnsv6[6] = 2;
+            p_rebind_req->dns.v6[0].dnsv6[7] = 1;
+
+            p_rebind_req->ip_addr.ip_addr_type = IPV6_ADDR_TYPE;
+            p_rebind_req->ip_addr.ipv6[0] = 0xfe;
+            p_rebind_req->ip_addr.ipv6[1] = 0xf0;
+            p_rebind_req->ip_addr.ipv6[2] = 0x01;
+            p_rebind_req->ip_addr.ipv6[3] = 0x02;
+            p_rebind_req->ip_addr.ipv6[4] = 0x03;
+            p_rebind_req->ip_addr.ipv6[5] = 0x04;
+            p_rebind_req->ip_addr.ipv6[6] = 0x05;
+            p_rebind_req->ip_addr.ipv6[7] = 0x06;
+            break;
+        case IPV4V6_ADDR_TYPE:
+            p_rebind_req->dns.v4[0].is_dnsv4_present = KAL_TRUE;
+            p_rebind_req->dns.v4[0].dnsv4[0] = 8;
+            p_rebind_req->dns.v4[0].dnsv4[1] = 8;
+            p_rebind_req->dns.v4[0].dnsv4[2] = 8;
+            p_rebind_req->dns.v4[0].dnsv4[3] = 8;
+            p_rebind_req->ip_addr.ip_addr_type = IPV4_ADDR_TYPE;
+            p_rebind_req->ip_addr.ipv4[0] = 192;
+            p_rebind_req->ip_addr.ipv4[1] = 168;
+            p_rebind_req->ip_addr.ipv4[2] = 0;
+            p_rebind_req->ip_addr.ipv4[3] = 1;
+            break;
+        default:
+            utELOG("unsupported pdn ip type");
+            return KAL_FALSE;
+            break;
+    }
+
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ilm.src_mod_id = MOD_UPCM;
+    ilm.dest_mod_id = MOD_IPCORE;
+    ilm.sap_id = IPCORE_SAP;
+    ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_REBIND_IND;
+    ilm.local_para_ptr = (local_para_struct *)p_rebind_req;
+    ilm.peer_buff_ptr = NULL;
+    ipc_on_ilm(&ilm);
+
+    *p_rebind_req2 = p_rebind_req;
+    return KAL_TRUE;
+}
+
+void ipc_ut_prepare_dl_did_list_tcprst(
+        kal_uint32 pkt_cnt,
+        kal_uint32 align_offset,
+        upcm_did   **did_head,
+        upcm_did   **did_tail,
+        kal_uint32 did_cnt)
+{
+    kal_uint32          total_cnt = pkt_cnt;
+    kal_uint32          idx;
+    upcm_did           *curr_did;
+    upcm_did_si        *curr_sit;
+    upcm_did_si        *curr_si;
+    kal_uint32          curr_si_idx;
+    kal_uint32          pkt_start_si_idx;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          pkt_num;
+    kal_uint32          seg_num;
+    kal_uint8           per_pkt_max_sit_num = 10; /* one DID max packet number will be 7. one DID has 62 SIT entries */
+
+    if (did_cnt != ipc_ut_alloc_did(
+                        did_cnt,
+                        did_head,
+                        did_tail)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did   *next_did;
+        kal_bool    end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (   curr_did = *did_head ;
+                curr_did && (end_of_list == KAL_FALSE) ;
+                curr_did = next_did)
+        {
+            kal_uint32  i;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si    *si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+    /*must have ra packet , test included to have other packets based upon ipv6 packet count*/
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+    for (idx = 0; idx < pkt_cnt; idx++) {
+        switch(idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv4_tcp_fin_ack_packet;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_fin_ack_packet);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_tcp_ack_packet;
+                packet_len = sizeof(ipc_ut_ipv4_tcp_ack_packet);
+                break;
+            case 2: // non tcp packet
+                packet_buf = ipc_ut_non_ip_packet;
+                packet_len = sizeof(ipc_ut_non_ip_packet);
+                break;
+			case 3:
+				// no-IP packet
+				packet_buf = ipc_ut_non_ip_packet;
+				packet_len = sizeof(ipc_ut_non_ip_packet);
+                break;
+			case 4:
+				// fragment non-1st packet
+				packet_buf = ipc_ut_ipv4_tcp_error_frag1_packet;
+				packet_len = sizeof(ipc_ut_ipv4_tcp_error_frag1_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_tcp_syn_packet;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_syn_packet);
+                break;
+
+        }
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len)
+            {
+                kal_uint32 current_copy_len;
+
+                if ((curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) || (cont_loop_cnt == per_pkt_max_sit_num-1))
+                {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else
+                {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt ++;
+            }
+        }
+        pkt_num ++;
+
+    }
+
+    UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+    UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+ }
+
+void ipc_ut_prepare_dl_did_list_udp(
+        kal_uint32 ipv4_cnt,
+        kal_uint32 align_offset,
+        upcm_did   **did_head,
+        upcm_did   **did_tail,
+        kal_uint32 did_cnt)
+{
+    kal_uint32          total_cnt = ipv4_cnt;
+    kal_uint32          idx;
+    upcm_did           *curr_did;
+    upcm_did_si        *curr_sit;
+    upcm_did_si        *curr_si;
+    kal_uint32          curr_si_idx;
+    kal_uint32          pkt_start_si_idx;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          pkt_num;
+    kal_uint32          seg_num;
+	kal_uint8           per_pkt_max_sit_num = 10; /* one DID max packet number will be 7. one DID has 62 SIT entries */
+
+    if (did_cnt != ipc_ut_alloc_did(
+                        did_cnt,
+                        did_head,
+                        did_tail)) {
+        IPC_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did   *next_did;
+        kal_bool    end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (   curr_did = *did_head ;
+                curr_did && (end_of_list == KAL_FALSE) ;
+                curr_did = next_did)
+        {
+            kal_uint32      i;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si    *si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        switch(idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv4_udp_packet_example;
+                packet_len = sizeof(ipc_ut_ipv4_udp_packet_example);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_udp_packet;
+                packet_len = sizeof(ipc_ut_ipv4_udp_packet);
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv6_udp_packet;
+                packet_len = sizeof(ipc_ut_ipv6_udp_packet);
+                break;
+            case 3:
+                packet_buf = g_ipc_ut_large_udp_pkt;
+                packet_len = sizeof(g_ipc_ut_large_udp_pkt);
+                break;
+            default:
+                packet_buf = ipc_ut_non_ip_packet;
+                packet_len = sizeof(ipc_ut_non_ip_packet);
+                break;
+        }
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len)
+            {
+                kal_uint32 current_copy_len;
+
+                if ((curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) || (cont_loop_cnt == per_pkt_max_sit_num-1))
+                {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else
+                {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    IPC_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt ++;
+            }
+        }
+        pkt_num ++;
+
+    }
+
+    UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+    UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+ }
+
+
+kal_bool ipc_ut_downlink_test_udp_drop_packet(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+        ipc_ut_netif_t   *net;
+    kal_uint32       netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool         result;
+    kal_uint8         proto_idx[] = {0, 1, 2, 3};
+    kal_uint32        idx;
+    kal_uint32       gpd_remain_cnt_ul, gpd_remain_cnt_dl, did_remain_cnt;
+    // init before test
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * ipc_attach()
+     */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++)
+    {
+        kal_uint32  cnt;
+        kal_uint32  did_cnt;
+        upcm_did   *did_head;
+        upcm_did   *did_tail;
+        kal_uint32  alignment;
+        kal_uint8 expected_pkt_cnt = 0;
+
+        for (alignment = 0 ; alignment < 1 ; alignment ++)
+        for (cnt = 1; cnt <= 5; cnt++) {
+
+            did_cnt = 1;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_reset_ul_info();
+
+            /*Store DID remain cnt */
+			did_remain_cnt = upcm_did_get_buff_remain_num();
+
+            /*prepare a DID of UDP ipv4 */
+            ipc_ut_prepare_dl_did_list_udp(cnt,
+                                        alignment,
+                                        &did_head,
+                                        &did_tail,
+                                        did_cnt);
+
+            /*Store GPD remain cnt */
+            gpd_remain_cnt_ul = qbm_get_buff_remain_num(QBM_TYPE_NET_UL);
+            gpd_remain_cnt_dl = qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx); //0 for SIM1
+
+            /*packet 1, 2, 3: udp packet
+                above 3 are non udp packet*/
+            if(cnt <= 3)
+            {
+                expected_pkt_cnt = cnt;
+            } else {
+                expected_pkt_cnt = 3;
+            }
+
+            if (ipc_ut_ul_gpd_cnt != expected_pkt_cnt) {
+                utELOG("wrong expected count!\r\n");
+                return KAL_FALSE;
+            }
+
+            if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                utELOG("DL DID is forwarded on PDN unbind!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(gpd_remain_cnt_ul != qbm_get_buff_remain_num(QBM_TYPE_NET_UL)){
+                utELOG("wrong expected QBM_TYPE_NET_UL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(gpd_remain_cnt_dl != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+
+			if(did_remain_cnt != upcm_did_get_buff_remain_num()){
+                utELOG("wrong expected DID count!\r\n");
+                return KAL_FALSE;
+            }
+
+        }
+    }
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+
+}
+
+kal_bool ipc_ut_downlink_tcprst_packet(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t   *net;
+    kal_uint32       netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool         result;
+    kal_uint8        proto_idx[] = {0, 1, 2, 3};
+    kal_uint32       idx;
+    kal_uint32       gpd_remain_cnt_ul, gpd_remain_cnt_dl, did_remain_cnt;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /*
+     * Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * ipc_attach()
+     */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* no BINDING */
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++)
+    {
+        kal_uint32  pkt_cnt;
+        kal_uint32  did_cnt;
+        upcm_did   *did_head;
+        upcm_did   *did_tail;
+        kal_uint32  alignment;
+        kal_uint8 expected_pkt_cnt = 0;
+
+        for (alignment = 0 ; alignment < 4 ; alignment ++)
+        for (pkt_cnt = 1; pkt_cnt <= 5; pkt_cnt++) {
+
+            did_cnt = 1;
+            expected_pkt_cnt = 0;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_reset_ul_info();
+
+            /*Store DID remain cnt */
+            did_remain_cnt = upcm_did_get_buff_remain_num();
+
+            /* prepare a DID of TCP RST */
+            ipc_ut_prepare_dl_did_list_tcprst(pkt_cnt,
+                                             alignment,
+                                             &did_head,
+                                             &did_tail,
+                                             did_cnt);
+
+            /*Store GPD remain cnt */
+            gpd_remain_cnt_ul = qbm_get_buff_remain_num(QBM_TYPE_NET_UL);
+            gpd_remain_cnt_dl = qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID on unbind condition*/
+            ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx); //0 for SIM1
+            if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                utELOG("DL DID is forwarded on PDN unbind!\r\n");
+                return KAL_FALSE;
+            }
+
+            /* expected ul pkt cnt should be
+             * pkt 1 is of fin ack, generate 2 GPD
+             * pkt 2 is of ack pkt , generate 1 GPD
+             * pkt 3 is of ipv4 DNS packet(non tcp), generate 0 GPD
+             * pkt 4 is of non-IP packet, generate 0 GPD
+             * pkt 5 is of ipv4 non 1st fragment, generate 0 GPD
+             */
+            if ( pkt_cnt >= 1) {
+                expected_pkt_cnt += 2;
+            }
+            if ( pkt_cnt >= 2) {
+                expected_pkt_cnt += 1;
+            }
+            if ( pkt_cnt >= 3) {
+                expected_pkt_cnt += 0;
+            }
+            if ( pkt_cnt >= 4) {
+                expected_pkt_cnt += 0;
+            }
+            if ( pkt_cnt >= 5) {
+                expected_pkt_cnt += 0;
+            }
+
+            if (ipc_ut_ul_gpd_cnt != expected_pkt_cnt) {
+                utELOG("wrong expected count!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(gpd_remain_cnt_ul != qbm_get_buff_remain_num(QBM_TYPE_NET_UL)){
+                utELOG("wrong expected QBM_TYPE_NET_UL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(gpd_remain_cnt_dl != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(did_remain_cnt != upcm_did_get_buff_remain_num()){
+                utELOG("wrong expected DID count!\r\n");
+                return KAL_FALSE;
+            }
+        }
+    }
+
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+static kal_bool ipc_ut_netif_attach(ipc_ut_netif_t *p_netif,
+                                    kal_uint32 netif_id)
+{
+    UT_ASSERT(NULL != p_netif);
+
+    kal_mem_set(p_netif, 0, sizeof(ipc_ut_netif_t));
+    p_netif->conf.module_id = MOD_IPCORE;
+    p_netif->conf.netif_id = netif_id;
+    p_netif->conf.ul_reload_context = p_netif;
+    p_netif->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    p_netif->conf.callback_context = p_netif;
+    p_netif->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    p_netif->conf.features = 0;
+    UT_ASSERT(ipc_attach(&p_netif->conf, &p_netif->handle));
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_rebind_pdn(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    ipc_ut_netif_t *p_netid_1 = &(ipc_ut_nets_s[0]);
+    ipc_ut_netif_t *p_netid_2 = &(ipc_ut_nets_s[1]);
+    ipcore_upcm_pdn_rebind_ind_struct *p_rebind_req = NULL;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    UT_ASSERT(ipc_reset());
+
+    /* Case 1 : no netif attach, no pdn binding, IPCore received rebind request from UPCM */
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_PDN_BIND_RSP_INVALID_NETIF, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+
+    /* Case 2 : netif attach, no pdn binding, IPCore received rebind request from UPCM */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_PDN_BIND_RSP_SESSION_RLOCK_FAIL, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 3 : netif attach, pdn IPv4 binding, IPCore received rebind request from UPCM */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    //UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID));
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 4 : netif attach, pdn IPv4 binding, IPCore received rebind request from UPCM with wrong old pdn */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4_ADDR_TYPE, IPC_UT_PDN_ID + 2, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_PDN_BIND_RSP_SESSION_RLOCK_FAIL, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 5 : netif attach, pdn IPv4 binding, IPCore received rebind request from UPCM with IPv4v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4V6_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    //UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID));
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 6 : netif attach, pdn IPv4 binding, IPCore received rebind request from UPCM with v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV6_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 7 : netif attach, pdn IPv6 binding, IPCore received rebind request from UPCM with v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV6_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 7 : netif attach, pdn IPv6 binding, IPCore received rebind request from UPCM with v4 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 8 : netif attach, pdn IPv6 binding, IPCore received rebind request from UPCM with v4v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4V6_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 9 : netif attach, pdn IPv4v6 binding, IPCore received rebind request from UPCM with v4v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4V6_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4V6_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 10 : netif attach, pdn IPv4v6 binding, IPCore received rebind request from UPCM with v4 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4V6_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 11 : netif attach, pdn IPv4v6 binding, IPCore received rebind request from UPCM with v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4V6_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV6_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 12 : netif attach, pdn IPv4 IPv6 binding, IPCore received rebind request from UPCM with v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV6_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_PDN_BIND_RSP_NEW_SESSION_FAIL, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID));
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID+1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 13 : netif attach, pdn IPv4 IPv6 binding, IPCore received rebind request from UPCM with v4 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_PDN_BIND_RSP_NEW_SESSION_FAIL, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 14 : netif attach, pdn IPv4 IPv6 binding, IPCore received rebind request from UPCM with v4 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 2, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 2));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 15 : netif attach, pdn IPv4 IPv6 binding, IPCore received rebind request from UPCM with v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV6_ADDR_TYPE, IPC_UT_PDN_ID + 1, IPC_UT_PDN_ID + 2, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID));
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 2));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 15 : netif attach, pdn IPv4 IPv6 binding, IPCore received rebind request from UPCM with v4v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4V6_ADDR_TYPE, IPC_UT_PDN_ID + 1, IPC_UT_PDN_ID + 2, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_PDN_BIND_RSP_NEW_SESSION_FAIL, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 16 : netif attach, pdn IPv4 IPv6 binding, IPCore received rebind request from UPCM with v4v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4V6_ADDR_TYPE, IPC_UT_PDN_ID + 1, IPC_UT_PDN_ID + 2, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 2));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    /* Case 17 : netif attach, pdn IPv4 IPv6 binding, IPCore received rebind request from UPCM with v4v6 pdn type */
+    UT_ASSERT(ipc_ut_netif_attach(p_netid_1, IPC_UT_LHIF_NETID_START));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV4_ADDR_TYPE, IPC_UT_PDN_ID, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_bind_pdn_req(IPV6_ADDR_TYPE, IPC_UT_PDN_ID + 1, p_netid_1->conf.netif_id));
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 1));
+    UT_ASSERT(ipc_ut_rebind_pdn_req(&p_rebind_req, IPV4V6_ADDR_TYPE, IPC_UT_PDN_ID, IPC_UT_PDN_ID + 2, p_netid_1->conf.netif_id));
+    UT_ASSERT(NULL != p_rebind_req);
+
+    /* verification */
+    UT_ASSERT(ipc_ut_rebind_pdn_verification(HIF_IPC_OK, p_rebind_req, &ipc_ut_msg_sent));
+    free_local_para((local_para_struct *)p_rebind_req);
+    UT_ASSERT(ipc_ut_unbind_pdn_req(IPC_UT_PDN_ID + 2));
+    UT_ASSERT(ipc_detach(p_netid_1->handle));
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ipc_fragment(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    ipc_fragment_test();
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+void ipc_ut_filter_info_cbk(ipc_filter_info_t *info_p,
+                            void *context,
+                            kal_int32 filter_id,
+                            qbm_gpd *p_head,
+                            qbm_gpd *p_tail,
+                            kal_uint32 length)
+{
+    g_normal_cbk_pkt_recv_cnt++;
+    qbmt_dest_q(p_head, p_tail);
+}
+
+void ipc_ut_filter_cbk(void *context,
+                       kal_int32 filter_id,
+                       qbm_gpd *p_head,
+                       qbm_gpd *p_tail,
+                       kal_uint32 length)
+{
+    g_normal_cbk_pkt_recv_cnt++;
+    qbmt_dest_q(p_head, p_tail);
+}
+
+kal_bool ipc_ut_cust_filter_cbk(const kal_uint8 *p_pkt,
+                                kal_int32 pkt_len,
+                                kal_int32 filter_id,
+                                void *p_args)
+{
+    kal_bool ret = KAL_FALSE;
+    kal_uint32 win_size = 0;
+
+    if (IPC_HDR_IS_V4(p_pkt)) {
+        win_size = IPC_HDR_TCP_GET_WINDOW(p_pkt + IPC_HDR_V4_HEADER_SIZE);
+        if (0x2001 == win_size) {
+            g_cbk_pkt_recv_cnt++;
+            ret = KAL_TRUE;
+        }
+    } else if (IPC_HDR_IS_V6(p_pkt)) {
+    } else {
+        UT_ASSERT(KAL_FALSE);
+    }
+
+    return ret;
+}
+
+kal_bool ipc_ut_new_filter_verification(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    ipc_filter_rules_t rules = {0};
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+    kal_int32 filter_id = 0;
+
+    /* invalid data path */
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(2, &rules, &ntfy_ctxt));
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(3, &rules, &ntfy_ctxt));
+
+    /* invalid rules */
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(UL_DIRECT, &rules, &ntfy_ctxt));
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, NULL, &ntfy_ctxt));
+
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_UDP;
+    rules.pdn_id = 5;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+
+    /* invalid ntfy_ctxt */
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(UL_DIRECT, &rules, &ntfy_ctxt));
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, NULL));
+
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM;
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    UT_ASSERT(1 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+    ipc_dereg_filter(1);
+
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO;
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    UT_ASSERT(1 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+    ipc_dereg_filter(1);
+
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    UT_ASSERT(1 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+    ipc_dereg_filter(1);
+
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    UT_ASSERT(1 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+    ipc_dereg_filter(1);
+
+    rules.features |= IPC_FILTER_FEATURE_CUST_FILTER;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM;
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_ILM_WITH_FILTER_INFO;
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    rules.cust_cbk_func = ipc_ut_cust_filter_cbk;
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    UT_ASSERT(1 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+    ipc_dereg_filter(1);
+
+    /* invalid DL filter to filter out ESP packets : no set PROTOCOL in valid fields */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_SPI |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.spi = 0x0000000a;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+
+    /* invalid DL filter to filter out ESP packets : set wrong PROTOCOL in valid fields */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_SPI |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_UDP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.spi = 0x0000000a;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+
+    /* valid DL filter to filter out ESP packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_SPI |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_ESP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.spi = 0x0000000a;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* invalid DL filter to filter out src port packets : wrong protocol */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_SRC_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_ESP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.src_port = 132;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+
+    /* invalid DL filter to filter out dst port packets : wrong protocol */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_DST_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_ICMP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.src_port = 132;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+
+    /* invalid DL filter to filter out icmp v4 packets : wrong protocol */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_ICMPV4_TYPE |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_UDP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.src_port = 132;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+
+    /* invalid DL filter to filter out icmp v4 packets : wrong ip version */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_ICMPV4_TYPE |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_ICMP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.src_port = 132;
+    rules.ip_type = IPC_IP_TYPE_IPV6;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+
+    /* invalid DL filter to filter out icmp v6 packets : wrong protocol */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_ICMPV6_TYPE |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_UDP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.src_port = 132;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+
+    /* invalid DL filter to filter out icmp v4 packets : wrong ip version */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_ICMPV6_TYPE |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_ICMP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.src_port = 132;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(IPC_INVALID_FILTER_ID == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+
+    /* valid DL filter to filter out tcp port packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_SRC_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_TCP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    rules.src_ipv4.addr32 = 3;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* valid DL filter to filter out tcp port packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_SRC_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_TCP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV6;
+    rules.src_ipv6.addr32[0] = 3;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* valid DL filter to filter out tcp port packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_DST_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_TCP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    rules.dst_ipv4.addr32 = 3;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* valid DL filter to filter out tcp port packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_DST_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_TCP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV6;
+    rules.dst_ipv6.addr32[0] = 3;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* valid DL filter to filter out udp port packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_SRC_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_UDP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    rules.src_ipv4.addr32 = 3;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* valid DL filter to filter out udp port packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_SRC_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_UDP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV6;
+    rules.src_ipv6.addr32[0] = 3;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* valid DL filter to filter out udp port packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_DST_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_UDP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    rules.dst_ipv4.addr32 = 3;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* valid DL filter to filter out udp port packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_DST_PORT |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_UDP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV6;
+    rules.dst_ipv6.addr32[0] = 3;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* valid DL filter to filter out icmp v4 packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_ICMPV4_TYPE |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_ICMP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    rules.icmpv4_type = 2;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    /* valid DL filter to filter out icmp v6 packets */
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_ICMPV6_TYPE |
+                         IPC_FILTER_BY_PDN_ID;
+    rules.protocol = IPC_HDR_PROT_ICMPV6;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.ip_type = IPC_IP_TYPE_IPV6;
+    rules.icmpv6_type = 2;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    UT_ASSERT(0 == ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt));
+    ipc_dereg_filter(0);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_esp_parser(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    ipc_packet_info_t p_info = {0};
+    kal_uint32 spi = 0;
+
+    kal_mem_set(&p_info, 0, sizeof(p_info));
+    ipc_get_packet_info(g_ipc_ut_v4_esp_pkt_1, sizeof(g_ipc_ut_v4_esp_pkt_1), &p_info);
+    spi = 0x0000000a;
+    UT_ASSERT(spi == p_info.spi);
+    UT_ASSERT(IPC_HDR_PROT_ESP == p_info.protocol);
+
+    kal_mem_set(&p_info, 0, sizeof(p_info));
+    ipc_get_packet_info(g_ipc_ut_v4_ah_esp_pkt_1, sizeof(g_ipc_ut_v4_ah_esp_pkt_1), &p_info);
+    spi = 0x48dac2e4;
+    UT_ASSERT(spi == p_info.spi);
+    UT_ASSERT(IPC_HDR_PROT_ESP == p_info.protocol);
+
+    kal_mem_set(&p_info, 0, sizeof(p_info));
+    ipc_get_packet_info(g_ipc_ut_v6_esp_pkt_1, sizeof(g_ipc_ut_v6_esp_pkt_1), &p_info);
+    spi = 0x49507646;
+    UT_ASSERT(spi == p_info.spi);
+    UT_ASSERT(IPC_HDR_PROT_ESP == p_info.protocol);
+
+    kal_mem_set(&p_info, 0, sizeof(p_info));
+    ipc_get_packet_info(g_ipc_ut_v6_ah_esp_pkt_1, sizeof(g_ipc_ut_v6_ah_esp_pkt_1), &p_info);
+    spi = 0x49507656;
+    UT_ASSERT(spi == p_info.spi);
+    UT_ASSERT(IPC_HDR_PROT_ESP == p_info.protocol);
+
+    kal_mem_set(&p_info, 0, sizeof(p_info));
+    ipc_get_packet_info(g_ipc_ut_v6_routing_ah_esp_pkt_1, sizeof(g_ipc_ut_v6_routing_ah_esp_pkt_1), &p_info);
+    spi = 0x49507666;
+    UT_ASSERT(spi == p_info.spi);
+    UT_ASSERT(IPC_HDR_PROT_ESP == p_info.protocol);
+
+    kal_mem_set(&p_info, 0, sizeof(p_info));
+    ipc_get_packet_info(g_ipc_ut_v6_routing_esp_pkt_1, sizeof(g_ipc_ut_v6_routing_esp_pkt_1), &p_info);
+    spi = 0x49507676;
+    UT_ASSERT(spi == p_info.spi);
+    UT_ASSERT(IPC_HDR_PROT_ESP == p_info.protocol);
+
+    kal_mem_set(&p_info, 0, sizeof(p_info));
+    ipc_get_packet_info(g_ipc_ut_v6_hop_dst_route_esp_pkt_1, sizeof(g_ipc_ut_v6_hop_dst_route_esp_pkt_1), &p_info);
+    spi = 0x49508637;
+    UT_ASSERT(spi == p_info.spi);
+    UT_ASSERT(IPC_HDR_PROT_ESP == p_info.protocol);
+
+    kal_mem_set(&p_info, 0, sizeof(p_info));
+    ipc_get_packet_info(g_ipc_ut_v6_hop_dst_route_ah_esp_pkt_1, sizeof(g_ipc_ut_v6_hop_dst_route_ah_esp_pkt_1), &p_info);
+    spi = 0x49507637;
+    UT_ASSERT(spi == p_info.spi);
+    UT_ASSERT(IPC_HDR_PROT_ESP == p_info.protocol);
+
+    kal_mem_set(&p_info, 0, sizeof(p_info));
+    ipc_get_packet_info(g_ipc_ut_v6_hop_dst_route_frag_ah_esp_pkt_1, sizeof(g_ipc_ut_v6_hop_dst_route_frag_ah_esp_pkt_1), &p_info);
+    spi = 0x49507737;
+    UT_ASSERT(spi == p_info.spi);
+    UT_ASSERT(IPC_HDR_PROT_ESP == p_info.protocol);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+void ipc_ut_prepare_esp_filter_pkt(kal_uint32 ipv4_cnt,
+                                    kal_uint32 dhcpv4_idx,
+                                    kal_bool dnsv4_only,
+                                    kal_bool v4hdr_exist,
+                                    kal_uint32 ipv6_cnt,
+                                    kal_uint32 dhcpv6_idx,
+                                    kal_bool dnsv6_only,
+                                    kal_bool v6hdr_exist,
+                                    kal_uint32 additional_bd_cnt,
+                                    kal_uint32 align_offset,
+                                    upcm_did **did_head,
+                                    upcm_did **did_tail,
+                                    kal_uint16 *ipv4_invalid_packet_len,
+                                    kal_uint16 *ipv6_invalid_packet_len,
+                                    kal_uint32 did_cnt,
+                                    kal_bool did_igr_enable)
+{
+    kal_uint32 total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32 idx;
+    upcm_did *curr_did;
+    upcm_did_si *curr_sit;
+    upcm_did_si *curr_si;
+    kal_uint32 curr_si_idx;
+    kal_uint32 pkt_start_si_idx;
+    kal_uint8 *packet_buf;
+    kal_uint32 packet_len;
+    kal_uint32 pkt_num;
+    kal_uint32 seg_num;
+
+    if (did_cnt != ipc_ut_alloc_did(did_cnt, did_head, did_tail)) {
+        IPC_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did *next_did;
+        kal_bool end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (curr_did = *did_head; curr_did && (end_of_list == KAL_FALSE);
+                curr_did = next_did) {
+            kal_uint32 i;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si *si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+
+    /* Set SIT to the first SIT in DID for data configuration */
+    curr_did = *did_head;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        switch (idx % 3) {
+            case 0 :
+                //packet_buf = ipc_ut_ipv4_tcp_empty_ack_packet;
+                //packet_len = sizeof(ipc_ut_ipv4_tcp_empty_ack_packet);
+                packet_buf = g_ipc_ut_v4_esp_pkt_1;
+                packet_len = sizeof(g_ipc_ut_v4_esp_pkt_1);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                g_cbk_pkt_send_cnt++;
+                break;
+            case 1 :
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+            case 2 :
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_7;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_7);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+            default :
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_6;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_6);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        if (ipv4_invalid_packet_len) {
+            if (ipv4_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv4_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv4_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+#if 1
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) { /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else { /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    IPC_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt++;
+            }
+        }
+#endif
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv4_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        packet_buf = ipc_ut_ipv6_ext0_dhcp_packet;
+        packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_packet);
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        // invalid len packet
+        if (ipv6_invalid_packet_len) {
+            if (ipv6_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv6_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv6_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) { /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else { /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    IPC_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt++;
+            }
+        }
+
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv6_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+}
+
+
+void ipc_ut_prepare_ra_filter_pkt(kal_uint32 ipv4_cnt,
+                                    kal_uint32 dhcpv4_idx,
+                                    kal_bool dnsv4_only,
+                                    kal_bool v4hdr_exist,
+                                    kal_uint32 ipv6_cnt,
+                                    kal_uint32 dhcpv6_idx,
+                                    kal_bool dnsv6_only,
+                                    kal_bool v6hdr_exist,
+                                    kal_uint32 additional_bd_cnt,
+                                    kal_uint32 align_offset,
+                                    upcm_did **did_head,
+                                    upcm_did **did_tail,
+                                    kal_uint16 *ipv4_invalid_packet_len,
+                                    kal_uint16 *ipv6_invalid_packet_len,
+                                    kal_uint32 did_cnt,
+                                    kal_bool did_igr_enable)
+{
+    kal_uint32 total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32 idx;
+    upcm_did *curr_did;
+    upcm_did_si *curr_sit;
+    upcm_did_si *curr_si;
+    kal_uint32 curr_si_idx;
+    kal_uint32 pkt_start_si_idx;
+    kal_uint8 *packet_buf;
+    kal_uint32 packet_len;
+    kal_uint32 pkt_num;
+    kal_uint32 seg_num;
+
+    if (did_cnt != ipc_ut_alloc_did(did_cnt, did_head, did_tail)) {
+        IPC_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did *next_did;
+        kal_bool end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (curr_did = *did_head; curr_did && (end_of_list == KAL_FALSE);
+                curr_did = next_did) {
+            kal_uint32 i;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si *si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+
+    /* Set SIT to the first SIT in DID for data configuration */
+    curr_did = *did_head;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        switch (idx % 3) {
+            case 0 :
+                //packet_buf = ipc_ut_ipv4_tcp_empty_ack_packet;
+                //packet_len = sizeof(ipc_ut_ipv4_tcp_empty_ack_packet);
+                packet_buf = g_ipc_ut_icmp_ra_pkt;
+                packet_len = sizeof(g_ipc_ut_icmp_ra_pkt);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                g_cbk_pkt_send_cnt++;
+                break;
+            case 1 :
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+            case 2 :
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_7;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_7);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+            default :
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_6;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_6);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                break;
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        if (ipv4_invalid_packet_len) {
+            if (ipv4_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv4_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv4_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+#if 1
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) { /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else { /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    IPC_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt++;
+            }
+        }
+#endif
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv4_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        packet_buf = g_ipc_ut_icmpv6_ra_pkt;
+        packet_len = sizeof(g_ipc_ut_icmpv6_ra_pkt);
+        g_cbk_pkt_send_cnt++;
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        // invalid len packet
+        if (ipv6_invalid_packet_len) {
+            if (ipv6_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len = (ipv6_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv6_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) { /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else { /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    IPC_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt++;
+            }
+        }
+
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv6_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+}
+
+kal_bool ipc_ut_esp_filter(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32 i = 0;
+    kal_uint32 ipv4_cnt = 0;
+    kal_uint32 ipv6_cnt = 0;
+    ipcore_upcm_pdn_bind_ind_struct *p_bind_req = NULL;
+    ipc_filter_rules_t rules = {0};
+    kal_int32 filter_id = 0;
+    kal_uint32 pdn_id = 0;
+    ipc_session_t *p_session = NULL;
+    kal_uint32 netif_id = IPC_UT_LHIF_NETID_START;
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    /* initialize before test & reset IPCORE  */
+    ipc_ut_init();
+    ASSERT(KAL_TRUE == ipc_reset());
+
+    /* netif attach */
+    ASSERT(KAL_TRUE == ipc_ut_fin_ack_filter_netif_attach());
+
+    /* IPv4 binding */
+    p_bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    p_bind_req->network_interface_id = IPC_UT_LHIF_NETID_START;
+    p_bind_req->pdn_id = IPC_UT_PDN_ID;
+    p_bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)p_bind_req);
+    free_local_para((local_para_struct * )p_bind_req);
+
+    /* Registered DL filter to filter out ESP packets*/
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_PDN_ID |
+                         IPC_FILTER_BY_SPI;
+    rules.protocol = IPC_HDR_PROT_ESP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.spi = 0x0000000a;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    filter_id= ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt);
+    ASSERT(0 == filter_id);
+
+    /* Simulate DL traffic to IPCore : PDN binding */
+    {
+        kal_uint32 did_cnt = 0;
+        upcm_did *did_head = NULL;
+        upcm_did *did_tail = NULL;
+        kal_uint32 alignment = 0;
+        kal_uint32 did_igr_bit = 0;
+        kal_uint32 free_cnt = 0;
+
+        for (alignment = 0; alignment < 4; alignment++)
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+        for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+                continue;
+            }
+
+            utDLOG("@[Binding] v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+            //g_cbk_pkt_recv_cnt = 0;
+            g_cbk_pkt_send_cnt = 0;
+            g_normal_cbk_pkt_recv_cnt = 0;
+
+            did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_prepare_esp_filter_pkt(ipv4_cnt,
+                                           0,
+                                           KAL_FALSE,
+                                           KAL_FALSE,
+                                           ipv6_cnt,
+                                           0,
+                                           KAL_FALSE,
+                                           KAL_FALSE,
+                                           0,
+                                           alignment,
+                                           &did_head,
+                                           &did_tail,
+                                           NULL,
+                                           NULL,
+                                           did_cnt,
+                                           did_igr_bit);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+            UT_ASSERT(g_cbk_pkt_send_cnt == g_normal_cbk_pkt_recv_cnt);
+            //UT_ASSERT(g_cbk_pkt_recv_cnt == g_cbk_pkt_send_cnt);
+            UT_ASSERT((ipc_ut_dl_callback_did_pkt_cnt + g_normal_cbk_pkt_recv_cnt) == (ipv4_cnt + ipv6_cnt));
+        }
+   }
+    ipc_dereg_filter(filter_id);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+
+}
+
+void ipc_ut_prepare_cust_filter_pkt(kal_uint32 ipv4_cnt,
+                                    kal_uint32 dhcpv4_idx,
+                                    kal_bool dnsv4_only,
+                                    kal_bool v4hdr_exist,
+                                    kal_uint32 ipv6_cnt,
+                                    kal_uint32 dhcpv6_idx,
+                                    kal_bool dnsv6_only,
+                                    kal_bool v6hdr_exist,
+                                    kal_uint32 additional_bd_cnt,
+                                    kal_uint32 align_offset,
+                                    upcm_did **did_head,
+                                    upcm_did **did_tail,
+                                    kal_uint16 *ipv4_invalid_packet_len,
+                                    kal_uint16 *ipv6_invalid_packet_len,
+                                    kal_uint32 did_cnt,
+                                    kal_bool did_igr_enable)
+{
+    kal_uint32 total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32 idx;
+    upcm_did *curr_did;
+    upcm_did_si *curr_sit;
+    upcm_did_si *curr_si;
+    kal_uint32 curr_si_idx;
+    kal_uint32 pkt_start_si_idx;
+    kal_uint8 *packet_buf;
+    kal_uint32 packet_len;
+    kal_uint32 pkt_num;
+    kal_uint32 seg_num;
+
+    if (did_cnt != ipc_ut_alloc_did(did_cnt, did_head, did_tail)) {
+        IPC_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did *next_did;
+        kal_bool end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (curr_did = *did_head; curr_did && (end_of_list == KAL_FALSE); curr_did = next_did) {
+            kal_uint32 i = 0;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si *si = &curr_sit[i];
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+
+    /* Set SIT to the first SIT in DID for data configuration */
+    curr_did = *did_head;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        switch (idx % 3) {
+            case 0:
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_5;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_5);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                g_cbk_pkt_send_cnt++;
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI)
+                ;
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_7;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_7);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI)
+                ;
+                break;
+            default:
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_6;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_6);
+                UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI)
+                ;
+                break;
+        }
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        if (ipv4_invalid_packet_len) {
+            if (ipv4_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len =
+                        (ipv4_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv4_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) { /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else { /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    IPC_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+                cont_loop_cnt++;
+            }
+        }
+
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv4_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        packet_buf = ipc_ut_ipv6_ext0_dhcp_packet;
+        packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_packet);
+
+#if (IPC_UT_GEN_INVALID_LEN_PKT)
+        // invalid len packet
+        if (ipv6_invalid_packet_len) {
+            if (ipv6_invalid_packet_len[idx] > packet_len) {
+                packet_buf = ipc_ut_invalid_len_ip_packet;
+                packet_len =
+                        (ipv6_invalid_packet_len[idx] > IPC_INVALID_MAX_PKT_LEN) ? IPC_INVALID_MAX_PKT_LEN : ipv6_invalid_packet_len[idx];
+            }
+        }
+#endif
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len) {
+                kal_uint32 current_copy_len;
+
+                if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) {
+                    /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else {
+                    /* Non latest SIT : copy partial of data */
+                    current_copy_len = (
+                            ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                    current_copy_len =
+                            (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num++;
+
+                if (copied_len >= packet_len) {
+                    IPC_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx++;
+                curr_si = &curr_sit[curr_si_idx];
+                cont_loop_cnt++;
+            }
+        }
+
+        if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+            kal_uint32 i;
+
+            for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                upcm_did_si *tmp_si = &curr_sit[i];
+                UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                seg_num--;
+            }
+        } else {
+            pkt_num++;
+        }
+    }
+
+    if (ipv6_cnt) {
+        UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+        UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+    }
+}
+
+kal_bool ipc_ut_cust_filter(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32 i = 0;
+    kal_uint32 ipv4_cnt = 0;
+    kal_uint32 ipv6_cnt = 0;
+    ipcore_upcm_pdn_bind_ind_struct *p_bind_req = NULL;
+    ipc_filter_rules_t rules = {0};
+    kal_int32 filter_id = 0;
+    kal_uint32 pdn_id = 0;
+    ipc_session_t *p_session = NULL;
+    kal_uint32 netif_id = IPC_UT_LHIF_NETID_START;
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    /* initialize before test & reset IPCORE  */
+    ipc_ut_init();
+    UT_ASSERT(KAL_TRUE == ipc_reset());
+
+    /* netif attach */
+    UT_ASSERT(KAL_TRUE == ipc_ut_fin_ack_filter_netif_attach());
+
+    /* IPv4 binding */
+    p_bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    p_bind_req->network_interface_id = IPC_UT_LHIF_NETID_START;
+    p_bind_req->pdn_id = IPC_UT_PDN_ID;
+    p_bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)p_bind_req);
+    free_local_para((local_para_struct * )p_bind_req);
+
+    /* Registered DL filter to filter out TCP SYN packets*/
+    rules.valid_fields = IPC_FILTER_BY_PDN_ID |
+                         IPC_FILTER_BY_PROTOCOL |
+                         IPC_FILTER_BY_TCP_FLAGS;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    rules.protocol = IPC_HDR_PROT_TCP;
+    rules.pdn_id = IPC_UT_PDN_ID;
+    rules.tcp_flags = IPC_HDR_TCP_FLAG_SYN;
+    rules.features = IPC_FILTER_FEATURE_CUST_FILTER;
+    rules.cust_cbk_func = ipc_ut_cust_filter_cbk;
+    ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_filter_info_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+
+    filter_id= ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt);
+    UT_ASSERT(0 == filter_id);
+
+    /* Simulate DL traffic to IPCore : PDN binding */
+    {
+        kal_uint32 did_cnt = 0;
+        upcm_did *did_head = NULL;
+        upcm_did *did_tail = NULL;
+        kal_uint32 alignment = 0;
+        kal_uint32 did_igr_bit = 0;
+        kal_uint32 free_cnt = 0;
+
+        for (alignment = 0; alignment < 4; alignment++)
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+        for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+                continue;
+            }
+
+            utDLOG("@[Binding] v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+            g_cbk_pkt_recv_cnt = 0;
+            g_cbk_pkt_send_cnt = 0;
+            g_normal_cbk_pkt_recv_cnt = 0;
+
+            did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_prepare_cust_filter_pkt(ipv4_cnt,
+                                           0,
+                                           KAL_FALSE,
+                                           KAL_FALSE,
+                                           ipv6_cnt,
+                                           0,
+                                           KAL_FALSE,
+                                           KAL_FALSE,
+                                           0,
+                                           alignment,
+                                           &did_head,
+                                           &did_tail,
+                                           NULL,
+                                           NULL,
+                                           did_cnt,
+                                           did_igr_bit);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+            UT_ASSERT(g_cbk_pkt_recv_cnt == g_cbk_pkt_send_cnt);
+            UT_ASSERT((ipc_ut_dl_callback_did_pkt_cnt + g_normal_cbk_pkt_recv_cnt) == (ipv4_cnt + ipv6_cnt));
+        }
+   }
+    ipc_dereg_filter(filter_id);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_pdn_sim_macro(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint8 sim_idx = 0;
+    kal_uint8 pdn_id = 0;
+
+    /* (sim_idx, pdn_id) = (0, 5) => 0000 0101 */
+    sim_idx = 0;
+    pdn_id = 5;
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x05 == pdn_id);
+    IPC_RETRIEVE_PROTOID_FROM_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x00 == sim_idx);
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x05 == pdn_id);
+    IPC_UNMASK_PROTOID_FROM_PDNID(pdn_id);
+    UT_ASSERT(0x05 == pdn_id);
+
+    /* (sim_idx, pdn_id) = (1, 5) => 0100 0101 */
+    sim_idx = 1;
+    pdn_id = 5;
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x45 == pdn_id);
+    IPC_RETRIEVE_PROTOID_FROM_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x01 == sim_idx);
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x45 == pdn_id);
+    IPC_UNMASK_PROTOID_FROM_PDNID(pdn_id);
+    UT_ASSERT(0x05 == pdn_id);
+
+    /* (sim_idx, pdn_id) = (2, 5) => 1000 0101 */
+    sim_idx = 2;
+    pdn_id = 5;
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x85 == pdn_id);
+    IPC_RETRIEVE_PROTOID_FROM_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x02 == sim_idx);
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x85 == pdn_id);
+    IPC_UNMASK_PROTOID_FROM_PDNID(pdn_id);
+    UT_ASSERT(0x05 == pdn_id);
+
+    /* (sim_idx, pdn_id) = (3, 5) => 1100 0101 */
+    sim_idx = 3;
+    pdn_id = 5;
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0xC5 == pdn_id);
+    IPC_RETRIEVE_PROTOID_FROM_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0x03 == sim_idx);
+    IPC_MASK_PROTOID_ON_PDNID(pdn_id, sim_idx);
+    UT_ASSERT(0xC5 == pdn_id);
+    IPC_UNMASK_PROTOID_FROM_PDNID(pdn_id);
+    UT_ASSERT(0x05 == pdn_id);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+static void ipc_ut_prepare_retry_queue_list(kal_uint32 ipv4_cnt,
+                                            kal_bool dnsv4_only,
+                                            kal_bool v4hdr_exist,
+                                            kal_uint32 ipv6_cnt,
+                                            kal_bool dnsv6_only,
+                                            kal_bool v6hdr_exist,
+                                            kal_uint32 additional_bd_cnt,
+                                            kal_uint32 align_offset,
+                                            upcm_did **did_head,
+                                            upcm_did **did_tail,
+                                            kal_uint32 did_cnt,
+                                            kal_bool did_igr_enable,
+                                            kal_uint32 did_flow)
+{
+    kal_uint32 total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32 idx = 0;
+    upcm_did *curr_did = NULL;
+    upcm_did_si *curr_sit = NULL;
+    upcm_did_si *curr_si = NULL;
+    kal_uint32 curr_si_idx = 0;
+    kal_uint32 pkt_start_si_idx = 0;
+    kal_uint8 *packet_buf = NULL;
+    kal_uint32 packet_len = 0;
+    kal_uint32 pkt_num = 0;
+    kal_uint32 seg_num = 0;
+    kal_uint32 flow = did_flow;
+
+    if (did_cnt != ipc_ut_alloc_did(did_cnt, did_head, did_tail)) {
+        IPC_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did *p_next_did = NULL;
+        kal_bool end_of_list = KAL_FALSE;
+        kal_uint32 i = 0;
+
+        for (curr_did = *did_head; (end_of_list == KAL_FALSE); curr_did = p_next_did) {
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+            p_next_did = UPCM_DID_GET_NEXT(curr_did);
+            end_of_list = (curr_did == *did_tail);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si *p_sit = &curr_sit[i];
+                UPCM_DID_SI_SET_OFFSET(p_sit, UPCM_DID_SI_GET_OFFSET(p_sit) + (align_offset % 4));
+            }
+            UPCM_DID_SET_FLOW(curr_did, ++flow);
+        }
+    }
+
+    {
+        upcm_did *p_next_did = NULL;
+        kal_bool end_of_list = KAL_FALSE;
+        kal_uint32 i = 0;
+        kal_uint32 cur_flow = 0;
+
+        for (curr_did = *did_head; (end_of_list == KAL_FALSE); curr_did = p_next_did) {
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+            p_next_did = UPCM_DID_GET_NEXT(curr_did);
+            end_of_list = (curr_did == *did_tail);
+            cur_flow = UPCM_DID_GET_FLOW(curr_did);
+
+            curr_si_idx = 0;
+            curr_si = &curr_sit[curr_si_idx];
+            pkt_num = 0;
+            seg_num = 0;
+
+            switch (cur_flow % 2) {
+                case 0 :
+                    packet_buf = g_ipc_ut_v4_esp_pkt_1;
+                    packet_len = sizeof(g_ipc_ut_v4_esp_pkt_1);
+                    UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                    break;
+                case 1 :
+                default :
+                    packet_buf = ipc_ut_ipv6_ext0_dhcp_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_packet);
+                    UPCM_DID_SET_SW_CTRL_FIELD(curr_did, IPC_UT_DL_EBI);
+                    break;
+            }
+
+            {
+                kal_uint32 copied_len = 0;
+                kal_uint32 cont_loop_cnt = 0;
+                kal_uint32 si_offset = 0;
+
+                pkt_start_si_idx = curr_si_idx;
+                while (copied_len < packet_len) {
+                    kal_uint32 current_copy_len = 0;
+
+                    if (curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) {
+                        /* Latest SIT : copy all remaining data */
+                        current_copy_len = packet_len - copied_len;
+                    } else {
+                        /* Non latest SIT : copy partial of data */
+                        current_copy_len = (
+                                ((align_offset > 0) || (cont_loop_cnt % 2)) ? (idx + cont_loop_cnt) : 0) % (packet_len - copied_len);
+                        current_copy_len =
+                                (current_copy_len == 0) ? 1 : current_copy_len;
+                    }
+
+                    /* No buffer is allocated and we need to set its buffer to static template */
+                    si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                    UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                    UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                    copied_len += current_copy_len;
+                    seg_num++;
+
+                    if (copied_len >= packet_len) {
+                        IPC_ASSERT(copied_len == packet_len);
+                        UPCM_DID_SI_SET_EOL(curr_si);
+                    }
+
+                    /* Get next SI in list */
+                    curr_si_idx++;
+                    curr_si = &curr_sit[curr_si_idx];
+                    cont_loop_cnt++;
+                }
+            }
+
+            if ((did_igr_enable) && (1 == ipc_ut_did_packet_igr_s[idx])) {
+                kal_uint32 i = 0;
+
+                for (i = pkt_start_si_idx; i < curr_si_idx; i++) {
+                    upcm_did_si *tmp_si = &curr_sit[i];
+                    UPCM_DID_SI_SET_HIF_TYPE(tmp_si, IPC_SI_HIF_TYPE_IGR);
+                    seg_num--;
+                }
+            } else {
+                pkt_num++;
+            }
+
+            UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+            UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+        }
+    }
+
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+    return;
+}
+
+kal_bool ipc_ut_dl_cbk_retry_did(void *context, upcm_did *did)
+{
+    upcm_did *p_next_did = NULL;
+    upcm_did *p_curr_did = did;
+    kal_uint32 i = 0;
+
+    UT_ASSERT(NULL != did);
+
+    ipc_ut_dl_callback_did_cnt ++;
+    ipc_ut_dl_callback_did_pkt_cnt += UPCM_DID_GET_PKT_NUM(did);
+
+    if ((2 == UPCM_DID_GET_FLOW(p_curr_did)) && g_is_block) {
+        g_is_block = KAL_FALSE;
+
+        if (KAL_FALSE == g_is_insert) {
+            upcm_did *did_head = NULL;
+            upcm_did *did_tail = NULL;
+            ipc_ut_prepare_retry_queue_list(1, KAL_FALSE, KAL_FALSE, 1, KAL_FALSE, KAL_FALSE, 0, 0, &did_head, &did_tail, 2, KAL_FALSE, 6);
+            ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+            g_is_insert = KAL_TRUE;
+        }
+
+        return KAL_FALSE;
+    } else {
+        g_is_block = KAL_TRUE;
+    }
+
+    UT_ASSERT(g_current_flow < UPCM_DID_GET_FLOW(p_curr_did));
+    g_current_flow = UPCM_DID_GET_FLOW(p_curr_did);
+    return KAL_TRUE;
+}
+
+static kal_bool ipc_ut_retry_queue_netif_attach(void) {
+    ipc_conf_t config = {0};
+    ipc_handle_t p_handle = NULL;
+    kal_bool ret = KAL_TRUE;
+
+    config.module_id = MOD_IPCORE;
+    config.netif_id = IPC_UT_LHIF_NETID_START;
+    config.features = 0;
+    config.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    config.ipc_dlink_did_cb_t = ipc_ut_dl_cbk_retry_did;
+    config.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+
+    UT_ASSERT(KAL_TRUE == ipc_attach(&config, &p_handle));
+    UT_ASSERT(NULL != p_handle);
+    utDLOG("netif id = %d attach successfully", config.netif_id);
+
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_did_retry_put_head_queue(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32 i = 0;
+    kal_uint32 ipv4_cnt = 0;
+    kal_uint32 ipv6_cnt = 0;
+    ipcore_upcm_pdn_bind_ind_struct *p_bind_req = NULL;
+    ipc_filter_rules_t rules = {0};
+    kal_int32 filter_id = 0;
+    kal_uint32 pdn_id = 0;
+    ipc_session_t *p_session = NULL;
+    kal_uint32 netif_id = IPC_UT_LHIF_NETID_START;
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    /* initialize before test & reset IPCORE  */
+    ipc_ut_init();
+    ASSERT(KAL_TRUE == ipc_reset());
+
+    /* netif attach */
+    ASSERT(KAL_TRUE == ipc_ut_retry_queue_netif_attach());
+
+    /* IPv4 binding */
+    p_bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    p_bind_req->network_interface_id = IPC_UT_LHIF_NETID_START;
+    p_bind_req->pdn_id = IPC_UT_PDN_ID;
+    p_bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)p_bind_req);
+    free_local_para((local_para_struct * )p_bind_req);
+
+    /* Simulate DL traffic to IPCore : PDN binding */
+    {
+        kal_uint32 did_cnt = 0;
+        upcm_did *did_head = NULL;
+        upcm_did *did_tail = NULL;
+        kal_uint32 alignment = 0;
+        kal_uint32 did_igr_bit = 0;
+        kal_uint32 free_cnt = 0;
+
+        for (alignment = 0; alignment < 4; alignment++)
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+        for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+                continue;
+            }
+
+            utDLOG("@[Binding] v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+            g_cbk_pkt_send_cnt = 0;
+            g_normal_cbk_pkt_recv_cnt = 0;
+
+            did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 2 : 3;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+
+            ipc_ut_prepare_retry_queue_list(ipv4_cnt, KAL_FALSE, KAL_FALSE, ipv6_cnt, KAL_FALSE, KAL_FALSE, 0, alignment, &did_head, &did_tail, did_cnt, did_igr_bit, 0);
+            g_current_flow = 0;
+            g_is_insert = KAL_FALSE;
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+            kal_sleep_task(IPC_UT_MSG_LATENCY);
+        }
+    }
+    ipc_dereg_filter(filter_id);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+void ipc_ut_prepare_ipc_ut_ul_udp_igmp_filter(kal_bool allValidIpPkt,
+                                              kal_uint32 ipv4_tcp_cnt,
+                                              kal_uint32 dhcpv4_idx,
+                                              kal_uint32 ipv4_udp_cnt,
+                                              kal_uint32 dhcpv6_idx,
+                                              kal_uint32 *p_head_idx,
+                                              kal_uint32 *p_tail_idx,
+                                              LHIF_QUEUE_TYPE *q_type,
+                                              kal_uint32 netif_id,
+                                              kal_uint8 proto_idx,
+                                              kal_uint8 test_stage)
+{
+    kal_uint32          total_cnt = ipv4_tcp_cnt + ipv4_udp_cnt;
+    kal_uint32          idx = 0;
+    kal_uint32          curr_meta_idx = 0;
+    lhif_meta_tbl_t    *curr_meta = NULL;
+    kal_uint8          *packet_buf = NULL;
+    kal_uint32          packet_len = 0;
+    kal_uint32          netif_id_prefix = (netif_id & 0xFFFFFF00);
+
+    if (total_cnt != ipc_ut_alloc_meta(IPC_UT_LHIF_META_AP0, total_cnt, p_head_idx, p_tail_idx)) {
+        IPC_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    *q_type = LHIF_HWQ_AP_UL_Q0;
+    curr_meta_idx = *p_head_idx;
+
+    for (idx = 0; idx < total_cnt; idx++) {
+        curr_meta = &ipc_ut_meta_tbl_s[curr_meta_idx];
+        curr_meta->net_type = ((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS;
+        curr_meta->channel_id = netif_id & 0x0000001F;
+        curr_meta->mr = IPC_HPC_MR_UNKNOWN;
+
+        switch (idx % 6) {
+            case 0:
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                g_chk_pkt_cnt++;
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_3;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_2);
+                break;
+            case 2:
+                packet_buf = g_ipc_ut_igmp_pkt_1;
+                packet_len = sizeof(g_ipc_ut_igmp_pkt_1);
+                g_chk_pkt_cnt++;
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv6_tcp_fin_ack_packet;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_fin_ack_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv6_dhcp_ul_packet;
+                packet_len = sizeof(ipc_ut_ipv6_dhcp_ul_packet);
+                g_chk_pkt_cnt++;
+                break;
+            case 5:
+                packet_buf = ipc_ut_ipv6_udp_zero_checksum_packet;
+                packet_len = sizeof(ipc_ut_ipv6_udp_zero_checksum_packet);
+                g_chk_pkt_cnt++;
+                break;
+            default:
+                packet_buf = ipc_ut_ipv4_ul_syn_window_scale_packets_3;
+                packet_len = sizeof(ipc_ut_ipv4_ul_syn_window_scale_packets_3);
+                break;
+        }
+
+        kal_mem_cpy(curr_meta->vrb_addr, packet_buf, packet_len);
+        curr_meta->length = packet_len;
+
+        curr_meta_idx++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+    return;
+}
+
+kal_bool ipc_ut_ul_udp_igmp_filter(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32                          blocked_cnt = 0;
+    ipc_ut_netif_t                     *net = NULL;
+    kal_uint32                          netif_id = IPC_NETIF_ID_ETH_BEGIN;
+    kal_bool                            result = KAL_FALSE;
+    kal_uint32                          idx = 0;
+    kal_uint8                           proto_idx[] = {0, 1};
+    ipcore_upcm_pdn_bind_ind_struct    *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct  *deact_req = NULL;
+    ilm_struct                          ilm = {0};
+    kal_uint8                           test_stage = 0;
+    ipc_session_t                      *p_session = NULL;
+    ipc_filter_rules_t                  rules = {0};
+    kal_int32                           filter_id = 0;
+    kal_uint32                          pdn_id = 0;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_NETIF_ID_ETH_BEGIN;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++) {
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Simulate UL traffic to IPCore : Before PDN binding, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  total_cnt;
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  head_idx;
+            kal_uint32  tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+
+            test_stage = IPC_UT_STAGE_BEFORE_BINDING;
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+                    continue;
+                }
+
+                utDLOG("@ [Before Bind] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                ipc_ut_prepare_ipc_ut_ul_udp_igmp_filter(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (0 != ipc_ut_ul_meta_non_igr_cnt) ) {
+                    utELOG("UL META is forwarded before PDN binding! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM + idx, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE)
+        {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+        free_local_para((local_para_struct *)bind_req);
+
+        utDLOG("PDN binding successfull");
+
+        /* Registered uplink filter */
+        UT_ASSERT(KAL_TRUE == msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_IPCORE_UDP_IGMP_REG_FILTER_REQ, NULL, NULL));
+
+        /* Simulate UL traffic to IPCore : All GPDs should be forward to UL callback regardless of IP types (IPv4/IPv6) */
+        {
+            kal_uint32  total_cnt;
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt = 0;
+            kal_uint32  head_idx;
+            kal_uint32  tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+
+            test_stage = IPC_UT_STAGE_BINDING;
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+            {
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+                    continue;
+                }
+
+                utDLOG("@ [Binded] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                g_chk_pkt_cnt = 0;
+                ipc_ut_prepare_ipc_ut_ul_udp_igmp_filter(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                UT_ASSERT(total_cnt == ipc_ut_ul_meta_cnt);
+                UT_ASSERT(g_chk_pkt_cnt == g_ipc_ut_igr_meta_cnt);
+            }
+        }
+
+        UT_ASSERT(KAL_TRUE == msg_send6(MOD_NIL, MOD_IPCORE, IPCORE_SAP, MSG_ID_IPCORE_UDP_IGMP_DEREG_FILTER_REQ, NULL, NULL));
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+
+        /* Simulate UL traffic to IPCore : After PDN deactivation, all GPDs should be silently dropped by IPCore and NO callback is triggered */
+        {
+            kal_uint32  total_cnt;
+            kal_uint32  ipv4_cnt;
+            kal_uint32  ipv6_cnt;
+            kal_uint32  head_idx;
+            kal_uint32  tail_idx;
+            LHIF_QUEUE_TYPE q_type;
+
+            test_stage = IPC_UT_STAGE_UNBINDING;
+            for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+            for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+
+                if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+                    continue;
+                }
+
+                utDLOG("@ [Deactivated] proto_idx(%d),v4_cnt(%d),v6_cnt(%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+
+                total_cnt = ipv4_cnt + ipv6_cnt;
+                ipc_ut_prepare_ipc_ut_ul_udp_igmp_filter(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, idx, test_stage);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_ul_info();
+
+                ipc_meta_uplink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+                if ( (total_cnt != ipc_ut_ul_meta_cnt) ||
+                     (0 != ipc_ut_ul_meta_non_igr_cnt) ) {
+                    utELOG("UL META is forwarded after PDN deactivation! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, ipv4_cnt, ipv6_cnt);
+                    ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+                    return KAL_FALSE;
+                }
+            }
+        }
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+void ipc_ut_prepare_dl_did_list_ipv6ra(
+        kal_uint32 pkt_cnt,
+        kal_uint32 align_offset,
+        upcm_did   **did_head,
+        upcm_did   **did_tail,
+        kal_uint32 did_cnt)
+{
+    kal_uint32          total_cnt = pkt_cnt;
+    kal_uint32          idx;
+    upcm_did           *curr_did;
+    upcm_did_si        *curr_sit;
+    upcm_did_si        *curr_si;
+    kal_uint32          curr_si_idx;
+    kal_uint32          pkt_start_si_idx;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          pkt_num;
+    kal_uint32          seg_num;
+    kal_uint8           per_pkt_max_sit_num = 10; /* one DID max packet number will be 7. one DID has 62 SIT entries */
+
+    if (did_cnt != ipc_ut_alloc_did(
+                        did_cnt,
+                        did_head,
+                        did_tail)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did   *next_did;
+        kal_bool    end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (   curr_did = *did_head ;
+                curr_did && (end_of_list == KAL_FALSE) ;
+                curr_did = next_did)
+        {
+            kal_uint32  i;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si    *si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+    /*must have ra packet , test included to have other packets based upon ipv6 packet count*/
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+    for (idx = 0; idx < pkt_cnt; idx++) {
+        switch(idx) {
+            case 0:
+                packet_buf = g_ipc_ut_icmpv6_ra_pkt;
+                packet_len = sizeof(g_ipc_ut_icmpv6_ra_pkt);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_tcp_syn_packet;
+                packet_len = sizeof(ipc_ut_ipv6_tcp_syn_packet);
+                break;
+
+        }
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len)
+            {
+                kal_uint32 current_copy_len;
+
+                if ((curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) || (cont_loop_cnt == per_pkt_max_sit_num-1))
+                {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else
+                {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    UT_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt ++;
+            }
+        }
+        pkt_num ++;
+
+    }
+
+    UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+    UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+}
+
+kal_bool ipc_ut_dl_filter_ra_pkt_did(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t *net;
+    kal_uint32 netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool result;
+    kal_uint8 proto_idx[] = {0, 1};
+    kal_uint32 idx;
+    kal_uint32 gpd_remain_cnt_ul, gpd_remain_cnt_dl, did_remain_cnt;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+#if (IPC_IPV6_RA_WORKAROUND == 1)    
+    d2cm_ipcore_info_ind_struct *d2cm_ind = NULL;
+#endif
+    ilm_struct ilm = {0};
+
+    /* init before test */
+    ipc_ut_init();
+
+    /*
+     * Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * ipc_attach()
+     */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did_ra;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* no BINDING */
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++){
+        kal_uint32 pkt_cnt;
+        kal_uint32 did_cnt;
+        upcm_did *did_head;
+        upcm_did *did_tail;
+        kal_uint32 alignment;
+        kal_uint8 expected_pkt_cnt = 0;
+
+        /*Store GPD remain cnt */
+        gpd_remain_cnt_dl = qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+
+        for (alignment = 0 ; alignment < 4 ; alignment ++)
+        for (pkt_cnt = 1; pkt_cnt <= 2; pkt_cnt++) {
+
+            did_cnt = 1;
+            expected_pkt_cnt = 0;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_reset_ul_info();
+
+            /*Store DID remain cnt */
+            did_remain_cnt = upcm_did_get_buff_remain_num();
+
+            /* prepare a DID of TCP RST */
+            ipc_ut_prepare_dl_did_list_ipv6ra(pkt_cnt, alignment, &did_head, &did_tail, did_cnt);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID on unbind condition*/
+            ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx); //0 for SIM1
+            if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                utELOG("DL DID is forwarded on PDN unbind!\r\n");
+                return KAL_FALSE;
+            }
+
+            /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+            bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+            bind_req->network_interface_id = net->conf.netif_id;
+            bind_req->pdn_id = IPC_UT_PDN_ID;
+            bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_UPCM + idx;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+            ilm.local_para_ptr = (local_para_struct *)bind_req;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)bind_req);
+
+#if (IPC_IPV6_RA_WORKAROUND == 1)   
+            /* Send D2CM message to flush RA */
+            d2cm_ind = (d2cm_ipcore_info_ind_struct *)construct_local_para(sizeof(d2cm_ipcore_info_ind_struct), TD_RESET);
+            /* Be careful that D2CM only proivde NETIF ID from AP view (start from 0)
+             * IPCORE will translate netif ID by adding prefix IPC_NETIF_ID_LHIF_BEGIN
+             */
+            d2cm_ind->netif_id = IPC_UT_NETID_START;
+            d2cm_ind->keep_ra = KAL_TRUE;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_NIL;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_D2CM_IPCORE_INFO_IND;
+            ilm.local_para_ptr = (local_para_struct *)d2cm_ind;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)d2cm_ind);
+            
+#endif
+            /* expected DL pkt cnt should be
+             * pkt 1 is of ICMPv6 RA packet, generate 1 DL GPD
+             * pkt 2 is of TCP pkt , generate 0 DL GPD
+             */
+            if ( pkt_cnt >= 1) {
+                expected_pkt_cnt += 1;
+            }
+
+            if (ipc_ut_dl_callback_did_pkt_cnt != expected_pkt_cnt) {
+                utELOG("wrong expected count!\r\n");
+                return KAL_FALSE;
+            }
+#if (IPC_IPV6_RA_WORKAROUND == 1)
+            /* IPCORE should keep RA packet after flushing RA to AP */
+            if((gpd_remain_cnt_dl-1) != qbm_get_buff_remain_num(QBM_TYPE_NET_DL) ){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+#else
+            if(gpd_remain_cnt_dl != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+#endif
+            if(did_remain_cnt != upcm_did_get_buff_remain_num()){
+                utELOG("wrong expected DID count!\r\n");
+                return KAL_FALSE;
+            }
+
+#if (IPC_IPV6_RA_WORKAROUND == 1)   
+            /* Reset DL counts */
+            ipc_ut_reset_dl_callback_info();
+
+            /* Send D2CM message to flush RA */
+            d2cm_ind = (d2cm_ipcore_info_ind_struct *)construct_local_para(sizeof(d2cm_ipcore_info_ind_struct), TD_RESET);
+            /* Be careful that D2CM only proivde NETIF ID from AP view (start from 0)
+             * IPCORE will translate netif ID by adding prefix IPC_NETIF_ID_LHIF_BEGIN
+             */
+            d2cm_ind->netif_id = IPC_UT_NETID_START;
+            d2cm_ind->keep_ra = KAL_FALSE;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_NIL;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_D2CM_IPCORE_INFO_IND;
+            ilm.local_para_ptr = (local_para_struct *)d2cm_ind;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)d2cm_ind);
+
+            /* No RA packets should be stored in IPCORE */
+            if(gpd_remain_cnt_dl != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+            /* IPCORE should flush RA to NETIF */
+            if (ipc_ut_dl_callback_did_pkt_cnt != 1) {
+                utELOG("wrong expected count!\r\n");
+                return KAL_FALSE;
+            }
+            if(did_remain_cnt != upcm_did_get_buff_remain_num()){
+                utELOG("wrong expected DID count!\r\n");
+                return KAL_FALSE;
+            }
+#endif
+            /* PDN deactivation. */
+            deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+            deact_req->pdn_id = IPC_UT_PDN_ID;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_UPCM + idx;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+            ilm.local_para_ptr = (local_para_struct *)deact_req;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)deact_req);
+        }
+    }
+
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_filter_ra_pkt_did_w_dynamic_q(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t *net;
+    kal_uint32 netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool result;
+    kal_uint8 proto_idx[] = {0, 1};
+    kal_uint32 idx;
+    kal_uint32 gpd_remain_cnt_ul, gpd_remain_cnt_dl, did_remain_cnt;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    ipc_lhifcore_q_mapping_msg_t *dynamic_q_rsp = NULL;
+#if (IPC_IPV6_RA_WORKAROUND == 1)    
+    d2cm_ipcore_info_ind_struct *d2cm_ind = NULL;
+#endif
+    ilm_struct ilm = {0};
+
+    /* init before test */
+    ipc_ut_init();
+
+    /*
+     * Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * ipc_attach()
+     */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did_ra;
+    net->conf.features = IPC_F_DYNAMIC_Q_MAPPING;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* no BINDING */
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++){
+        kal_uint32 pkt_cnt;
+        kal_uint32 did_cnt;
+        upcm_did *did_head;
+        upcm_did *did_tail;
+        kal_uint32 alignment;
+        kal_uint8 expected_pkt_cnt = 0;
+
+        /*Store GPD remain cnt */
+        gpd_remain_cnt_dl = qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+
+        for (alignment = 0 ; alignment < 4 ; alignment ++)
+        for (pkt_cnt = 1; pkt_cnt <= 2; pkt_cnt++) {
+
+            did_cnt = 1;
+            expected_pkt_cnt = 0;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_reset_ul_info();
+
+            /*Store DID remain cnt */
+            did_remain_cnt = upcm_did_get_buff_remain_num();
+
+            /* prepare a DID of TCP RST */
+            ipc_ut_prepare_dl_did_list_ipv6ra(pkt_cnt, alignment, &did_head, &did_tail, did_cnt);
+
+            /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+            bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+            bind_req->network_interface_id = net->conf.netif_id;
+            bind_req->pdn_id = IPC_UT_PDN_ID;
+            bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_UPCM + idx;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+            ilm.local_para_ptr = (local_para_struct *)bind_req;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID on unbind condition*/
+            ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx); //0 for SIM1
+            if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                utELOG("DL DID is forwarded on PDN unbind!\r\n");
+                return KAL_FALSE;
+            }
+
+            /* Send dynamic queue mapping response to IPCore. */
+            dynamic_q_rsp = (ipc_lhifcore_q_mapping_msg_t *)construct_local_para(sizeof(ipc_lhifcore_q_mapping_msg_t), TD_RESET);
+            kal_mem_cpy(&(dynamic_q_rsp->bind_ind), bind_req, sizeof(ipcore_upcm_pdn_bind_ind_struct));
+            dynamic_q_rsp->netif_features = net->conf.features;
+            dynamic_q_rsp->callback_context = net->conf.callback_context;
+            dynamic_q_rsp->bind_src_mod_id = net->conf.module_id;
+            dynamic_q_rsp->netif_type = IPC_NETIF_TYPE_NORMAL;
+            dynamic_q_rsp->result = KAL_TRUE;
+
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_LHIFCORE;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_IPCORE_LHIFCORE_QUEUE_MAPPING_RSP;
+            ilm.local_para_ptr = (local_para_struct *)dynamic_q_rsp;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)bind_req);
+            free_local_para((local_para_struct *)dynamic_q_rsp);
+
+#if (IPC_IPV6_RA_WORKAROUND == 1)   
+            /* Send D2CM message to flush RA */
+            d2cm_ind = (d2cm_ipcore_info_ind_struct *)construct_local_para(sizeof(d2cm_ipcore_info_ind_struct), TD_RESET);
+            /* Be careful that D2CM only proivde NETIF ID from AP view (start from 0)
+             * IPCORE will translate netif ID by adding prefix IPC_NETIF_ID_LHIF_BEGIN
+             */
+            d2cm_ind->netif_id = IPC_UT_NETID_START;
+            d2cm_ind->keep_ra = KAL_TRUE;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_NIL;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_D2CM_IPCORE_INFO_IND;
+            ilm.local_para_ptr = (local_para_struct *)d2cm_ind;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)d2cm_ind);
+                        
+#endif
+
+            /* expected DL pkt cnt should be
+             * pkt 1 is of ICMPv6 RA packet, generate 1 DL GPD
+             * pkt 2 is of TCP pkt , generate 0 DL GPD
+             */
+            if ( pkt_cnt >= 1) {
+                expected_pkt_cnt += 1;
+            }
+
+            if (ipc_ut_dl_callback_did_pkt_cnt != expected_pkt_cnt) {
+                utELOG("wrong expected count!\r\n");
+                return KAL_FALSE;
+            }
+            
+#if (IPC_IPV6_RA_WORKAROUND == 1)
+            /* IPCORE should keep RA packet after flushing RA to AP */
+            if((gpd_remain_cnt_dl-1) != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+#else
+            if(gpd_remain_cnt_dl != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+#endif
+
+            if(did_remain_cnt != upcm_did_get_buff_remain_num()){
+                utELOG("wrong expected DID count!\r\n");
+                return KAL_FALSE;
+            }
+
+#if (IPC_IPV6_RA_WORKAROUND == 1)   
+            /* Reset DL counts */
+            ipc_ut_reset_dl_callback_info();
+
+            /* Send D2CM message to flush RA */
+            d2cm_ind = (d2cm_ipcore_info_ind_struct *)construct_local_para(sizeof(d2cm_ipcore_info_ind_struct), TD_RESET);
+            /* Be careful that D2CM only proivde NETIF ID from AP view (start from 0)
+             * IPCORE will translate netif ID by adding prefix IPC_NETIF_ID_LHIF_BEGIN
+             */
+            d2cm_ind->netif_id = IPC_UT_NETID_START;
+            d2cm_ind->keep_ra = KAL_FALSE;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_NIL;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_D2CM_IPCORE_INFO_IND;
+            ilm.local_para_ptr = (local_para_struct *)d2cm_ind;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)d2cm_ind);
+
+            /* No RA packets should be stored in IPCORE */
+            if(gpd_remain_cnt_dl != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+            /* IPCORE should flush RA to NETIF */
+            if (ipc_ut_dl_callback_did_pkt_cnt != 1) {
+                utELOG("wrong expected count!\r\n");
+                return KAL_FALSE;
+            }
+            if(did_remain_cnt != upcm_did_get_buff_remain_num()){
+                utELOG("wrong expected DID count!\r\n");
+                return KAL_FALSE;
+            }
+#endif
+
+            /* PDN deactivation. */
+            deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+            deact_req->pdn_id = IPC_UT_PDN_ID;
+
+            ipc_ut_msg_reset(NULL, 0, NULL, 0);
+            ilm.src_mod_id = MOD_UPCM + idx;
+            ilm.dest_mod_id = MOD_IPCORE;
+            ilm.sap_id = IPCORE_SAP;
+            ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+            ilm.local_para_ptr = (local_para_struct *)deact_req;
+            ilm.peer_buff_ptr = NULL;
+            ipc_on_ilm(&ilm);
+            free_local_para((local_para_struct *)deact_req);
+        }
+    }
+
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+void ipc_ut_notify_l2(kal_uint32 unknown_header_num,
+                      kal_uint16 begin_cntl,
+                      kal_uint16 end_cntl,
+                      kal_uint16 rb_idx,
+                      kal_uint16 protocol_idx)
+{
+    g_ut_unk_hdr_stat_recv[protocol_idx][rb_idx].unk_hdr_cnt = unknown_header_num;
+    g_ut_unk_hdr_stat_recv[protocol_idx][rb_idx].begin_cntl = begin_cntl;
+    g_ut_unk_hdr_stat_recv[protocol_idx][rb_idx].end_cntl = end_cntl;
+    g_ut_unk_hdr_stat_recv[protocol_idx][rb_idx].is_valid = KAL_TRUE;
+}
+
+void ipc_ut_prepare_dl_meta_list_with_statistics(kal_bool allValidIpPkt,
+                                                 kal_uint32 ipv4_cnt,
+                                                 kal_uint32 dhcpv4_idx,
+                                                 kal_uint32 ipv6_cnt,
+                                                 kal_uint32 dhcpv6_idx,
+                                                 kal_uint32 *p_head_idx,
+                                                 kal_uint32 *p_tail_idx,
+                                                 ipfc_dl_filter_queue_type *q_type,
+                                                 kal_uint32 netif_id,
+                                                 kal_uint8 match_result,
+                                                 kal_uint8 sim_idx,
+                                                 kal_uint8 *v4_cntl_begin,
+                                                 kal_uint8 *v6_cntl_begin,
+                                                 kal_uint8 *v4_cntl_end,
+                                                 kal_uint8 *v6_cntl_end)
+{
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx;
+    kal_uint32          curr_meta_idx;
+    ipf_dl_meta         *curr_meta;
+    kal_uint8           *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          netif_id_prefix = (netif_id & 0xFFFFFF00);
+    kal_uint8           meta_cntl = 0;
+
+    if (total_cnt != ipc_ut_alloc_meta(IPC_UT_IPF_DL_0, total_cnt, p_head_idx, p_tail_idx)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    *q_type = IPFC_META_QUEUE_DL;
+    curr_meta_idx = *p_head_idx;
+    curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+    meta_cntl = 0;
+    curr_meta->count = 0;
+    *v4_cntl_begin = 0;
+    *v4_cntl_end = 0;
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+        meta_cntl++;
+        curr_meta->count = meta_cntl;
+        curr_meta->rbid = 4;
+        curr_meta->channel_id = ((((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS) <<8 )
+                            |(netif_id & 0x000000FF) ;
+
+        switch (idx) {
+            case 0:
+            case 1:
+                packet_buf = ipc_ut_non_ip_packet;
+                packet_len = sizeof(ipc_ut_non_ip_packet);
+                g_unk_pkt_v4_cnt ++;
+                if (0 == *v4_cntl_begin) {
+                    *v4_cntl_begin = curr_meta->count;
+                }
+                *v4_cntl_end = curr_meta->count;
+                break;
+            default:
+                packet_buf = ipc_ut_ipv4_dns_packet;
+                packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                break;
+        }
+
+        kal_mem_cpy((kal_uint8*)curr_meta->addr, packet_buf, packet_len);
+        curr_meta->len = packet_len;
+        curr_meta->ip = 0;
+
+        /* Fill Match index (don't care value)
+         * we assgin the same value as ip type. it will be reused for querey filter id.
+         */
+        curr_meta->match_idx = 0;
+        curr_meta->mr = (match_result & 0x07);
+        curr_meta->pdn_sim_id = IPC_UT_PDN_ID;
+        IPC_MASK_PROTOID_ON_PDNID(curr_meta->pdn_sim_id, sim_idx);
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+    curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+    meta_cntl = 0;
+    curr_meta->count = 0;
+    *v6_cntl_begin = 0;
+    *v6_cntl_end = 0;
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+        meta_cntl++;
+        curr_meta->count = meta_cntl;
+        curr_meta->rbid = 6;
+        curr_meta->channel_id = ((((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS) <<8 )
+                            |(netif_id & 0x000000FF) ;
+
+        switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_non_ip_packet;
+                packet_len = sizeof(ipc_ut_non_ip_packet);
+                g_unk_pkt_v6_cnt++;
+                if (0 == *v6_cntl_begin) {
+                    *v6_cntl_begin = curr_meta->count;
+                }
+                *v6_cntl_end = curr_meta->count;
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_mdns_packet;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                break;
+        }
+
+        kal_mem_cpy((kal_uint8*)curr_meta->addr, packet_buf, packet_len);
+        curr_meta->len = packet_len;
+        curr_meta->ip = 1;
+
+        /* Fill Match index (don't care value)
+         * we assgin the same value as ip type. it will be reused for querey filter id.
+         */
+        curr_meta->match_idx = 1;
+        curr_meta->mr = (match_result & 0x07);
+        curr_meta->pdn_sim_id = IPC_UT_PDN_ID;
+        IPC_MASK_PROTOID_ON_PDNID(curr_meta->pdn_sim_id, sim_idx);
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+}
+
+kal_bool ipc_ut_dl_filter_fragments(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint32 i = 0;
+    kal_uint32 ipv4_cnt = 0;
+    kal_uint32 ipv6_cnt = 0;
+    ipcore_upcm_pdn_bind_ind_struct *p_bind_req = NULL;
+    ipc_filter_rules_t rules = {0};
+    kal_int32 filter_id = 0;
+    kal_uint32 pdn_id = 0;
+    ipc_session_t *p_session = NULL;
+    kal_uint32 netif_id = IPC_UT_LHIF_NETID_START;
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+    ipc_conf_t config = {0};
+    ipc_handle_t p_handle = NULL;
+    kal_bool ret = KAL_TRUE;
+
+    /* initialize before test & reset IPCORE  */
+    ipc_ut_init();
+    ASSERT(KAL_TRUE == ipc_reset());
+
+    /* netif attach */
+    config.module_id = MOD_IPCORE;
+    config.netif_id = IPC_UT_LHIF_NETID_START;
+    config.features = 0;
+    config.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    config.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    config.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+
+    UT_ASSERT(KAL_TRUE == ipc_attach(&config, &p_handle));
+    UT_ASSERT(NULL != p_handle);
+    utDLOG("netif id = %d attach successfully", config.netif_id);
+
+    /* IPv4 binding */
+    p_bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    p_bind_req->network_interface_id = IPC_UT_LHIF_NETID_START;
+    p_bind_req->pdn_id = IPC_UT_PDN_ID;
+    p_bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)p_bind_req);
+    free_local_para((local_para_struct * )p_bind_req);
+
+    ipc_ut_prepare_fragments_and_send(IPC_UT_PDN_ID, 0);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+
+kal_bool ipc_ut_meta_downlink_with_statistics(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    ipc_ut_netif_t   *net;
+    kal_uint32        netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool          result;
+    ilm_struct        ilm;
+    kal_uint32        ipv4_cnt;
+    kal_uint32        ipv6_cnt;
+    kal_uint32        ipv4_filter_cnt;
+    kal_uint32        ipv6_filter_cnt;
+    kal_uint8         matched_filter_idx_v4;
+    kal_uint8         matched_filter_idx_v6;
+    kal_uint32        callback_with_info;
+    kal_uint32        total_cnt;
+    kal_uint32        sim_idx = 0;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (sim_idx = 0; sim_idx <= 1; sim_idx++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) {
+        if ((0 == ipv4_cnt) && (0 == ipv6_cnt)) {
+            continue;
+        }
+
+        utDLOG("sim_idx(%d) v4Cnt(%d) v6Cnt(%d) \r\n", sim_idx, ipv4_cnt, ipv6_cnt);
+        total_cnt = ipv4_cnt + ipv6_cnt;
+
+        /* Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X. */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ipc_ut_reset_ul_info();
+        ilm.src_mod_id = MOD_UPCM + sim_idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)bind_req);
+
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+            kal_uint8 v4_cntl_begin = 0;
+            kal_uint8 v6_cntl_begin = 0;
+            kal_uint8 v4_cntl_end = 0;
+            kal_uint8 v6_cntl_end = 0;
+
+            /* Before PDN Binding, IPF will only report PN not mtach case or NETIF invalid case */
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+
+                utDLOG("@ Before activation : match_result(%d)\r\n", match_result);
+
+                kal_mem_set(&g_ut_unk_hdr_stat_recv, 0, sizeof(g_ut_unk_hdr_stat_recv));
+                kal_mem_set(&g_ut_unk_hdr_stat_send, 0, sizeof(g_ut_unk_hdr_stat_send));
+                g_unk_pkt_v4_cnt = 0;
+                g_unk_pkt_v6_cnt = 0;
+
+                ipc_ut_prepare_dl_meta_list_with_statistics(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx,
+                                                            &q_type, netif_id, match_result, sim_idx, &v4_cntl_begin,
+                                                            &v6_cntl_begin, &v4_cntl_end, &v6_cntl_end);
+
+                if (IPC_IPF_MR_UNKNOWN_HEADER == match_result) {
+                    if (0 != ipv4_cnt) {
+                        g_ut_unk_hdr_stat_send[sim_idx][4].begin_cntl = v4_cntl_begin;
+                        g_ut_unk_hdr_stat_send[sim_idx][4].end_cntl = v4_cntl_end;
+                        g_ut_unk_hdr_stat_send[sim_idx][4].unk_hdr_cnt = g_unk_pkt_v4_cnt;
+                        g_ut_unk_hdr_stat_send[sim_idx][4].is_valid = KAL_TRUE;
+                    }
+
+                    if (0 != ipv6_cnt) {
+                        g_ut_unk_hdr_stat_send[sim_idx][6].begin_cntl = v6_cntl_begin;
+                        g_ut_unk_hdr_stat_send[sim_idx][6].end_cntl = v6_cntl_end;
+                        g_ut_unk_hdr_stat_send[sim_idx][6].unk_hdr_cnt = g_unk_pkt_v6_cnt;
+                        g_ut_unk_hdr_stat_send[sim_idx][6].is_valid = KAL_TRUE;
+                    }
+                }
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                UT_ASSERT(0 == kal_mem_cmp(g_ut_unk_hdr_stat_send, g_ut_unk_hdr_stat_recv, sizeof(g_ut_unk_hdr_stat_recv)));
+            }
+        }
+
+        /* PDN deactivation. */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM + sim_idx;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+    }
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+void ipc_ut_prepare_rs_ul_filter(kal_uint32 total_cnt,
+                                  kal_uint32 *p_head_idx,
+                                  kal_uint32 *p_tail_idx,
+                                  kal_uint32 netif_id,
+                                  LHIF_QUEUE_TYPE *q_type) {
+    kal_uint32 curr_meta_idx;
+    lhif_meta_tbl_t    *curr_meta = NULL;
+    kal_uint8          *packet_buf = NULL;
+    kal_uint32          packet_len = 0;
+    kal_uint32          netif_id_prefix = (netif_id & 0xFFFFFF00);
+    kal_uint32          idx = 0;
+
+    if (total_cnt != ipc_ut_alloc_meta(IPC_UT_LHIF_META_AP0, total_cnt, p_head_idx, p_tail_idx)) {
+        IPC_ASSERT(KAL_FALSE);
+        return;
+    }
+    *q_type = LHIF_HWQ_AP_UL_Q0;
+    curr_meta_idx = *p_head_idx;
+    for (idx = 0; idx < total_cnt; idx++) {
+        curr_meta = &ipc_ut_meta_tbl_s[curr_meta_idx];
+        curr_meta->net_type = ((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS;
+        curr_meta->channel_id = netif_id & 0x0000001F;
+        curr_meta->mr = IPC_HPC_MR_UNKNOWN;
+        if ((idx % 2) == 0) {
+            packet_buf = g_ipc_ut_icmpv6_rs_pkt;
+            packet_len = sizeof(g_ipc_ut_icmpv6_rs_pkt);
+        } else {
+            packet_buf = g_ipc_ut_icmp_rs_pkt;
+            packet_len = sizeof(g_ipc_ut_icmp_rs_pkt);
+        }
+        g_chk_pkt_cnt++;
+
+        kal_mem_cpy(curr_meta->vrb_addr, packet_buf, packet_len);
+        curr_meta->length = packet_len;
+
+        curr_meta_idx++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+}
+
+kal_bool ipc_ut_rs_ul(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipc_ut_netif_t                     *net = NULL;
+    kal_uint32                          netif_id = IPC_NETIF_ID_ETH_BEGIN;
+    kal_bool                            result = KAL_FALSE;
+    kal_uint32                          head_idx;
+    kal_uint32                          tail_idx;
+    LHIF_QUEUE_TYPE                     q_type;
+    ipcore_upcm_pdn_bind_ind_struct    *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct  *deact_req = NULL;
+    ilm_struct                          ilm = {0};
+    ipc_filter_rules_t                 *rules = NULL;
+    ipc_filter_ntfy_ctxt_t              ntfy_ctxt = {0};
+    ipc_ut_filter_info_t               *info = NULL;
+    kal_uint32                          idx = 0;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_NETIF_ID_ETH_BEGIN;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_callback_t = ipc_ut_dl_callback;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+    ipc_ut_prepare_rs_ul_filter(2, &head_idx, &tail_idx, netif_id, &q_type);
+
+    /* Send IOR into IP Core */
+    ipc_ut_reset_ul_info();
+
+    ipc_meta_uplink(head_idx, tail_idx, q_type);
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+    if ( (2 != ipc_ut_ul_meta_cnt) ||
+         (0 != ipc_ut_ul_meta_non_igr_cnt) ) {
+        utELOG("UL META is forwarded before PDN binding! (proto_idx:%d, ipv4:%d, ipv6:%d)\r\n", idx, 1, 1);
+        ipc_ut_meta_read_done(head_idx, tail_idx, q_type);
+        return KAL_FALSE;
+    }
+    /* Activate IPv6 PDN with unspecified IP address & from different MOD_UPCM_X. */
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = net->conf.netif_id;
+    bind_req->pdn_id = IPC_UT_PDN_ID;
+    bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ilm.src_mod_id = MOD_UPCM + idx;
+    ilm.dest_mod_id = MOD_IPCORE;
+    ilm.sap_id = IPCORE_SAP;
+    ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+    ilm.local_para_ptr = (local_para_struct *)bind_req;
+    ilm.peer_buff_ptr = NULL;
+    ipc_on_ilm(&ilm);
+    if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM + idx, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE)
+    {
+        utELOG("Bind response is not received\r\n");
+        return KAL_FALSE;
+    }
+    free_local_para((local_para_struct *)bind_req);
+    
+    utDLOG("PDN binding successfull");
+
+    info = &ipc_ut_info_set[0];
+    
+    rules = &info->rules;
+    kal_mem_set(rules, 0, sizeof(*rules));
+    rules->protocol = IPC_HDR_PROT_ICMP;
+    rules->valid_fields = IPC_FILTER_BY_PROTOCOL |
+                          IPC_FILTER_BY_ICMPV4_TYPE;
+    rules->icmpv4_type = IPC_HDR_ICMP_TYPE_RS;
+    rules->ip_type = IPC_IP_TYPE_IPV4;
+
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+    ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+    ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+
+    info = &ipc_ut_info_set[1];
+    
+    rules = &info->rules;
+    kal_mem_set(rules, 0, sizeof(*rules));
+    rules->protocol = IPC_HDR_PROT_ICMPV6;
+    rules->valid_fields = IPC_FILTER_BY_PROTOCOL |
+                          IPC_FILTER_BY_ICMPV6_TYPE;
+    rules->icmpv6_type = IPC_HDR_ICMPV6_TYPE_RS;
+    rules->ip_type = IPC_IP_TYPE_IPV6;
+
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_ul_filter_callback;
+    ntfy_ctxt.ntfy_mod.with_info_cbk_func = ipc_ut_ul_filter_with_info_callback;
+    ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    info->filter_id = ipc_reg_filter(UL_DIRECT, rules, &ntfy_ctxt);
+
+    g_chk_pkt_cnt = 0;
+
+    ipc_ut_prepare_rs_ul_filter(2, &head_idx, &tail_idx, netif_id, &q_type);
+
+    /* Send IOR into IP Core */
+    ipc_ut_reset_ul_info();
+
+    ipc_meta_uplink(head_idx, tail_idx, q_type);
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    UT_ASSERT(2 == ipc_ut_ul_meta_cnt);
+    UT_ASSERT(g_chk_pkt_cnt == g_ipc_ut_igr_meta_cnt);
+
+    ipc_dereg_filter(0);
+    ipc_dereg_filter(1);
+
+    /* PDN deactivation. */
+    deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+    deact_req->pdn_id = IPC_UT_PDN_ID;
+
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ilm.src_mod_id = MOD_UPCM + idx;
+    ilm.dest_mod_id = MOD_IPCORE;
+    ilm.sap_id = IPCORE_SAP;
+    ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+    ilm.local_para_ptr = (local_para_struct *)deact_req;
+    ilm.peer_buff_ptr = NULL;
+    ipc_on_ilm(&ilm);
+    free_local_para((local_para_struct *)deact_req);
+
+    ipc_ut_prepare_rs_ul_filter(2, &head_idx, &tail_idx, netif_id, &q_type);
+
+    /* Send IOR into IP Core */
+    ipc_ut_reset_ul_info();
+
+    ipc_meta_uplink(head_idx, tail_idx, q_type);
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+
+}
+
+kal_bool ipc_ut_dl_callback_did_2(void *context, upcm_did *did)
+{
+    UT_ASSERT(NULL != did);
+
+    ipc_ut_dl_callback_did_cnt ++;
+    ipc_ut_dl_callback_did_pkt_cnt += (UPCM_DID_GET_PKT_NUM(did) << 1);
+
+    return KAL_TRUE;
+}
+
+
+kal_bool ipc_ut_send_dl_pkt_force(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    typedef kal_bool (*ipc_dlink_callback_t)(void *context, ipc_io_request_t *ior);
+    ipc_ut_netif_t *netif;
+    kal_bool result;
+    kal_uint32 idx = 0, pkt_cnt = 0;
+    qbm_gpd *pkt, *tail;
+    ipc_dlink_callback_t did_cb[] = {ipc_ut_dl_callback_did, ipc_ut_dl_callback_did_2};
+    ipcore_upcm_pdn_bind_ind_struct    *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct  *deact_req = NULL;
+    ilm_struct                          ilm = {0};
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+        *   Reset IPCore before test
+        */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (pkt_cnt = 1; pkt_cnt < 3; pkt_cnt++) {
+        ipc_ut_reset_dl_callback_info();
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        /* Test race condition */
+        ipc_data_set_dl_ilm_flag();
+
+        for (idx = 0; idx < pkt_cnt; idx++) {
+            ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                       0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+            ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START, IPC_IP_TYPE_MIXED);
+
+            ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                       0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+            ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START+1, IPC_IP_TYPE_MIXED);
+        }
+        ipc_data_clear_dl_ilm_flag();
+        ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                   0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+        ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START+1,IPC_IP_TYPE_MIXED);
+        
+        ASSERT(ipc_ut_dl_callback_did_pkt_cnt == 0); /* (2*1)+1 */
+        ASSERT(ipc_ut_dl_callback_did_cnt == 0); /* (2*1)+1 */
+    }
+
+    for (idx = 0; idx < 2; idx++) {
+        netif = &(ipc_ut_nets_s[idx]);
+        kal_mem_set(netif, 0, sizeof(ipc_ut_netif_t));
+        netif->conf.module_id = MOD_IPCORE;
+        netif->conf.netif_id = IPC_UT_LHIF_NETID_START + idx;
+        netif->conf.ul_reload_context = netif;
+        netif->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+        netif->conf.callback_context = netif;
+        netif->conf.ipc_dlink_did_cb_t = did_cb[idx];
+        netif->conf.features = 0;
+        result = ipc_attach(&netif->conf, &netif->handle);
+        if (!result) {
+            utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    for (pkt_cnt = 1; pkt_cnt < 3; pkt_cnt++) {
+        ipc_ut_reset_dl_callback_info();
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+        /* Test race condition */
+        ipc_data_set_dl_ilm_flag();
+
+        for (idx = 0; idx < pkt_cnt; idx++) {
+            ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                       0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+            ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START, IPC_IP_TYPE_MIXED);
+
+            ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                       0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+            ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START+1, IPC_IP_TYPE_MIXED);
+        }
+        ipc_data_clear_dl_ilm_flag();
+        ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                   0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+        ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START+1, IPC_IP_TYPE_MIXED);
+        
+        ASSERT(ipc_ut_dl_callback_did_pkt_cnt == 0); /* (2*1)+1 */
+        ASSERT(ipc_ut_dl_callback_did_cnt == 0); /* (2*1)+1 */
+    }
+
+    for (idx = 0; idx < 2; idx++) {
+        /* Activate IPv6 PDN with unspecified IP address & from different MOD_UPCM_X. */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = IPC_UT_LHIF_NETID_START + idx;
+        bind_req->pdn_id = IPC_UT_PDN_ID_2 + idx;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE)
+        {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+        free_local_para((local_para_struct *)bind_req);
+
+        for (pkt_cnt = 1; pkt_cnt < 3; pkt_cnt++) {
+            kal_uint32 expect_count;
+            kal_uint32 idx1;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_set_error(IPC_UT_NO_ERROR);
+            /* Test race condition */
+            ipc_data_set_dl_ilm_flag();
+            expect_count = 0;
+        
+            for (idx1 = 0; idx1 < pkt_cnt; idx1++) {
+                ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                           0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+                expect_count++;
+                ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START, IPC_IP_TYPE_MIXED);
+
+                ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                           0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+                if (idx > 0) {
+                    expect_count += 2;
+                }
+                ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START+1, IPC_IP_TYPE_MIXED);
+            }
+            ipc_data_clear_dl_ilm_flag();
+            ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                       0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+            if (idx > 0) {
+                expect_count += 2;
+            }
+            ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START+1, IPC_IP_TYPE_MIXED);
+
+            ASSERT(ipc_ut_dl_callback_did_pkt_cnt == expect_count);
+        }
+
+    }
+    utDLOG("PDN binding successfull");
+
+    /* PDN deactivation. */
+    for (idx = 0; idx < 2; idx++) {
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID_2 + idx;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        free_local_para((local_para_struct *)deact_req);
+
+        for (pkt_cnt = 1; pkt_cnt < 3; pkt_cnt++) {
+            kal_uint32 idx1;
+            kal_uint32 expect_count;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_set_error(IPC_UT_NO_ERROR);
+            /* Test race condition */
+            ipc_data_set_dl_ilm_flag();
+            expect_count = 0;
+        
+            for (idx1 = 0; idx1 < pkt_cnt; idx1++) {
+                ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                           0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+                ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START, IPC_IP_TYPE_MIXED);
+
+                ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                           0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+                if (idx == 0) {
+                    expect_count += 2;
+                }
+                ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START+1, IPC_IP_TYPE_MIXED);
+            }
+            ipc_data_clear_dl_ilm_flag();
+            ipc_ut_prepare_dl_gpd_list(0, 0, KAL_FALSE, KAL_FALSE, 1, 0, KAL_TRUE, KAL_FALSE,
+                                       0, 0, &pkt, &tail, NULL, NULL, KAL_FALSE, KAL_FALSE, 0);
+            if (idx == 0) {
+                expect_count += 2;
+            }
+            ipc_send_dl_pkt_enqueue(pkt, IPC_UT_LHIF_NETID_START+1, IPC_IP_TYPE_MIXED);
+
+            ASSERT(ipc_ut_dl_callback_did_pkt_cnt == expect_count);
+        }
+    }
+
+    for (idx = 0; idx < 2; idx++) {
+        netif = &(ipc_ut_nets_s[idx]);
+        result = ipc_detach(netif->handle);
+        if (!result) {
+            utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+            return KAL_FALSE;
+        }
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_ra_dl(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint32 i = 0;
+    kal_uint32 ipv4_cnt = 0;
+    kal_uint32 ipv6_cnt = 0;
+    ipcore_upcm_pdn_bind_ind_struct *p_bind_req = NULL;
+    ipc_filter_rules_t rules = {0};
+    kal_int32 filter_id = 0, filter_idv6 = 0;
+    kal_uint32 pdn_id = 0;
+    ipc_session_t *p_session = NULL;
+    kal_uint32 netif_id = IPC_UT_LHIF_NETID_START;
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+
+    /* initialize before test & reset IPCORE  */
+    ipc_ut_init();
+    ASSERT(KAL_TRUE == ipc_reset());
+
+    /* netif attach */
+    ASSERT(KAL_TRUE == ipc_ut_fin_ack_filter_netif_attach());
+    /* Before binding */
+    {
+        upcm_did *did_head = NULL;
+        upcm_did *did_tail = NULL;
+
+        ipc_ut_reset_dl_callback_info();
+
+        ipc_ut_prepare_ra_filter_pkt(0,
+                                     0,
+                                     KAL_FALSE,
+                                     KAL_FALSE,
+                                     1,
+                                     0,
+                                     KAL_FALSE,
+                                     KAL_FALSE,
+                                     0,
+                                     0,
+                                     &did_head,
+                                     &did_tail,
+                                     NULL,
+                                     NULL,
+                                     1,
+                                     0);
+        ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+    }
+    /* IPv6 binding */
+    p_bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    p_bind_req->network_interface_id = IPC_UT_LHIF_NETID_START;
+    p_bind_req->pdn_id = IPC_UT_PDN_ID;
+    p_bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)p_bind_req);
+    free_local_para((local_para_struct * )p_bind_req);
+
+//    UT_ASSERT (ipc_ut_dl_callback_did_pkt_cnt == 1);
+
+    /* Registered DL filter to filter out v4 RA packets*/
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                      IPC_FILTER_BY_ICMPV4_TYPE;
+    rules.protocol = IPC_HDR_PROT_ICMP;
+    rules.icmpv4_type = IPC_HDR_ICMP_TYPE_RA;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    rules.features = IPC_FILTER_FEATURE_IG_PN;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    filter_id= ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt);
+    ASSERT(0 == filter_id);
+
+    /* Registered DL filter to filter out v6 RA packets*/
+    kal_mem_set(&rules, 0, sizeof(ipc_filter_rules_t));
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                      IPC_FILTER_BY_ICMPV6_TYPE;
+    rules.protocol = IPC_HDR_PROT_ICMPV6;
+    rules.icmpv6_type = IPC_HDR_ICMPV6_TYPE_RA;
+    rules.ip_type = IPC_IP_TYPE_IPV6;
+    rules.features = IPC_FILTER_FEATURE_IG_PN;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_ut_filter_cbk;
+    ntfy_ctxt.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC;
+
+    filter_idv6 = ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt);
+    ASSERT(1 == filter_idv6);
+
+    /* Simulate DL traffic to IPCore : PDN binding */
+    {
+        kal_uint32 did_cnt = 0;
+        upcm_did *did_head = NULL;
+        upcm_did *did_tail = NULL;
+        kal_uint32 alignment = 0;
+        kal_uint32 did_igr_bit = 0;
+        kal_uint32 free_cnt = 0;
+
+        for (alignment = 0; alignment < 4; alignment++)
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+        for (did_igr_bit = 0; did_igr_bit < 1; did_igr_bit++) {
+        if (0 == ipv4_cnt && 0 == ipv6_cnt) {
+         continue;
+        }
+
+        utDLOG("@[Binding] v4_cnt(%d),v6_cnt(%d),alignment(%d),igr(%d)\r\n", ipv4_cnt, ipv6_cnt, alignment, did_igr_bit);
+        //g_cbk_pkt_recv_cnt = 0;
+        g_cbk_pkt_send_cnt = 0;
+        g_normal_cbk_pkt_recv_cnt = 0;
+
+        did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+        ipc_ut_reset_dl_callback_info();
+        ipc_ut_reset_dl_filter_info();
+        ipc_ut_prepare_ra_filter_pkt(ipv4_cnt,
+                                  0,
+                                  KAL_FALSE,
+                                  KAL_FALSE,
+                                  ipv6_cnt,
+                                  0,
+                                  KAL_FALSE,
+                                  KAL_FALSE,
+                                  0,
+                                  alignment,
+                                  &did_head,
+                                  &did_tail,
+                                  NULL,
+                                  NULL,
+                                  did_cnt,
+                                  did_igr_bit);
+
+        /* simulate DL traffic from IPC_UT_PDN_ID */
+        ipc_did_downlink_enqueue(IPC_UT_PDN_ID, did_head, did_tail);
+        kal_sleep_task(IPC_UT_MSG_LATENCY);
+        UT_ASSERT(g_cbk_pkt_send_cnt == g_normal_cbk_pkt_recv_cnt);
+        //UT_ASSERT(g_cbk_pkt_recv_cnt == g_cbk_pkt_send_cnt);
+        UT_ASSERT((ipc_ut_dl_callback_did_pkt_cnt + g_normal_cbk_pkt_recv_cnt) == (ipv4_cnt + ipv6_cnt));
+        }
+    }
+    ipc_dereg_filter(filter_id);
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+    
+}
+
+void ipc_ut_prepare_dl_did_large_udp_packets_list(
+        kal_uint32 ipv4_cnt,
+        kal_uint32 align_offset,
+        upcm_did   **did_head,
+        upcm_did   **did_tail,
+        kal_uint32 did_cnt)
+{
+    kal_uint32          total_cnt = ipv4_cnt;
+    kal_uint32          idx;
+    upcm_did           *curr_did;
+    upcm_did_si        *curr_sit;
+    upcm_did_si        *curr_si;
+    kal_uint32          curr_si_idx;
+    kal_uint32          pkt_start_si_idx;
+    kal_uint8          *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          pkt_num;
+    kal_uint32          seg_num;
+	kal_uint8           per_pkt_max_sit_num = 10; /* one DID max packet number will be 7. one DID has 62 SIT entries */
+
+    if (did_cnt != ipc_ut_alloc_did(
+                        did_cnt,
+                        did_head,
+                        did_tail)) {
+        IPC_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    /* For un-alignment test : 4 byte align as maximum */
+    {
+        upcm_did   *next_did;
+        kal_bool    end_of_list;
+
+        next_did = NULL;
+        end_of_list = KAL_FALSE;
+        for (   curr_did = *did_head ;
+                curr_did && (end_of_list == KAL_FALSE) ;
+                curr_did = next_did)
+        {
+            kal_uint32      i;
+
+            curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+
+            for (i = 0; i < IPC_UT_DID_MAX_SIT_NUM; i++) {
+                upcm_did_si    *si = &curr_sit[i];
+
+                UPCM_DID_SI_SET_OFFSET(si, UPCM_DID_SI_GET_OFFSET(si) + (align_offset % 4));
+            }
+        }
+    }
+    curr_did = *did_tail;
+    curr_sit = UPCM_DID_GET_SIT_PTR(curr_did);
+    curr_si_idx = 0;
+    curr_si = &curr_sit[curr_si_idx];
+    pkt_num = 0;
+    seg_num = 0;
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        switch(idx) {
+            case 0:
+                packet_buf = g_ipc_ut_large_udp_pkt_s3632;
+                packet_len = sizeof(g_ipc_ut_large_udp_pkt_s3632);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_udp_packet;
+                packet_len = sizeof(ipc_ut_ipv4_udp_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv4_udp_packet_example;
+                packet_len = sizeof(ipc_ut_ipv4_udp_packet_example);
+                break;
+        }
+
+        {
+            kal_uint32 copied_len;
+            kal_uint32 cont_loop_cnt;
+            kal_uint32 si_offset;
+
+            pkt_start_si_idx = curr_si_idx;
+            copied_len = 0;
+            cont_loop_cnt = 0;
+
+            while (copied_len < packet_len)
+            {
+                kal_uint32 current_copy_len;
+
+                if ((curr_si_idx == IPC_UT_DID_MAX_SIT_NUM - 1) || (cont_loop_cnt == per_pkt_max_sit_num-1))
+                {   /* Latest SIT : copy all remaining data */
+                    current_copy_len = packet_len - copied_len;
+                } else
+                {   /* Non latest SIT : copy partial of data */
+                    current_copy_len = (((align_offset > 0) || (cont_loop_cnt % 2))?(idx + cont_loop_cnt):0) % (packet_len - copied_len);
+                    current_copy_len = (current_copy_len == 0) ? 1 : current_copy_len;
+                }
+
+                /* No buffer is allocated and we need to set its buffer to static template */
+                si_offset = UPCM_DID_SI_GET_OFFSET(curr_si);
+                UPCM_DID_SI_SET_DATAPTR(curr_si, packet_buf + copied_len - si_offset);
+                UPCM_DID_SI_SET_LEN(curr_si, current_copy_len);
+                copied_len += current_copy_len;
+                seg_num ++;
+
+                if (copied_len >= packet_len) {
+                    IPC_ASSERT(copied_len == packet_len);
+                    UPCM_DID_SI_SET_EOL(curr_si);
+                }
+
+                /* Get next SI in list */
+                curr_si_idx ++;
+                curr_si = &curr_sit[curr_si_idx];
+
+                cont_loop_cnt ++;
+            }
+        }
+        pkt_num ++;
+
+    }
+
+    UPCM_DID_SET_PKT_NUM(curr_did, pkt_num);
+    UPCM_DID_SET_SEG_NUM(curr_did, seg_num);
+ }
+
+kal_bool ipc_ut_downlink_test_udp_drop_large_packet(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+        ipc_ut_netif_t   *net;
+    kal_uint32       netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool         result;
+    kal_uint8         proto_idx[] = {0, 1, 2, 3};
+    kal_uint32        idx;
+    kal_uint32       gpd_remain_cnt_ul, gpd_remain_cnt_dl, did_remain_cnt;
+    // init before test
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * ipc_attach()
+     */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+    for (idx = 0; idx < sizeof(proto_idx)/sizeof(proto_idx[0]); idx++)
+    {
+        kal_uint32  cnt;
+        kal_uint32  did_cnt;
+        upcm_did   *did_head;
+        upcm_did   *did_tail;
+        kal_uint32  alignment;
+        kal_uint8 expected_pkt_cnt = 0;
+
+        for (alignment = 0 ; alignment < 1 ; alignment ++)
+        for (cnt = 1; cnt <= 2; cnt++) {
+
+            did_cnt = 1;
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+            ipc_ut_reset_ul_info();
+
+            /*Store DID remain cnt */
+			did_remain_cnt = upcm_did_get_buff_remain_num();
+
+            /*prepare a DID of UDP ipv4 */
+            ipc_ut_prepare_dl_did_large_udp_packets_list(cnt,
+                                                        alignment,
+                                                        &did_head,
+                                                        &did_tail,
+                                                        did_cnt);
+
+            /*Store GPD remain cnt */
+            gpd_remain_cnt_ul = qbm_get_buff_remain_num(QBM_TYPE_NET_UL);
+            gpd_remain_cnt_dl = qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, idx); //0 for SIM1
+
+            if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                utELOG("DL DID is forwarded on PDN unbind!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(gpd_remain_cnt_ul != qbm_get_buff_remain_num(QBM_TYPE_NET_UL)){
+                utELOG("wrong expected QBM_TYPE_NET_UL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(gpd_remain_cnt_dl != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+
+			if(did_remain_cnt != upcm_did_get_buff_remain_num()){
+                utELOG("wrong expected DID count!\r\n");
+                return KAL_FALSE;
+            }
+
+        }
+    }
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+
+}
+
+void ipc_ut_prepare_dl_meta_list_with_large_udp_pkt(kal_bool allValidIpPkt,
+                                                 kal_uint32 ipv4_cnt,
+                                                 kal_uint32 dhcpv4_idx,
+                                                 kal_uint32 ipv6_cnt,
+                                                 kal_uint32 dhcpv6_idx,
+                                                 kal_uint32 *p_head_idx,
+                                                 kal_uint32 *p_tail_idx,
+                                                 ipfc_dl_filter_queue_type *q_type,
+                                                 kal_uint32 netif_id,
+                                                 kal_uint8 match_result)
+{
+    kal_uint32          total_cnt = ipv4_cnt + ipv6_cnt;
+    kal_uint32          idx;
+    kal_uint32          curr_meta_idx;
+    ipf_dl_meta         *curr_meta;
+    kal_uint8           *packet_buf;
+    kal_uint32          packet_len;
+    kal_uint32          netif_id_prefix = (netif_id & 0xFFFFFF00);
+
+    if (total_cnt != ipc_ut_alloc_meta(
+                        IPC_UT_IPF_DL_0, //LHIF_HWQ_AP_UL_Q0,
+                        total_cnt,
+                        p_head_idx,
+                        p_tail_idx)) {
+        UT_ASSERT(KAL_FALSE);
+        return;
+    }
+    *q_type = IPFC_META_QUEUE_DL;
+    curr_meta_idx = *p_head_idx;
+
+    for (idx = 0; idx < ipv4_cnt; idx++) {
+        curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+        curr_meta->channel_id = ((((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS) <<8 )
+                            |(netif_id & 0x000000FF) ;
+
+        if (idx == dhcpv4_idx) {
+            packet_buf = ipc_ut_ipv4_dhcp_packet;
+            packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+            ipc_ut_dl_filter_expect_gpd_cnt++;
+        } else {
+            switch (idx) {
+            case 0:
+                if (ipv4_cnt > 4) {
+                    if ((ipv4_cnt%2) == 0) {
+                        packet_buf = ipc_ut_ipv4_dhcp_packet;
+                        packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                        ipc_ut_dl_filter_expect_gpd_cnt++;
+                    } else {
+                        packet_buf = ipc_ut_non_ip_packet;
+                        packet_len = sizeof(ipc_ut_non_ip_packet);
+                    }
+                }
+                else {
+                    packet_buf = ipc_ut_non_ip_packet;
+                    packet_len = sizeof(ipc_ut_non_ip_packet);
+                }
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv4_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv4_incomplete_ip_header_packet);
+                break;
+            case 2:
+                packet_buf = g_ipc_ut_large_udp_pkt_s3632;
+                packet_len = sizeof(g_ipc_ut_large_udp_pkt_s3632);
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv4_frag0_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag0_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv4_frag1_packet;
+                packet_len = sizeof(ipc_ut_ipv4_frag1_packet);
+                break;
+            default:
+                if ((idx%3) == 0) {
+                    packet_buf = ipc_ut_ipv4_dns_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_dns_packet);
+                } else {
+                    packet_buf = ipc_ut_ipv4_dhcp_packet;
+                    packet_len = sizeof(ipc_ut_ipv4_dhcp_packet);
+                    ipc_ut_dl_filter_expect_gpd_cnt++;
+                }
+                break;
+            }
+        }
+
+        kal_mem_cpy((kal_uint8*)curr_meta->addr, packet_buf, packet_len);
+        curr_meta->len = packet_len;
+
+        // Fill IP type
+        curr_meta->ip = 0;
+
+        // Fill Match index (don't care value)
+        // we assgin the same value as ip type. it will be reused for querey filter id.
+        curr_meta->match_idx = 0;
+
+        curr_meta->mr = (match_result & 0x07);
+
+        curr_meta->pdn_sim_id = IPC_UT_PDN_ID;
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+
+
+    for (idx = 0; idx < ipv6_cnt; idx++) {
+        curr_meta = &ipc_ut_dl_meta_tbl_s[curr_meta_idx];
+        curr_meta->channel_id = ((((netif_id & IPC_NETIF_ID_LHIF_BEGIN) == IPC_NETIF_ID_LHIF_BEGIN) ? LHIF_NET_TYPE_LHIF : LHIF_NET_TYPE_RNDIS) <<8 )
+                            |(netif_id & 0x000000FF) ;
+
+
+        if (idx == dhcpv6_idx) {
+            switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_ipv6_ext0_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv6_ext0_dhcp_packet);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_ext1_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv6_ext1_dhcp_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_dhcp_packet;
+                packet_len = sizeof(ipc_ut_ipv6_dhcp_packet);
+            }
+        } else {
+            switch (idx) {
+            case 0:
+                packet_buf = ipc_ut_non_ip_packet;
+                packet_len = sizeof(ipc_ut_non_ip_packet);
+                break;
+            case 1:
+                packet_buf = ipc_ut_ipv6_incomplete_ip_header_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ip_header_packet);
+                break;
+            case 2:
+                packet_buf = ipc_ut_ipv6_incomplete_hop_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_hop_packet);
+                break;
+            case 3:
+                packet_buf = ipc_ut_ipv6_incomplete_ah_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ah_packet);
+                break;
+            case 4:
+                packet_buf = ipc_ut_ipv6_unknown_ext_packet;
+                packet_len = sizeof(ipc_ut_ipv6_unknown_ext_packet);
+                break;
+            case 5:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv4enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv4enc_packet);
+                break;
+            case 6:
+                packet_buf = ipc_ut_ipv6_incomplete_ipv6enc_packet;
+                packet_len = sizeof(ipc_ut_ipv6_incomplete_ipv6enc_packet);
+                break;
+            case 7:
+                if (ipv6_cnt <= 10) {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag0_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag0_packet);
+                } else {
+                    packet_buf = ipc_ut_ipv6_ipv4enc_frag1_packet;
+                    packet_len = sizeof(ipc_ut_ipv6_ipv4enc_frag1_packet);
+                }
+                break;
+            case 8:
+                packet_buf = ipc_ut_ipv6_frag_packet;
+                packet_len = sizeof(ipc_ut_ipv6_frag_packet);
+                break;
+            default:
+                packet_buf = ipc_ut_ipv6_mdns_packet;
+                packet_len = sizeof(ipc_ut_ipv6_mdns_packet);
+                break;
+            }
+        }
+
+        kal_mem_cpy((kal_uint8*)curr_meta->addr, packet_buf, packet_len);
+        curr_meta->len = packet_len;
+
+        // Fill IP type
+        curr_meta->ip = 1;
+
+        // Fill Match index (don't care value)
+        // we assgin the same value as ip type. it will be reused for querey filter id.
+        curr_meta->match_idx = 1;
+
+        curr_meta->mr = (match_result & 0x07);
+
+        curr_meta->pdn_sim_id = IPC_UT_PDN_ID;
+
+        curr_meta_idx ++;
+        if (curr_meta_idx == IPC_UT_META_TABLE_SIZE) {
+            curr_meta_idx = 0;
+        }
+        if (curr_meta_idx == *p_tail_idx) {
+            return;
+        }
+    }
+}
+
+kal_bool ipc_ut_meta_downlink_with_large_pkt(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    ipc_ut_netif_t   *net;
+    kal_uint32        netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool          result;
+    ilm_struct        ilm;
+    kal_uint32        ipv4_cnt;
+    kal_uint32        ipv6_cnt;
+    kal_uint32        ipv4_filter_cnt;
+    kal_uint32        ipv6_filter_cnt;
+    kal_uint8         matched_filter_idx_v4;
+    kal_uint8         matched_filter_idx_v6;
+    kal_uint32        callback_with_info;
+    kal_uint32        total_cnt;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * ipc_attach()
+     */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++)
+    for (ipv4_filter_cnt = 0; ipv4_filter_cnt <= 4; ipv4_filter_cnt++)
+    for (ipv6_filter_cnt = 0; ipv6_filter_cnt <= 4; ipv6_filter_cnt++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < ipv4_filter_cnt; matched_filter_idx_v4++)
+    for (matched_filter_idx_v6 = 0; matched_filter_idx_v6 < ipv6_filter_cnt; matched_filter_idx_v6++) {
+        if ((0 == ipv4_cnt) && (0 == ipv6_cnt)) continue;
+
+        utDLOG("ifo(%d) v4Cnt(%d) v6Cnt(%d) v4FltCnt(%d) v6FltCnt(%d) v4Idx(%d) v6Idx(%d)\r\n",
+               callback_with_info, ipv4_cnt, ipv6_cnt, ipv4_filter_cnt , ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6);
+
+        total_cnt = ipv4_cnt + ipv6_cnt;
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Install DL filter for each test loop */
+        ipc_ut_install_dl_filters(callback_with_info, KAL_TRUE, ipv4_filter_cnt, ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6, IPC_UT_LHIF_NETID_START);
+
+        ipc_ut_dl_ipf_match_filter_id_v4_s = matched_filter_idx_v4;
+        ipc_ut_dl_ipf_match_filter_id_v6_s = ipv4_filter_cnt + matched_filter_idx_v6;
+        
+        /*
+         * Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         *   Simulate DL traffic from IPCore : All meta should be forward to either DL callback or filter callback(IPv4/IPv6)
+         */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            /* Before PDN Binding, IPF will only report PN not mtach case or NETIF invalid case */
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_dl_v4_filter_out_cnt;
+                kal_uint32 expected_dl_v6_filter_out_cnt;
+                kal_uint32 expected_dl_filter_out_cnt;
+                kal_uint32 did_cnt;
+                kal_uint32 expected_dl_forwad_cnt;
+
+                utDLOG("@ PDN connected : match_result(%d)\r\n", match_result);
+                ipc_ut_prepare_dl_meta_list_with_large_udp_pkt(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_dl_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                  (ipv4_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))? 1:0;
+                expected_dl_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                  (ipv6_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))?1:0;
+
+                expected_dl_filter_out_cnt = expected_dl_v4_filter_out_cnt + expected_dl_v6_filter_out_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) ||
+                    (match_result == IPC_IPF_MR_PN_NO_MATCH) ||
+                    (match_result == IPC_IPF_MR_NET_INVALID)) {
+                    did_cnt = expected_dl_forwad_cnt = 0;
+                }
+                else {
+                    did_cnt = total_cnt-expected_dl_filter_out_cnt; //Supposed one DID only contains one packet
+                    expected_dl_forwad_cnt = total_cnt-expected_dl_filter_out_cnt;
+                }
+
+                if (expected_dl_filter_out_cnt > 0) {
+                    if (callback_with_info) {
+                        if (ipc_ut_dl_filter_info.netif_id != IPC_UT_LHIF_NETID_START) {
+                            utELOG("Filtered-out netif ID is incorrect!\r\n");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                        if (ipc_ut_dl_filter_info.ebi != -1) {
+                            utELOG("Filtered-out EBI is incorrect!\r\r");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                    }
+                    else {
+                        if (ipc_ut_dl_filter_info.netif_id != 0) {
+                            utELOG("Filtered-out netif ID is incorrect!\r\n");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                        if (ipc_ut_dl_filter_info.ip_id != -1) {
+                            utELOG("Filtered-out IP ID is incorrect!\r\r");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                    }
+                }
+
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+    }
+
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_fragment_ut_cust_filter_cbk(const kal_uint8 *p_pkt,
+                                kal_int32 pkt_len,
+                                kal_int32 filter_id,
+                                void *p_args)
+{
+    kal_bool ret = KAL_FALSE;
+
+    if (IPC_HDR_IS_V4(p_pkt)) {
+        ret = KAL_TRUE;
+    } else if (IPC_HDR_IS_V6(p_pkt)) {
+        ret = KAL_TRUE;
+    } else {
+        UT_ASSERT(KAL_FALSE);
+    }
+
+    return ret;
+}
+
+void ipc_ut_reg_cust_filter_prepare_fragments_and_send(kal_uint32 pdn_id, kal_uint8 proto_idx) {
+    upcm_did *did_p = NULL;
+    upcm_did_si *sit_p = NULL;
+    ipc_filter_rules_t rules = {0};
+    ipc_filter_ntfy_ctxt_t ntfy_ctxt = {0};
+    kal_uint32 filter_id = IPC_INVALID_FILTER_ID;
+    kal_uint32 buff_count = 0, remain_count = 0;
+
+    buff_count = upcm_did_get_buff_remain_num() + 
+        qbm_get_buff_remain_num(QBM_TYPE_TGPD) + qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+    rules.priority = 3;
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_PDN_ID | IPC_FILTER_BY_SPI;
+    rules.features = IPC_FILTER_FEATURE_FRAG | IPC_FILTER_FEATURE_CUST_FILTER;
+    rules.pdn_id = pdn_id;
+    rules.protocol = IPC_HDR_PROT_ESP;
+    rules.spi = 0x481fde70;
+    rules.cust_cbk_func = ipc_fragment_ut_cust_filter_cbk;
+    ntfy_ctxt.ntfy_mod.cbk_func = ipc_fragment_ut_dl_filter_callback;
+    ntfy_ctxt.ntfy_mod.cbk_mod = MOD_IPCORE;
+    filter_id = ipc_reg_filter(DL_DIRECT, &rules, &ntfy_ctxt);
+
+    did_p = upcm_did_alloc_one();
+    sit_p = UPCM_DID_GET_SIT_PTR(did_p);
+    UPCM_DID_SET_NEXT(did_p, NULL);
+    
+    kal_mem_set(sit_p, 0, sizeof(upcm_did_si));
+    UPCM_DID_SI_SET_LEN(sit_p, sizeof(pkt2508_1));
+    UPCM_DID_SI_SET_DATAPTR(sit_p, ((void*)pkt2508_1));
+    UPCM_DID_SI_SET_EOL(sit_p);
+    sit_p++;
+    kal_mem_set(sit_p, 0, sizeof(upcm_did_si));
+    UPCM_DID_SI_SET_LEN(sit_p, sizeof(pkt2509_1));
+    UPCM_DID_SI_SET_DATAPTR(sit_p, ((void*)pkt2509_1));
+    UPCM_DID_SI_SET_EOL(sit_p);
+    sit_p++;
+    kal_mem_set(sit_p, 0, sizeof(upcm_did_si));
+    UPCM_DID_SI_SET_LEN(sit_p, sizeof(pkt2510_1));
+    UPCM_DID_SI_SET_DATAPTR(sit_p, ((void*)pkt2510_1));
+    UPCM_DID_SI_SET_EOL(sit_p);
+
+    UPCM_DID_SET_PKT_NUM(did_p, 3);
+    UPCM_DID_SET_SEG_NUM(did_p, 3);
+
+    ipc_on_did_downlink_multiple_ps(pdn_id, did_p, did_p, proto_idx);
+    ipc_dereg_filter(filter_id);
+
+    remain_count = upcm_did_get_buff_remain_num() + 
+        qbm_get_buff_remain_num(QBM_TYPE_TGPD) + qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+    ASSERT(remain_count == buff_count);
+}
+
+kal_bool ipc_ut_dl_frag_refilter_with_cust_feature(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz)
+{
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    ipc_ut_netif_t   *net;
+    kal_uint32        netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool          result;
+    ilm_struct        ilm;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /* Reset IPCore before test */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* Activate IPv4 PDN */
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = netif_id;
+    bind_req->pdn_id = IPC_UT_PDN_ID;
+    bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ipc_ut_reset_ul_info();
+    ilm.src_mod_id = MOD_UPCM;
+    ilm.dest_mod_id = MOD_IPCORE;
+    ilm.sap_id = IPCORE_SAP;
+    ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+    ilm.local_para_ptr = (local_para_struct *)bind_req;
+    ilm.peer_buff_ptr = NULL;
+    ipc_on_ilm(&ilm);
+    free_local_para((local_para_struct *)bind_req);
+
+    ipc_ut_reg_cust_filter_prepare_fragments_and_send(IPC_UT_PDN_ID, 0);
+
+    /* PDN deactivation. */
+    deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+    deact_req->pdn_id = IPC_UT_PDN_ID;
+
+    ipc_ut_msg_reset(NULL, 0, NULL, 0);
+    ilm.src_mod_id = MOD_UPCM;
+    ilm.dest_mod_id = MOD_IPCORE;
+    ilm.sap_id = IPCORE_SAP;
+    ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+    ilm.local_para_ptr = (local_para_struct *)deact_req;
+    ilm.peer_buff_ptr = NULL;
+    ipc_on_ilm(&ilm);
+    free_local_para((local_para_struct *)deact_req);
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_dl_meta_table_threshold(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    ipc_ut_netif_t   *net;
+    kal_uint32        netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool          result;
+    ilm_struct        ilm;
+    kal_uint32        ipv4_cnt;
+    kal_uint32        ipv6_cnt;
+    kal_uint32        ipv4_filter_cnt;
+    kal_uint32        ipv6_filter_cnt;
+    kal_uint8         matched_filter_idx_v4;
+    kal_uint8         matched_filter_idx_v6;
+    kal_uint32        callback_with_info;
+    kal_uint32        total_cnt;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * ipc_attach()
+     */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 5; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 7; ipv6_cnt++)
+    for (ipv4_filter_cnt = 0; ipv4_filter_cnt <= 4; ipv4_filter_cnt++)
+    for (ipv6_filter_cnt = 0; ipv6_filter_cnt <= 4; ipv6_filter_cnt++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < ipv4_filter_cnt; matched_filter_idx_v4++)
+    for (matched_filter_idx_v6 = 0; matched_filter_idx_v6 < ipv6_filter_cnt; matched_filter_idx_v6++) {
+        if ((0 == ipv4_cnt) && (0 == ipv6_cnt)) continue;
+
+        utDLOG("ifo(%d) v4Cnt(%d) v6Cnt(%d) v4FltCnt(%d) v6FltCnt(%d) v4Idx(%d) v6Idx(%d)\r\n",
+               callback_with_info, ipv4_cnt, ipv6_cnt, ipv4_filter_cnt , ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6);
+
+        total_cnt = ipv4_cnt + ipv6_cnt;
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Install DL filter for each test loop */
+        ipc_ut_install_dl_filters(callback_with_info, KAL_TRUE, ipv4_filter_cnt, ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6, IPC_UT_LHIF_NETID_START);
+
+        ipc_ut_dl_ipf_match_filter_id_v4_s = matched_filter_idx_v4;
+        ipc_ut_dl_ipf_match_filter_id_v6_s = ipv4_filter_cnt + matched_filter_idx_v6;
+
+        /* Before PDN Binding */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            /* Before PDN Binding, IPF will only report PN not mtach case or NETIF invalid case */
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_pkt_cnt;
+
+                utDLOG("@ Before activation : match_result(%d)\r\n", match_result);
+
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_pkt_cnt = total_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) || (match_result == IPC_IPF_MR_PN_NO_MATCH)) {
+                    expected_pkt_cnt = 0;
+                }
+
+                /* Make sure no DL callback to HIF */
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Check if IPCore will release buffer when NETIF is invalid */
+                /* PN_NO_MATCH & DIRECT_TO_AP no need to free buffer */
+                if ( expected_pkt_cnt != ipc_ut_dl_meta_buf_free_num_s ) {
+                    utELOG("DL buffer is not released before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Activate IPv4 PDN with unspecified IP address & from different MOD_UPCM_X.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         *   Simulate DL traffic from IPCore : All meta should be forward to either DL callback or filter callback(IPv4/IPv6)
+         */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            /* Before PDN Binding, IPF will only report PN not mtach case or NETIF invalid case */
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_dl_v4_filter_out_cnt;
+                kal_uint32 expected_dl_v6_filter_out_cnt;
+                kal_uint32 expected_dl_filter_out_cnt;
+                kal_uint32 did_cnt;
+                kal_uint32 expected_dl_forwad_cnt;
+
+                utDLOG("@ PDN connected : match_result(%d)\r\n", match_result);
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_dl_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                  (ipv4_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))? 1:0;
+                expected_dl_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                  (ipv6_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))?1:0;
+
+                expected_dl_filter_out_cnt = expected_dl_v4_filter_out_cnt + expected_dl_v6_filter_out_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) ||
+                    (match_result == IPC_IPF_MR_PN_NO_MATCH) ||
+                    (match_result == IPC_IPF_MR_NET_INVALID)) {
+                    did_cnt = expected_dl_forwad_cnt = 0;
+                }
+                else {
+                    did_cnt = total_cnt-expected_dl_filter_out_cnt; //Supposed one DID only contains one packet
+                    expected_dl_forwad_cnt = total_cnt-expected_dl_filter_out_cnt;
+                }
+
+                if (expected_dl_filter_out_cnt > 0) {
+                    if (callback_with_info) {
+                        if (ipc_ut_dl_filter_info.netif_id != IPC_UT_LHIF_NETID_START) {
+                            utELOG("Filtered-out netif ID is incorrect!\r\n");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                        if (ipc_ut_dl_filter_info.ebi != -1) {
+                            utELOG("Filtered-out EBI is incorrect!\r\r");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                    }
+                    else {
+                        if (ipc_ut_dl_filter_info.netif_id != 0) {
+                            utELOG("Filtered-out netif ID is incorrect!\r\n");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                        if (ipc_ut_dl_filter_info.ip_id != -1) {
+                            utELOG("Filtered-out IP ID is incorrect!\r\r");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                    }
+                }
+
+
+                if (ipc_ut_dl_filter_gpd_cnt != expected_dl_filter_out_cnt) {
+                    utELOG("Filtered-out gpd count is incorrect!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                    return KAL_FALSE;
+                }
+
+                if ( (did_cnt != ipc_ut_dl_callback_did_cnt) ||
+                     (expected_dl_forwad_cnt != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is NOT forwarded to bound handler!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+
+        /*
+         *   Simulate DL traffic to IPCore : After PDN deactivation, all meta should be silently dropped by IPCore and NO callback is triggered
+         */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_pkt_cnt;
+
+                utDLOG("@ PDN deactivated : dhcpv4Idx(%d), dhcpv6Idx(%d), match_result(%d)\r\n",
+                                0, 0, match_result);
+
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_pkt_cnt = total_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) || (match_result == IPC_IPF_MR_PN_NO_MATCH)) {
+                    expected_pkt_cnt = 0;
+                }
+
+                /* Make sure no DL callback to HIF */
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded when PDN deactivated!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Check if IPCore will release buffer when NETIF is invalid */
+                /* PN_NO_MATCH & DIRECT_TO_AP no need to free buffer */
+                if ( expected_pkt_cnt != ipc_ut_dl_meta_buf_free_num_s ) {
+                    utELOG("DL buffer is not released when PDN deactivated!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+    }
+
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+kal_bool ipc_ut_data_usage(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    ipcore_upcm_pdn_bind_ind_struct *bind_req = NULL;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req = NULL;
+    ipc_ut_netif_t   *net;
+    kal_uint32        netif_id = IPC_UT_LHIF_NETID_START;
+    kal_bool          result;
+    ilm_struct        ilm;
+    kal_uint32        ipv4_cnt;
+    kal_uint32        ipv6_cnt;
+    kal_uint32        ipv4_filter_cnt;
+    kal_uint32        ipv6_filter_cnt;
+    kal_uint8         matched_filter_idx_v4;
+    kal_uint8         matched_filter_idx_v6;
+    kal_uint32        callback_with_info;
+    kal_uint32        total_cnt;
+
+    /* init before test */
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /*
+     * ipc_attach()
+     */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = netif_id;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    for (callback_with_info = 0 ; callback_with_info < 2 ; callback_with_info ++)
+    for (ipv4_cnt = 0; ipv4_cnt <= 5; ipv4_cnt++)
+    for (ipv6_cnt = 0; ipv6_cnt <= 7; ipv6_cnt++)
+    for (ipv4_filter_cnt = 0; ipv4_filter_cnt <= 4; ipv4_filter_cnt++)
+    for (ipv6_filter_cnt = 0; ipv6_filter_cnt <= 4; ipv6_filter_cnt++)
+    for (matched_filter_idx_v4 = 0; matched_filter_idx_v4 < ipv4_filter_cnt; matched_filter_idx_v4++)
+    for (matched_filter_idx_v6 = 0; matched_filter_idx_v6 < ipv6_filter_cnt; matched_filter_idx_v6++) {
+        if ((0 == ipv4_cnt) && (0 == ipv6_cnt)) continue;
+
+        utDLOG("ifo(%d) v4Cnt(%d) v6Cnt(%d) v4FltCnt(%d) v6FltCnt(%d) v4Idx(%d) v6Idx(%d)\r\n",
+               callback_with_info, ipv4_cnt, ipv6_cnt, ipv4_filter_cnt , ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6);
+
+        total_cnt = ipv4_cnt + ipv6_cnt;
+
+        ipc_ut_set_error(IPC_UT_NO_ERROR);
+
+        /* Install DL filter for each test loop */
+        ipc_ut_install_dl_filters(callback_with_info, KAL_TRUE, ipv4_filter_cnt, ipv6_filter_cnt, matched_filter_idx_v4, matched_filter_idx_v6, IPC_UT_LHIF_NETID_START);
+
+        ipc_ut_dl_ipf_match_filter_id_v4_s = matched_filter_idx_v4;
+        ipc_ut_dl_ipf_match_filter_id_v6_s = ipv4_filter_cnt + matched_filter_idx_v6;
+
+        /* Before PDN Binding */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            /* Before PDN Binding, IPF will only report PN not mtach case or NETIF invalid case */
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_pkt_cnt;
+
+                utDLOG("@ Before activation : match_result(%d)\r\n", match_result);
+
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_pkt_cnt = total_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) || (match_result == IPC_IPF_MR_PN_NO_MATCH)) {
+                    expected_pkt_cnt = 0;
+                }
+
+                /* Make sure no DL callback to HIF */
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Check if IPCore will release buffer when NETIF is invalid */
+                /* PN_NO_MATCH & DIRECT_TO_AP no need to free buffer */
+                if ( expected_pkt_cnt != ipc_ut_dl_meta_buf_free_num_s ) {
+                    utELOG("DL buffer is not released before PDN binding!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Activate IPv4v6 PDN with unspecified IP address & from different MOD_UPCM_X.
+         */
+        bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+        bind_req->network_interface_id = net->conf.netif_id;
+        bind_req->pdn_id = IPC_UT_PDN_ID;
+        bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_BIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)bind_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+        if (ipc_ut_msg_chk(MOD_IPCORE, MOD_UPCM, IPCORE_SAP, MSG_ID_IPCORE_UPCM_PDN_BIND_RSP, 2) != KAL_TRUE) {
+            utELOG("Bind response is not received\r\n");
+            return KAL_FALSE;
+        }
+
+        /*
+         *   Simulate DL traffic from IPCore : All meta should be forward to either DL callback or filter callback(IPv4/IPv6)
+         */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            /* After PDN Binding*/
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_dl_v4_filter_out_cnt;
+                kal_uint32 expected_dl_v6_filter_out_cnt;
+                kal_uint32 expected_dl_filter_out_cnt;
+                kal_uint32 did_cnt;
+                kal_uint32 expected_dl_forwad_cnt;
+
+                utDLOG("@ PDN connected : match_result(%d)\r\n", match_result);
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_dl_v4_filter_out_cnt = ( (ipv4_filter_cnt > 0) &&
+                                                  (ipv4_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))? 1:0;
+                expected_dl_v6_filter_out_cnt = ( (ipv6_filter_cnt > 0) &&
+                                                  (ipv6_cnt > 0) &&
+                                                  (match_result != IPC_IPF_MR_DIRECT_TO_AP) &&
+                                                  (match_result != IPC_IPF_MR_PN_NO_MATCH) &&
+                                                  (match_result != IPC_IPF_MR_NET_INVALID))?1:0;
+
+                expected_dl_filter_out_cnt = expected_dl_v4_filter_out_cnt + expected_dl_v6_filter_out_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) ||
+                    (match_result == IPC_IPF_MR_PN_NO_MATCH) ||
+                    (match_result == IPC_IPF_MR_NET_INVALID)) {
+                    did_cnt = expected_dl_forwad_cnt = 0;
+                }
+                else {
+                    did_cnt = total_cnt-expected_dl_filter_out_cnt; //Supposed one DID only contains one packet
+                    expected_dl_forwad_cnt = total_cnt-expected_dl_filter_out_cnt;
+                }
+
+                if (expected_dl_filter_out_cnt > 0) {
+                    if (callback_with_info) {
+                        if (ipc_ut_dl_filter_info.netif_id != IPC_UT_LHIF_NETID_START) {
+                            utELOG("Filtered-out netif ID is incorrect!\r\n");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                        if (ipc_ut_dl_filter_info.ebi != -1) {
+                            utELOG("Filtered-out EBI is incorrect!\r\r");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                    }
+                    else {
+                        if (ipc_ut_dl_filter_info.netif_id != 0) {
+                            utELOG("Filtered-out netif ID is incorrect!\r\n");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                        if (ipc_ut_dl_filter_info.ip_id != -1) {
+                            utELOG("Filtered-out IP ID is incorrect!\r\r");
+                            ipc_ut_free_gpd_list(NULL, NULL);
+                            ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                            return KAL_FALSE;
+                        }
+                    }
+                }
+
+
+                if (ipc_ut_dl_filter_gpd_cnt != expected_dl_filter_out_cnt) {
+                    utELOG("Filtered-out gpd count is incorrect!\r\r");
+                    ipc_ut_free_gpd_list(NULL, NULL);
+                    ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+                    return KAL_FALSE;
+                }
+
+                if ( (did_cnt != ipc_ut_dl_callback_did_cnt) ||
+                     (expected_dl_forwad_cnt != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is NOT forwarded to bound handler!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /*Get Data usage*/
+                ipc_data_usage_info_t data_usage = {0};
+                ipc_get_data_usage_by_netif_id(net->conf.netif_id, &data_usage);
+
+                /* Free GPD after test */
+                ipc_ut_free_gpd_list(NULL, NULL);
+            }
+        }
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        /*
+         * PDN deactivation.
+         */
+        deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+        deact_req->pdn_id = IPC_UT_PDN_ID;
+
+        ipc_ut_msg_reset(NULL, 0, NULL, 0);
+        ilm.src_mod_id = MOD_UPCM;
+        ilm.dest_mod_id = MOD_IPCORE;
+        ilm.sap_id = IPCORE_SAP;
+        ilm.msg_id = MSG_ID_IPCORE_UPCM_PDN_UNBIND_IND;
+        ilm.local_para_ptr = (local_para_struct *)deact_req;
+        ilm.peer_buff_ptr = NULL;
+        ipc_on_ilm(&ilm);
+
+        /*
+         *   Simulate DL traffic to IPCore : After PDN deactivation, all meta should be silently dropped by IPCore and NO callback is triggered
+         */
+        {
+            kal_uint32 head_idx;
+            kal_uint32 tail_idx;
+            ipfc_dl_filter_queue_type q_type;
+            kal_uint8 match_result;
+
+            for (match_result = IPC_IPF_MR_DIRECT_TO_AP ; match_result < IPC_IPF_MR_DPFM_MATCH ; match_result++) {
+                kal_uint32 expected_pkt_cnt;
+
+                utDLOG("@ PDN deactivated : dhcpv4Idx(%d), dhcpv6Idx(%d), match_result(%d)\r\n",
+                                0, 0, match_result);
+
+                ipc_ut_prepare_dl_meta_list(KAL_TRUE, ipv4_cnt, 0, ipv6_cnt, 0, &head_idx, &tail_idx, &q_type, netif_id, match_result);
+
+                /* Send IOR into IP Core */
+                ipc_ut_reset_dl_callback_info();
+                ipc_ut_reset_dl_filter_info();
+
+                ipc_meta_downlink(head_idx, tail_idx, q_type);
+                kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+                expected_pkt_cnt = total_cnt;
+
+                if ((match_result == IPC_IPF_MR_DIRECT_TO_AP) || (match_result == IPC_IPF_MR_PN_NO_MATCH)) {
+                    expected_pkt_cnt = 0;
+                }
+
+                /* Make sure no DL callback to HIF */
+                if ( (0 != ipc_ut_dl_callback_did_cnt) ||
+                     (0 != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                    utELOG("DL DID is forwarded when PDN deactivated!\r\n");
+                    return KAL_FALSE;
+                }
+
+                /* Check if IPCore will release buffer when NETIF is invalid */
+                /* PN_NO_MATCH & DIRECT_TO_AP no need to free buffer */
+                if ( expected_pkt_cnt != ipc_ut_dl_meta_buf_free_num_s ) {
+                    utELOG("DL buffer is not released when PDN deactivated!\r\n");
+                    return KAL_FALSE;
+                }
+            }
+        }
+
+        /*
+         * Free the ILM.
+         */
+        destroy_ilm(&ilm);
+
+        ipc_ut_uninstall_dl_filters(ipv4_filter_cnt, ipv6_filter_cnt);
+    }
+
+    /*
+     * ipc_detach().
+     */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+static void ipc_ut_pfm_garbage_str_wake_type_pkt_cbk(const kal_uint8 *packet, kal_int32 packet_len, kal_int32 pfm_filter_id, void* priv_data)
+{
+    utDLOG("Packet_buff(0x%x),len(%d),pfm_filter_id(%d),priv_data(0x%x),g_mbim_priv_data(0x%x)\r\n", packet, packet_len, pfm_filter_id, priv_data, &g_mbim_priv_data);
+    if(priv_data != &g_mbim_priv_data){
+        utELOG("wrong expected mbim priv_data!\r\n");
+        g_mbim_priv_data = IPC_UT_INAVLID_PRIV_DATA;
+    }
+    return;
+}
+
+kal_bool ipc_ut_str_garbage_filter_with_wakeup_pkt_cbk(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    pfm_filter_set_t filter_set;
+    local_para_struct *local_para_ptr;
+    peer_buff_struct *peer_buff_ptr;
+    pfm_str_filter_t *filter_info;
+    kal_uint8 i;
+    kal_uint8 *pdu_ptr;
+    kal_uint16 peer_buf_len;
+    ipc_ut_netif_t *net;
+    ipcore_upcm_pdn_bind_ind_struct *bind_req;
+    ipcore_upcm_pdn_unbind_ind_struct *deact_req;
+    static kal_uint8 ipv4_mask[192] = {0};
+    static kal_uint8 ipv6_mask[192] = {0};
+    kal_bool result;
+    kal_int32 *filter_id;
+
+    // init before test
+    ipc_ut_init();
+
+    /*
+     *   Reset IPCore before test
+     */
+    if (KAL_TRUE != ipc_reset()) {
+        utELOG("ipc_reset() FAIL!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* ipc_attach() */
+    net = &(ipc_ut_nets_s[0]);
+    kal_mem_set(net, 0, sizeof(ipc_ut_netif_t));
+    net->conf.module_id = MOD_IPCORE;
+    net->conf.netif_id = IPC_UT_LHIF_NETID_START;
+    net->conf.ul_reload_context = net;
+    net->conf.ipc_ul_reload_callback_t = ipc_ut_ul_reload;
+    net->conf.callback_context = net;
+    net->conf.ipc_dlink_did_cb_t = ipc_ut_dl_callback_did;
+    net->conf.features = 0;
+    result = ipc_attach(&net->conf, &net->handle);
+    if (!result) {
+        utELOG("ipc_attach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    /* PDN activation. */
+    bind_req = (ipcore_upcm_pdn_bind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_bind_ind_struct), TD_RESET);
+    bind_req->network_interface_id = net->conf.netif_id;
+    bind_req->pdn_id = IPC_UT_PDN_ID;
+    bind_req->ip_addr.ip_addr_type = IPV4V6_ADDR_TYPE;
+    ipc_on_pdn_bind_top(MOD_NIL, (local_para_struct *)bind_req);
+    free_local_para((local_para_struct *)bind_req);
+
+    /*
+     *   Register 0-7 IPv4 filter, 8-16 IPv6 filter
+     */
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_STR_FILTER_SET_ID;
+    filter_set.filter_cnt = 16;
+    filter_set.uplink = KAL_FALSE;
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ((kal_uint8*)&filter_set)+4, sizeof(filter_set) - 4); // shift local_para_ptr header
+
+    /* Init mask */
+    ipv4_mask[0] = ipv6_mask[0] = 0xF0; /* IP version */
+    ipv4_mask[8] = ipv6_mask[6] = 0xFF; /* Protocol */
+    ipv4_mask[22] = ipv4_mask[23] = ipv6_mask[42] = ipv6_mask[43] = 0xFF; /* L4 dest port */
+
+    peer_buff_ptr = construct_peer_buff(sizeof(pfm_str_filter_t)*16, 0, 0, TD_RESET);
+    if (!peer_buff_ptr) {
+        utDLOG("peer_buff_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    pdu_ptr = get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+
+    filter_info = (pfm_str_filter_t*)pdu_ptr;
+    for(i = 0; i < 16; i++){
+        filter_info->filter_id = i;
+        filter_info->magic_code = 0x1798; //PFM_STR_FILTER_MAGIC_CODE
+        filter_info->mask_len = 192;
+        filter_info->netif_id = IPC_UT_LHIF_NETID_START;
+        if( i < 8){
+            /* IPv4 filter pattern */
+            filter_info->filter_len = sizeof(ipc_ut_ipv4_tcp_ack_packet);
+
+            kal_mem_cpy(filter_info->mask, ipv4_mask, 192);
+            kal_mem_cpy(filter_info->filter, ipc_ut_ipv4_tcp_ack_packet, sizeof(ipc_ut_ipv4_tcp_ack_packet));
+
+            if(0 != i){
+                /* Not first pattern, increase dst port value (ipv4) */
+                filter_info->filter[23]++;
+                if(0 == filter_info->filter[23]){
+                    filter_info->filter[22]++;
+                }
+            }
+        }else{
+            /* IPv6 filter pattern */
+            filter_info->filter_len = sizeof(ipc_ut_ipv6_udp_packet);
+
+            kal_mem_cpy(filter_info->mask, ipv6_mask, 192);
+            kal_mem_cpy(filter_info->filter, ipc_ut_ipv6_udp_packet, sizeof(ipc_ut_ipv6_udp_packet));
+            if(8 != i){
+                /* Not first pattern, increase dst port value (ipv4) */
+                filter_info->filter[42]++;
+                if(0 == filter_info->filter[42]){
+                    filter_info->filter[43]++;
+                }
+            }
+        }
+        filter_info = filter_info+1;
+    }
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+          MOD_IPCORE, /* dest_mod_id */
+          IPCORE_SAP, /* sap_id */
+          MSG_ID_PFM_REGISTER_FILTER_REQ, /* msg_id */
+          local_para_ptr, /* local_para_ptr */
+          peer_buff_ptr); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*register callback for pfm garbage str matched wake type packet*/
+    pfm_garbage_str_wake_type_pkt_f pf_wake_type_pkt = ipc_ut_pfm_garbage_str_wake_type_pkt_cbk;
+    pfm_reg_cbk_wake_type_pkt(pf_wake_type_pkt, &g_mbim_priv_data);
+
+    /* Simulate DL traffic to IPCore : Only data matched garbage filter should be forward to DL callback regardless of IP types (IPv4/IPv6) */
+    {
+        kal_uint32 ipv4_cnt;
+        kal_uint32 ipv6_cnt;
+        kal_uint32 total_cnt;
+        kal_uint32 did_cnt;
+        upcm_did *did_head;
+        upcm_did *did_tail;
+        kal_uint32 alignment;
+        kal_uint32 ipv4_idx;
+        kal_uint32 ipv6_idx;
+        kal_uint32 did_remain_cnt, gpd_remain_cnt_dl;
+
+        for (alignment = 0 ; alignment < 4 ; alignment ++)
+        for (ipv4_cnt = 0; ipv4_cnt <= 3; ipv4_cnt++)
+        for (ipv6_cnt = 0; ipv6_cnt <= 3; ipv6_cnt++) 
+        for (ipv4_idx = 0; ipv4_idx < ipv4_cnt; ipv4_idx++)
+        for (ipv6_idx = 0; ipv6_idx < ipv6_cnt; ipv6_idx++) {
+            if (0 == ipv4_cnt && 0 == ipv6_cnt) continue;
+
+            utDLOG("v4_cnt(%d),v6_cnt(%d),ipv4_idx(%d),ipv6_idx(%d),alignment(%d)\r\n", ipv4_cnt, ipv6_cnt, ipv4_idx, ipv6_idx, alignment);
+
+            did_cnt = (ipv4_cnt == 0 || ipv6_cnt == 0) ? 1 : 2;
+            total_cnt = ipv4_cnt + ipv6_cnt;
+
+            ipc_ut_reset_dl_callback_info();
+            ipc_ut_reset_dl_filter_info();
+
+            /*Store DID remain cnt */
+            did_remain_cnt = upcm_did_get_buff_remain_num();
+
+            /*Store GPD remain cnt */
+            gpd_remain_cnt_dl = qbm_get_buff_remain_num(QBM_TYPE_NET_DL);
+            
+            ipc_ut_prepare_dl_did_list_garbage(ipv4_cnt,
+                                               ipv6_cnt,
+                                               ipv4_idx,
+                                               ipv6_idx,
+                                               alignment,
+                                               &did_head,
+                                               &did_tail,
+                                               did_cnt);
+
+            /* simulate DL traffic from IPC_UT_PDN_ID */
+            ipc_on_did_downlink_multiple_ps(IPC_UT_PDN_ID, did_head, did_tail, 0);
+
+            if (g_mbim_priv_data == IPC_UT_INAVLID_PRIV_DATA) {
+                utELOG("Invalid mbim priv_data!\r\n");
+                return KAL_FALSE;
+            }
+
+            if ( (did_cnt != ipc_ut_dl_callback_did_cnt) ||
+                 (ipc_ut_str_garbage_expect_host_cnt != ipc_ut_dl_callback_did_pkt_cnt) ) {
+                utELOG("DL PKT is NOT forwarded to bound handler!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(gpd_remain_cnt_dl != qbm_get_buff_remain_num(QBM_TYPE_NET_DL)){
+                utELOG("wrong expected QBM_TYPE_NET_DL GPD count!\r\n");
+                return KAL_FALSE;
+            }
+
+            if(did_remain_cnt != upcm_did_get_buff_remain_num()){
+                utELOG("wrong expected DID count!\r\n");
+                return KAL_FALSE;
+            }
+
+            ipc_ut_str_garbage_expect_host_cnt = 0;
+        }
+    }
+
+   /*
+     *   Deregister half of filters (0~7)
+     */
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_STR_FILTER_SET_ID;
+    filter_set.filter_cnt = 8;
+    filter_set.uplink = KAL_FALSE;
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ((kal_uint8*)&filter_set)+4, sizeof(filter_set) - 4); // shift local_para_ptr header
+
+    peer_buff_ptr = construct_peer_buff(sizeof(kal_int32)*8, 0, 0, TD_RESET);
+    if (!peer_buff_ptr) {
+        utDLOG("peer_buff_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    pdu_ptr = get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+
+    filter_id = (kal_int32*) pdu_ptr;
+    for (i = 0; i < 8; i++) {
+        *filter_id = (kal_int32) i;
+        filter_id++;
+    }
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_PFM_DEREGISTER_FILTER_REQ, /* msg_id */
+              local_para_ptr, /* local_para_ptr */
+              peer_buff_ptr); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     *   Register filter_id 0~7. Half of them should not be removed yet.
+     */
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_STR_FILTER_SET_ID;
+    filter_set.filter_cnt = 8;
+    filter_set.uplink = KAL_FALSE;
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ((kal_uint8*)&filter_set)+4, sizeof(filter_set) - 4); // shift local_para_ptr header
+
+    peer_buff_ptr = construct_peer_buff(sizeof(pfm_str_filter_t)*8, 0, 0, TD_RESET);
+    if (!peer_buff_ptr) {
+        utDLOG("peer_buff_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    pdu_ptr = get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+
+    filter_info = (pfm_str_filter_t*)pdu_ptr;
+    for(i = 0; i < 8; i++){
+        filter_info->filter_id = i;
+        filter_info->magic_code = 0x1798; //PFM_STR_FILTER_MAGIC_CODE
+        filter_info->mask_len = 192;
+        filter_info->netif_id = IPC_UT_LHIF_NETID_START;
+
+        /* IPv4 filter pattern */
+        filter_info->filter_len = sizeof(ipc_ut_ipv4_tcp_ack_packet);
+
+        kal_mem_cpy(filter_info->mask, ipv4_mask, 192);
+        kal_mem_cpy(filter_info->filter, ipc_ut_ipv4_tcp_ack_packet, sizeof(ipc_ut_ipv4_tcp_ack_packet));
+
+        if(0 != i){
+            /* Not first pattern, increase dst port value (ipv4) */
+            filter_info->filter[23]++;
+            if(0 == filter_info->filter[23]){
+                filter_info->filter[22]++;
+            }
+        }
+        filter_info = filter_info+1;
+    }
+
+    msg_send6(MOD_NIL, /* src_mod_id */
+          MOD_IPCORE, /* dest_mod_id */
+          IPCORE_SAP, /* sap_id */
+          MSG_ID_PFM_REGISTER_FILTER_REQ, /* msg_id */
+          local_para_ptr, /* local_para_ptr */
+          peer_buff_ptr); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*
+     *   Deregister all filters
+     */
+    kal_mem_set(&filter_set, 0, sizeof(filter_set));
+    filter_set.filter_set_id = PFM_GARBAGE_STR_FILTER_SET_ID;
+    filter_set.filter_cnt = -1;
+    filter_set.uplink = KAL_FALSE;
+
+    local_para_ptr = construct_local_para(sizeof(filter_set), TD_RESET);
+    if (!local_para_ptr) {
+        utDLOG("local_para_ptr is NULL!\r\n");
+        return KAL_FALSE;
+    }
+    kal_mem_cpy(local_para_ptr + 1, ((kal_uint8*)&filter_set)+4, sizeof(filter_set) - 4); // shift local_para_ptr header
+    
+    msg_send6(MOD_NIL, /* src_mod_id */
+              MOD_IPCORE, /* dest_mod_id */
+              IPCORE_SAP, /* sap_id */
+              MSG_ID_PFM_DEREGISTER_FILTER_REQ, /* msg_id */
+              local_para_ptr, /* local_para_ptr */
+              NULL); /* peer_buff_ptr */
+    kal_sleep_task(IPC_UT_MSG_LATENCY);
+
+    /*De-register callback for pfm garbage str matched wake type packet*/
+    pfm_dereg_cbk_wake_type_pkt();
+
+    /* PDN deactivation. */
+    deact_req = (ipcore_upcm_pdn_unbind_ind_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_unbind_ind_struct), TD_RESET);
+    deact_req->pdn_id = IPC_UT_PDN_ID;
+    ipc_on_pdn_unbind((local_para_struct *)deact_req);
+    free_local_para((local_para_struct *)deact_req);
+
+    /* ipc_detach(). */
+    result = ipc_detach(net->handle);
+    if (!result) {
+        utELOG("ipc_detach() returns KAL_FALSE!\r\n");
+        return KAL_FALSE;
+    }
+
+    IPC_UT_PASS();
+    return KAL_TRUE;
+}
+
+/*------------------------------------------------------------------------------
+ * Public functions.
+ *----------------------------------------------------------------------------*/
+#define IPC_UT_CASE(_func, _param) { #_func, _func, _param }
+
+kal_bool ipc_ut_st_create(void) {
+    static ST_TCASE_T ipc_ut_cases_s[] = {
+
+#if defined(__MTK_TARGET__)
+        IPC_UT_CASE(ipc_ut_struct, NULL),
+#endif
+        IPC_UT_CASE(ipc_ut_helper_macro, NULL),
+        IPC_UT_CASE(ipc_ut_checksum, NULL),
+        IPC_UT_CASE(ipc_ut_attach, NULL),
+        IPC_UT_CASE(ipc_ut_find_netif, NULL),
+        IPC_UT_CASE(ipc_ut_pdn_bind_deact, NULL),
+        IPC_UT_CASE(ipc_ut_new_session, NULL),
+        IPC_UT_CASE(ipc_ut_find_session, NULL),
+        IPC_UT_CASE(ipc_ut_poll_source, NULL),
+        IPC_UT_CASE(ipc_ut_ul_reload_retry, NULL),
+        IPC_UT_CASE(ipc_ut_del_session, NULL),
+        IPC_UT_CASE(ipc_ut_detach, NULL),
+        IPC_UT_CASE(ipc_ut_pdn_ip_info, NULL),
+        IPC_UT_CASE(ipc_ut_query_info, NULL),
+        IPC_UT_CASE(ipc_ut_rebind_pdn, NULL),
+        IPC_UT_CASE(ipc_ut_ipc_fragment, NULL),
+        IPC_UT_CASE(ipc_ut_ul_throttle, NULL),
+        IPC_UT_CASE(ipc_ut_ul_throttle_ims_emergency, NULL),
+        IPC_UT_CASE(ipc_ut_pdn_sim_macro, NULL),
+#if defined(__IPCORE_SUPPORT__) && !defined(IPCORE_NOT_PRESENT) && defined(__CCCICCMNI_SUPPORT__)
+        IPC_UT_CASE(ipc_ut_triggered_ul_reload, NULL),
+    #if (IPC_UT_GEN_INVALID_LEN_PKT)
+        IPC_UT_CASE(ipc_ut_downlink_invalid_packet, NULL),
+    #endif
+#endif
+        IPC_UT_CASE(ipc_ut_downlink_wo_dhcp4c, NULL),
+        IPC_UT_CASE(ipc_ut_uplink_filter, NULL),
+        IPC_UT_CASE(ipc_ut_link_notification, NULL),
+        IPC_UT_CASE(ipc_ut_link_status_ind, NULL),
+#if !defined(__SMART_PHONE_MODEM__)
+        IPC_UT_CASE(ipc_ut_downlink_w_dhcp4c, NULL),
+        IPC_UT_CASE(ipc_ut_ipv4_status_ind, NULL),
+        IPC_UT_CASE(ipc_ut_en_dhcp4c_unspecified_addr, NULL),
+        IPC_UT_CASE(ipc_ut_en_dhcp4c_valid_addr, NULL),
+        IPC_UT_CASE(ipc_ut_did_downlink_w_dhcp4c, NULL),
+#endif
+        IPC_UT_CASE(ipc_ut_dis_dhcp4c_unspecified_addr, NULL),
+        IPC_UT_CASE(ipc_ut_ul_filter_registration, NULL),
+        IPC_UT_CASE(ipc_ut_dl_filter_registration, NULL),
+        IPC_UT_CASE(ipc_ut_ul_filter_none, NULL),
+        IPC_UT_CASE(ipc_ut_dl_filter_none, NULL),
+        IPC_UT_CASE(ipc_ut_ul_filter_ipv4, NULL),
+        IPC_UT_CASE(ipc_ut_dl_filter_ipv4, NULL),
+        IPC_UT_CASE(ipc_ut_ul_filter_ipv6, NULL),
+        IPC_UT_CASE(ipc_ut_dl_filter_ipv6, NULL),
+        IPC_UT_CASE(ipc_ut_ul_filter_and_forward_msg, NULL),
+        IPC_UT_CASE(ipc_ut_dl_filter_and_forward_msg, NULL),
+        IPC_UT_CASE(ipc_ut_gpd_copy, NULL),
+        IPC_UT_CASE(ipc_ut_send_ul_pkt, NULL),
+        IPC_UT_CASE(ipc_ut_send_dl_pkt, NULL),
+        IPC_UT_CASE(ipc_ut_garbage_filter, NULL),
+        IPC_UT_CASE(ipc_ut_downlink_multiple_ps, NULL),
+        IPC_UT_CASE(ipc_ut_uplink_multiple_ps, NULL),
+        IPC_UT_CASE(ipc_ut_send_ul_pkt_multiple_ps, NULL),
+        IPC_UT_CASE(ipc_ut_meta_uplink, NULL),
+        IPC_UT_CASE(ipc_ut_did_downlink, NULL),
+        IPC_UT_CASE(ipc_ut_uplink_filter_meta, NULL),
+        IPC_UT_CASE(ipc_ut_did_downlink_wo_dhcp4c, NULL),
+        IPC_UT_CASE(ipc_ut_fin_ack_filter_did, NULL),
+        IPC_UT_CASE(ipc_ut_meta_downlink, NULL),
+        IPC_UT_CASE(ipc_ut_ul_throttle_plmn, NULL),
+        IPC_UT_CASE(ipc_ut_new_filter_verification, NULL),
+        IPC_UT_CASE(ipc_ut_esp_parser, NULL),
+        IPC_UT_CASE(ipc_ut_cust_filter, NULL),
+        IPC_UT_CASE(ipc_ut_esp_filter, NULL),
+        IPC_UT_CASE(ipc_ut_did_retry_put_head_queue, NULL),
+        IPC_UT_CASE(ipc_ut_ul_udp_igmp_filter, NULL),
+
+#if defined(__MD97__)
+        IPC_UT_CASE(ipc_ut_send_did_by_ch_id, NULL),
+        IPC_UT_CASE(ipc_ut_sdap_meta_downlink, NULL),
+        IPC_UT_CASE(ipc_ut_nr_did_downlink, NULL),
+#endif
+
+#ifdef __IPC_95_ACK_REDUCTION_SUPPORT__
+        IPC_UT_CASE(ipc_ut_uplink_ack_reduction, NULL),
+#endif
+
+#if defined(__MD_DIRECT_TETHERING_SUPPORT__)
+        IPC_UT_CASE(ipc_ut_meta_uplink_dpfm, NULL),
+        IPC_UT_CASE(ipc_ut_did_downlink_dpfm, NULL),
+        IPC_UT_CASE(ipc_ut_meta_uplink_dpfm_cmd_after_detach, NULL),
+#endif
+
+        IPC_UT_CASE(ipc_ut_downlink_tcprst_packet, NULL),
+        IPC_UT_CASE(ipc_ut_downlink_test_udp_drop_packet, NULL),
+        IPC_UT_CASE(ipc_ut_dl_filter_ra_pkt_did, NULL),
+        IPC_UT_CASE(ipc_ut_dl_filter_ra_pkt_did_w_dynamic_q, NULL),
+        IPC_UT_CASE(ipc_ut_str_garbage_filter, NULL),
+        IPC_UT_CASE(ipc_ut_meta_downlink_with_statistics, NULL),
+        IPC_UT_CASE(ipc_ut_dl_filter_fragments, NULL),
+        IPC_UT_CASE(ipc_ut_ra_dl, NULL),
+        IPC_UT_CASE(ipc_ut_rs_ul, NULL),
+        IPC_UT_CASE(ipc_ut_send_dl_pkt_force, NULL),
+        IPC_UT_CASE(ipc_ut_downlink_test_udp_drop_large_packet, NULL),
+        IPC_UT_CASE(ipc_ut_dl_frag_refilter_with_cust_feature, NULL),
+        IPC_UT_CASE(ipc_ut_dl_meta_table_threshold, NULL),
+        IPC_UT_CASE(ipc_ut_data_usage, NULL),
+        IPC_UT_CASE(ipc_ut_meta_downlink_with_large_pkt, NULL),
+        IPC_UT_CASE(ipc_ut_str_garbage_filter_with_wakeup_pkt_cbk, NULL),
+    };
+
+    return st_reg_test("IPCORE", &(ipc_ut_cases_s[0]), (sizeof(ipc_ut_cases_s)/sizeof(ST_TCASE_T)));
+}
+
+#endif /* ATEST_SYS_IPCORE */
diff --git a/mcu/middleware/hif/ipcore/src/ipc_ut_ilm.c b/mcu/middleware/hif/ipcore/src/ipc_ut_ilm.c
new file mode 100644
index 0000000..8eb7236
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_ut_ilm.c
@@ -0,0 +1,116 @@
+/*
+ * ipc_ut_ilm.c
+ *
+ *  Created on: 2018/2/26
+ *      Author: MTK15439
+ */
+
+#include "ipc_ut.h"
+#include "ipc_debug.h"
+#include "ipc_defs.h"
+#include "ipc_data.h"
+#include "upcm_msgid.h"
+
+#if defined(__MD97__)
+static kal_bool ipc_ut_rq_rule_ilm_handler(ilm_struct *p_ilm)
+{
+    ipc_rq_info_t rq_info_list = {0};
+    ipc_rq_info_t *p_rq_info = NULL;
+    ipc_rq_info_ind_t *p_rq_info_ind = NULL;
+    kal_uint32 info_cnt = 0;
+    kal_uint32 i = 0;
+    kal_uint16 peer_buf_len = 0;
+
+    ASSERT(NULL != p_ilm);
+    ASSERT(NULL == p_ilm->local_para_ptr);
+    ASSERT(NULL != p_ilm->peer_buff_ptr);
+
+    p_rq_info = (ipc_rq_info_t *)get_peer_buff_pdu(p_ilm->peer_buff_ptr, &peer_buf_len);
+    info_cnt = (peer_buf_len - 4) / sizeof(ipc_rq_info_t);
+
+    for (i = 0; i < info_cnt; i++) {
+        kal_mem_cpy(&rq_info_list, p_rq_info, sizeof(ipc_rq_info_t));
+        ipc_ut_rcv_rq_info(p_rq_info);
+        p_rq_info++;
+    }
+
+    return KAL_TRUE;
+}
+#endif
+
+static void ipc_ut_pdn_rebind_handler(ilm_struct *p_ilm)
+{
+    ipcore_upcm_pdn_rebind_rsp_struct *p_rebind_rsp = NULL;
+    p_rebind_rsp = (ipcore_upcm_pdn_rebind_rsp_struct *)construct_local_para(sizeof(ipcore_upcm_pdn_rebind_rsp_struct), TD_RESET);
+
+    ASSERT(NULL != p_ilm);
+    ASSERT(NULL != p_rebind_rsp);
+
+    kal_mem_cpy(p_rebind_rsp, p_ilm->local_para_ptr, sizeof(ipcore_upcm_pdn_rebind_rsp_struct));
+    ipc_ut_msg_send6(p_ilm->src_mod_id,
+                     p_ilm->dest_mod_id,
+                     p_ilm->sap_id,
+                     p_ilm->msg_id,
+                     (local_para_struct *)p_rebind_rsp,
+                     p_ilm->peer_buff_ptr);
+
+    return;
+}
+
+static void ipc_ut_query_info_handler(ilm_struct *p_ilm)
+{
+    ipc_query_info_t *p_query_cnf = NULL;
+    p_query_cnf = (ipc_query_info_t *)construct_local_para(sizeof(ipc_query_info_t), TD_RESET);
+
+    ASSERT(NULL != p_ilm);
+    ASSERT(NULL != p_query_cnf);
+
+    kal_mem_cpy(p_query_cnf, p_ilm->local_para_ptr, sizeof(ipc_query_info_t));
+    ipc_ut_msg_send6(p_ilm->src_mod_id,
+                     p_ilm->dest_mod_id,
+                     p_ilm->sap_id,
+                     p_ilm->msg_id,
+                     (local_para_struct *)p_query_cnf,
+                     p_ilm->peer_buff_ptr);
+
+    return;
+}
+
+kal_bool ipc_ut_on_ilm(ilm_struct *p_ilm)
+{
+    ASSERT(NULL != p_ilm);
+
+    switch(p_ilm->msg_id) {
+        case MSG_ID_IPCORE_UL_PACKET_FILTERED_REQ:
+            ipc_ut_on_ul_packet_filtered_req(p_ilm->local_para_ptr);
+            break;
+        case MSG_ID_IPCORE_DL_PACKET_FILTERED_REQ:
+            ipc_ut_on_dl_packet_filtered_req(p_ilm->local_para_ptr);
+            break;
+        case MSG_ID_IPCORE_UL_PACKET_FILTERED_WITH_INFO_REQ:
+            ipc_ut_on_ul_packet_filtered_with_info_req(p_ilm->local_para_ptr);
+            break;
+        case MSG_ID_IPCORE_DL_PACKET_FILTERED_WITH_INFO_REQ:
+            ipc_ut_on_dl_packet_filtered_with_info_req(p_ilm->local_para_ptr);
+            break;
+        case MSG_ID_IPCORE_UPCM_PDN_REBIND_RSP :
+            ipc_ut_pdn_rebind_handler(p_ilm);
+            break;
+        case MSG_ID_IPCORE_QUERY_INFO_CNF :
+            ipc_ut_query_info_handler(p_ilm);
+            break;
+#if defined(__MD97__)
+        case MSG_ID_IPCORE_NAS_RQ_INFO_IND:
+            ipc_ut_rq_rule_ilm_handler(p_ilm);
+            break;
+#endif
+        case MSG_ID_IPCORE_LHIFCORE_QUEUE_MAPPING_REQ:
+            /* do nothing */
+            break;
+        default :
+            ASSERT(KAL_FALSE);
+            break;
+    }
+
+    return KAL_TRUE;
+}
diff --git a/mcu/middleware/hif/ipcore/src/ipc_utils.c b/mcu/middleware/hif/ipcore/src/ipc_utils.c
new file mode 100644
index 0000000..90bc7e7
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/ipc_utils.c
@@ -0,0 +1,1195 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ipc_utils.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   IPCore internal utilities.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "upcm_did.h"
+#include "prbm.h"
+#include "qmu_bm_util.h"
+#include "mw_sap.h"
+#include "ipc_debug.h"
+#include "ipc_utils.h"
+
+#define IPC_UTILS_PKT_DUMP_DEFAULT_SIZE 3000
+
+static INLINE void ipc_utils_get_pkt_length(kal_uint8 *p_buf,
+                                            kal_uint32 buf_len,
+                                            kal_uint32 *p_pkt_len)
+{
+    ASSERT(NULL != p_buf);
+    ASSERT(NULL != p_pkt_len);
+
+    if (buf_len >= 6) {
+        /*
+         * check ip version and get ip packet length from header
+         * including ipv6 payload length
+         */
+        QBM_CACHE_INVALID((kal_uint8*)(p_buf), 6);
+
+        if (IPC_HDR_IS_V4(p_buf)) {
+            *p_pkt_len = IPC_HDR_V4_GET_TOTAL_LENGTH(p_buf);
+        } else if (IPC_HDR_IS_V6(p_buf)) {
+            *p_pkt_len = IPC_HDR_V6_GET_LENGTH(p_buf) + IPC_HDR_V6_HEADER_SIZE;
+        } else {
+            *p_pkt_len = 0;
+        }
+    } else {
+        *p_pkt_len = 0;
+    }
+}
+
+static void ipc_utils_pkt_dump_w_peerbuf(msg_type msg_id,
+                                         module_type src_mod,
+                                         peer_buff_struct *p_peer_buf)
+{
+    ilm_struct ilm = {0};
+
+    ASSERT(NULL != p_peer_buf);
+
+    /* fill ilm parameter */
+    ilm.src_mod_id = src_mod;
+    ilm.dest_mod_id = MOD_DHL;
+    ilm.sap_id = IPCORE_USER_SENSITIVE_SAP;
+    ilm.msg_id = msg_id;
+
+    ilm.local_para_ptr = NULL;
+    ilm.peer_buff_ptr = p_peer_buf;
+
+    /* send to DHL */
+    dhl_log_primitive(&ilm);
+    destroy_ilm(&ilm);
+}
+
+static kal_uint16 ipc_utils_calc_checksum16(kal_uint8 *data, kal_uint32 length)
+{
+    kal_uint32 odd = ((kal_uint32) data & 0x1);
+    kal_uint32 offset = 0;
+    kal_uint32 sum32 = 0;
+    kal_uint32 idx = 0;
+    kal_uint16 sum16 = 0;
+
+    if (!odd) {
+        sum32 = 0;
+    } else {
+        sum32 = ((kal_uint16)(*data) << 8);
+        data++;
+        length--;
+    }
+
+    offset = ((length >> 1) << 1);
+    for (idx = 0; idx < offset; idx += 2) {
+        sum32 += *((kal_uint16 *) (data + idx));
+    }
+    if ((length & 0x1)) {
+        sum32 += (kal_uint16)(*(data + length - 1));
+    }
+
+    /* add high word and low word. */
+    sum32 = (sum32 & 0xffff) + (sum32 >> 16);
+    /* add carry */
+    sum16 = (kal_uint16)((sum32 & 0xffff) + (sum32 >> 16));
+    if (odd) {
+        sum16 = (sum16 >> 8) | ((sum16 & 0xff) << 8);
+    }
+    return sum16;
+}
+
+kal_bool ipc_utils_gpd_copy(kal_uint8 *p_dst_buf,
+                            kal_uint32 dst_max_len,
+                            kal_uint32 *p_dst_len_copied,
+                            qbm_gpd *p_head_gpd,
+                            qbm_gpd *p_tail_gpd)
+{
+    qbm_gpd *p_curr_gpd = NULL;
+    qbm_gpd *p_curr_bd = NULL;
+    kal_bool is_end_of_gpd_list = KAL_FALSE;
+    kal_bool is_end_of_bd_list = KAL_FALSE;
+
+    if (NULL == p_dst_buf || 0 == dst_max_len || NULL == p_dst_len_copied ||
+        NULL == p_head_gpd || NULL == p_tail_gpd) {
+        return KAL_FALSE;
+    }
+
+    *p_dst_len_copied = 0;
+    is_end_of_gpd_list = KAL_FALSE;
+    for (p_curr_gpd = p_head_gpd; p_curr_gpd && !is_end_of_gpd_list; p_curr_gpd = (qbm_gpd *) QBM_DES_GET_NEXT(p_curr_gpd)) {
+        is_end_of_gpd_list = (p_curr_gpd == p_tail_gpd);
+        if (QBM_DES_GET_BDP(p_curr_gpd)) {
+
+            is_end_of_bd_list = KAL_FALSE;
+            for (p_curr_bd = (qbm_gpd *) QBM_DES_GET_DATAPTR(p_curr_gpd); p_curr_bd && !is_end_of_bd_list; p_curr_bd = (qbm_gpd *) QBM_DES_GET_NEXT(p_curr_bd)) {
+
+                is_end_of_bd_list = QBM_DES_GET_EOL(p_curr_bd);
+                if (QBM_DES_GET_DATALEN(p_curr_bd) > 0) {
+                    if (*p_dst_len_copied + QBM_DES_GET_DATALEN(p_curr_bd) <= dst_max_len) {
+                        /* Invalid source BD */
+                        QBM_CACHE_INVALID(QBM_DES_GET_DATAPTR(p_curr_bd), QBM_DES_GET_DATALEN(p_curr_bd));
+
+                        kal_mem_cpy(p_dst_buf + *p_dst_len_copied, QBM_DES_GET_DATAPTR(p_curr_bd), QBM_DES_GET_DATALEN(p_curr_bd));
+                        *p_dst_len_copied += QBM_DES_GET_DATALEN(p_curr_bd);
+                    } else {
+                        return KAL_FALSE;
+                    }
+                }
+            }
+        } else {
+            if (QBM_DES_GET_DATALEN(p_curr_gpd) > 0) {
+                if (*p_dst_len_copied + QBM_DES_GET_DATALEN(p_curr_gpd) <= dst_max_len) {
+                    /* Invalid source GPD */
+                    QBM_CACHE_INVALID(QBM_DES_GET_DATAPTR(p_curr_gpd), QBM_DES_GET_DATALEN(p_curr_gpd));
+
+                    kal_mem_cpy(p_dst_buf + *p_dst_len_copied, QBM_DES_GET_DATAPTR(p_curr_gpd), QBM_DES_GET_DATALEN(p_curr_gpd));
+                    *p_dst_len_copied += QBM_DES_GET_DATALEN(p_curr_gpd);
+                } else {
+                    return KAL_FALSE;
+                }
+            }
+        }
+    }
+
+    /* Flush destination cache */
+    QBM_CACHE_FLUSH(p_dst_buf, *p_dst_len_copied);
+    return KAL_TRUE;
+}
+
+void ipc_utils_set_gpd_datalen(void *p_gpd, kal_uint32 datalen, void **p_payload)
+{
+    kal_uint8* p_data = NULL;
+
+    IPC_ASSERT(p_gpd && p_payload);
+
+    if (QBM_DES_GET_BDP(p_gpd)) {
+        void* p_bd = NULL;
+
+        /* set p_bd data ptr */
+        p_bd = QBM_DES_GET_DATAPTR(p_gpd);
+
+        p_data = (kal_uint8*) QBM_DES_GET_DATAPTR(p_bd);
+
+        /* set p_bd data len */
+        QBM_DES_SET_DATALEN(p_bd, datalen);
+
+        /* set p_bd checksum */
+        qbm_cal_set_checksum(p_bd);
+    } else {
+        p_data = (kal_uint8*) QBM_DES_GET_DATAPTR(p_gpd);
+    }
+
+    /* set p_gpd data len */
+    QBM_DES_SET_DATALEN(p_gpd, datalen);
+
+    /* set p_gpd checksum */
+    qbm_cal_set_checksum(p_gpd);
+
+    *p_payload = (void*)(p_data);
+}
+
+kal_bool ipc_utils_get_gpd_dataptr(void *p_gpd, void **p_payload)
+{
+    kal_uint8* p_data = NULL;
+
+    if(!p_gpd || !p_payload){
+        return KAL_FALSE;
+    }
+
+    if (QBM_DES_GET_BDP(p_gpd)) {
+        void* p_bd = NULL;
+
+        /* set p_bd data ptr */
+        p_bd = QBM_DES_GET_DATAPTR(p_gpd);
+
+        p_data = (kal_uint8*) QBM_DES_GET_DATAPTR(p_bd);
+
+    } else {
+        p_data = (kal_uint8*) QBM_DES_GET_DATAPTR(p_gpd);
+    }
+
+    *p_payload = (void*)(p_data);
+    return KAL_TRUE;
+}
+
+
+void ipc_utils_clarify_gpd(qbm_gpd *p_head_gpd,
+                           qbm_gpd *p_tail_gpd,
+                           qbm_gpd **p_ipv4_head_gpd,
+                           qbm_gpd **p_ipv4_tail_gpd,
+                           qbm_gpd **p_ipv6_head_gpd,
+                           qbm_gpd **p_ipv6_tail_gpd)
+{
+    kal_bool is_end = KAL_FALSE;
+    qbm_gpd *p_curr_gpd = NULL;
+    qbm_gpd *p_next_gpd = NULL;
+    qbm_gpd *p_curr_bd = NULL;
+    kal_uint8 *p_first_buf = NULL;
+
+    IPC_ASSERT(p_ipv4_head_gpd);
+    IPC_ASSERT(p_ipv4_tail_gpd);
+    IPC_ASSERT(p_ipv6_head_gpd);
+    IPC_ASSERT(p_ipv6_tail_gpd);
+
+    *p_ipv4_head_gpd = *p_ipv4_tail_gpd = NULL;
+    *p_ipv6_head_gpd = *p_ipv6_tail_gpd = NULL;
+
+    is_end = KAL_FALSE;
+    for (p_curr_gpd = p_head_gpd; p_curr_gpd && !is_end; p_curr_gpd = p_next_gpd) {
+        IPC_ASSERT(QBM_DES_GET_DATAPTR(p_curr_gpd));
+
+        p_next_gpd = (qbm_gpd *) QBM_DES_GET_NEXT(p_curr_gpd);
+        is_end = (p_curr_gpd == p_tail_gpd) ? KAL_TRUE : KAL_FALSE;
+
+        if (QBM_DES_GET_DATALEN(p_curr_gpd) == 0) {
+            /* Zero length packet ! Drop this packet ! */
+            hif_trace_error(IPC_TR_CLARIFY_ZERO_LENGTH_PKT, p_curr_gpd, QBM_DES_GET_DATALEN(p_curr_gpd));
+            p_first_buf = NULL;
+        } else {
+            if (QBM_DES_GET_BDP(p_curr_gpd)) {
+                p_curr_bd = (qbm_gpd *) QBM_DES_GET_DATAPTR(p_curr_gpd);
+                /* Loop to trace 1st DL BD with data buffer */
+                while (p_curr_bd && (QBM_DES_GET_DATALEN(p_curr_bd) == 0)) {
+                    p_curr_bd = (QBM_DES_GET_EOL(p_curr_bd)) ? (NULL) : ((qbm_gpd*)QBM_DES_GET_NEXT(p_curr_bd));
+                }
+
+                if (p_curr_bd) {
+                    p_first_buf = (kal_uint8 *) QBM_DES_GET_DATAPTR(p_curr_bd);
+                } else {
+                    hif_trace_error(IPC_TR_CLARIFY_ZERO_LENGTH_BD, p_curr_gpd, QBM_DES_GET_DATALEN(p_curr_gpd));
+                    p_first_buf = NULL;
+                }
+            } else {
+                p_first_buf = (kal_uint8 *) QBM_DES_GET_DATAPTR(p_curr_gpd);
+            }
+        }
+
+        if (p_first_buf) {
+            if (IPC_HDR_IS_V4(p_first_buf)) {
+                if (*p_ipv4_tail_gpd) {
+                    QBM_DES_SET_NEXT((*p_ipv4_tail_gpd), p_curr_gpd);
+                    *p_ipv4_tail_gpd = p_curr_gpd;
+                } else {
+                    *p_ipv4_head_gpd = p_curr_gpd;
+                    *p_ipv4_tail_gpd = p_curr_gpd;
+                }
+            } else if (IPC_HDR_IS_V6(p_first_buf)) {
+                if (*p_ipv6_tail_gpd) {
+                    QBM_DES_SET_NEXT((*p_ipv6_tail_gpd), p_curr_gpd);
+                    *p_ipv6_tail_gpd = p_curr_gpd;
+                } else {
+                    *p_ipv6_head_gpd = p_curr_gpd;
+                    *p_ipv6_tail_gpd = p_curr_gpd;
+                }
+            } else {
+                hif_trace_error(IPC_TR_CLARIFY_NONE_IP_PKT, p_curr_gpd, QBM_DES_GET_DATALEN(p_curr_gpd));
+                qbmt_dest_q(p_curr_gpd, p_curr_gpd);
+            }
+        } else {
+            /* Always drop p_curr_gpd for parsing error case */
+            hif_trace_info(IPC_TR_CLARIFY_ZERO_LENGTH_PKT_DROP, p_curr_gpd, QBM_DES_GET_DATALEN(p_curr_gpd));
+            qbmt_dest_q(p_curr_gpd, p_curr_gpd);
+        }
+    }
+
+}
+
+ipc_si_hif_type_e ipc_utils_get_hif_type_by_netif_id(kal_uint32 netif_id)
+{
+    if (IPC_INVALID_NETIF_ID == netif_id) {
+        return IPC_SI_HIF_TYPE_IGR;
+    }
+
+    switch (netif_id & 0xFFFFFF00) {
+        case IPC_NETIF_ID_LHIF_BEGIN:
+            return IPC_SI_HIF_TYPE_LHIF;
+        case IPC_NETIF_ID_ETH_BEGIN:
+        case IPC_NETIF_ID_MBIM_BEGIN:
+            return IPC_SI_HIF_TYPE_USB;
+        case IPC_NETIF_ID_MCIF_BEGIN:
+            return IPC_SI_HIF_TYPE_MCIF;
+        case IPC_NETIF_ID_VNIF_BEGIN:
+            return IPC_SI_HIF_TYPE_VNIF;
+        default:
+            /* can't reach here */
+            IPC_ASSERT(KAL_FALSE);
+            return IPC_SI_HIF_TYPE_IGR;
+    }
+}
+
+void ipc_utils_pkt_set_si_hif_type(upcm_did *p_did,
+                                   ipc_si_hif_type_e hif_type,
+                                   kal_uint32 *p_curr_si_idx)
+{
+    upcm_did_si *p_sit = NULL;
+    kal_uint32 pkt_start_idx = 0;
+    kal_bool is_eol = KAL_FALSE;
+
+    IPC_ASSERT((p_did) && (p_curr_si_idx));
+
+    p_sit = UPCM_DID_GET_SIT_PTR(p_did);
+    pkt_start_idx = *p_curr_si_idx;
+
+    IPC_ASSERT( pkt_start_idx < UPCM_DID_MAX_SIT_ENT_NUM );
+
+    if (IPC_SI_HIF_TYPE_IGR == hif_type) {
+        ipc_utils_pkt_dump_did_one_pkt(p_did, &pkt_start_idx);
+        pkt_start_idx = *p_curr_si_idx;
+    }
+
+    is_eol = KAL_FALSE;
+    for (*p_curr_si_idx = pkt_start_idx; *p_curr_si_idx < UPCM_DID_MAX_SIT_ENT_NUM && !is_eol; (*p_curr_si_idx)++) {
+        upcm_did_si *p_curr_si = &p_sit[*p_curr_si_idx];
+
+        is_eol = UPCM_DID_SI_GET_EOL(p_curr_si);
+        UPCM_DID_SI_SET_HIF_TYPE(p_curr_si, hif_type);
+        if (IPC_SI_HIF_TYPE_IGR == hif_type) {
+            upcm_did_si_free_data_buf(p_curr_si);
+            /*
+             * We have to clear sit length if hif_type is IGNORE.
+             * Then, we can use this condition to skip these sit entries if the
+             * sit is already processed last time and HIF refuse to send.
+             */
+            UPCM_DID_SI_SET_LEN(p_curr_si, 0);
+        }
+    }
+}
+
+kal_bool ipc_utils_cpy_gpd_to_did(qbm_gpd *p_head_gpd,
+                                  qbm_gpd *p_tail_gpd,
+                                  upcm_did *p_did,
+                                  ipc_si_hif_type_e hif_type)
+{
+    qbm_gpd        *p_curr_gpd = NULL;
+    qbm_gpd        *p_curr_bd = NULL;
+    kal_bool        end_of_gpd_list = KAL_FALSE;
+    kal_bool        end_of_bd_list = KAL_FALSE;
+    upcm_did_si    *p_sit = NULL;
+    upcm_did_si    *p_curr_si = NULL;
+    kal_uint32      curr_si_idx;
+    kal_uint8      *p_dst_buf = NULL;
+    kal_uint8       pkt_cnt = 0;
+    kal_uint32      dst_len_copied = 0;
+    kal_uint32      dst_max_len = 0;
+
+    IPC_ASSERT(p_head_gpd && p_tail_gpd && p_did);
+
+    p_sit = UPCM_DID_GET_SIT_PTR(p_did);
+    curr_si_idx = 0;
+
+    end_of_gpd_list = KAL_FALSE;
+    for (p_curr_gpd = p_head_gpd;
+         p_curr_gpd && !end_of_gpd_list;
+         p_curr_gpd = (qbm_gpd *)QBM_DES_GET_NEXT(p_curr_gpd), curr_si_idx++) {
+
+        IPC_ASSERT(curr_si_idx < UPCM_DID_MAX_SIT_ENT_NUM);
+        p_curr_si = &p_sit[curr_si_idx];
+
+        dst_max_len = QBM_DES_GET_DATALEN(p_curr_gpd);
+        if (0 == dst_max_len) {
+            hif_trace_error(IPC_TR_COPY_GPD_TO_DID_ZERO_LENGTH_GPD, p_curr_gpd);
+            continue;
+        }
+
+        p_dst_buf = IPC_ALLOCATE_PRBM(dst_max_len, IPC_PRB_DL_ID);
+        dst_len_copied = 0;
+
+        if (!p_dst_buf) {
+            hif_trace_error(IPC_TR_COPY_GPD_TO_DID_ZERO_ALLOC_PRB_NG, p_curr_gpd, p_tail_gpd);
+            goto done;
+        }
+
+        end_of_gpd_list = (p_curr_gpd == p_tail_gpd);
+        if (QBM_DES_GET_BDP(p_curr_gpd)) {
+            end_of_bd_list = KAL_FALSE;
+            for (p_curr_bd = (qbm_gpd *)QBM_DES_GET_DATAPTR(p_curr_gpd);
+                 p_curr_bd && !end_of_bd_list;
+                 p_curr_bd = (qbm_gpd *)QBM_DES_GET_NEXT(p_curr_bd)) {
+
+                end_of_bd_list = QBM_DES_GET_EOL(p_curr_bd);
+                if (QBM_DES_GET_DATALEN(p_curr_bd) > 0) {
+                    if (dst_len_copied + QBM_DES_GET_DATALEN(p_curr_bd) <= dst_max_len) {
+                        /* Invalid source BD */
+                        QBM_CACHE_INVALID(QBM_DES_GET_DATAPTR(p_curr_bd), QBM_DES_GET_DATALEN(p_curr_bd));
+                        kal_mem_cpy(p_dst_buf + dst_len_copied, QBM_DES_GET_DATAPTR(p_curr_bd), QBM_DES_GET_DATALEN(p_curr_bd));
+                        dst_len_copied += QBM_DES_GET_DATALEN(p_curr_bd);
+                    } else {
+                        hif_trace_error(IPC_TR_COPY_GPD_TO_DID_GPD_LENGTH_NG, p_curr_gpd);
+                        IPC_FREE_PRBM(p_dst_buf, dst_max_len, IPC_PRB_DL_ID);
+                        continue;
+                    }
+                }
+            }
+        } else {
+            if (QBM_DES_GET_DATALEN(p_curr_gpd) > 0) {
+                if (dst_len_copied + QBM_DES_GET_DATALEN(p_curr_gpd) <= dst_max_len) {
+                    /* Invalid source GPD */
+                    QBM_CACHE_INVALID(QBM_DES_GET_DATAPTR(p_curr_gpd), QBM_DES_GET_DATALEN(p_curr_gpd));
+                    kal_mem_cpy(p_dst_buf + dst_len_copied, QBM_DES_GET_DATAPTR(p_curr_gpd), QBM_DES_GET_DATALEN(p_curr_gpd));
+                    dst_len_copied += QBM_DES_GET_DATALEN(p_curr_gpd);
+                } else {
+                    hif_trace_error(IPC_TR_COPY_GPD_TO_DID_GPD_LENGTH_NG, p_curr_gpd);
+                    IPC_FREE_PRBM(p_dst_buf, dst_max_len, IPC_PRB_DL_ID);
+                    continue;
+                }
+            }
+        }
+
+        /* Flush destination cache */
+        QBM_CACHE_FLUSH(p_dst_buf, dst_len_copied);
+
+        kal_mem_set(p_curr_si, 0, sizeof(upcm_did_si));
+        UPCM_DID_SI_SET_EOL(p_curr_si);
+        UPCM_DID_SI_SET_F(p_curr_si);
+        UPCM_DID_SI_SET_LEN(p_curr_si, dst_max_len);
+        UPCM_DID_SI_SET_DATAPTR(p_curr_si, p_dst_buf);
+        UPCM_DID_SI_SET_HIF_TYPE(p_curr_si, hif_type);
+
+        pkt_cnt++;
+    }
+
+done :
+    if (pkt_cnt) {
+        UPCM_DID_SET_PKT_NUM(p_did, pkt_cnt);
+        UPCM_DID_SET_SEG_NUM(p_did, pkt_cnt);
+
+        return KAL_TRUE;
+    } else {
+        return KAL_FALSE;
+    }
+}
+
+void ipc_utils_pkt_free_si_data_buf(upcm_did *p_did, kal_uint32 *p_curr_si_idx)
+{
+    upcm_did_si *p_sit = NULL;
+    kal_uint32 pkt_start_idx = 0;
+    kal_bool is_eol = KAL_FALSE;
+
+    IPC_ASSERT( (p_did) && (p_curr_si_idx) );
+
+    p_sit = UPCM_DID_GET_SIT_PTR(p_did);
+    pkt_start_idx = *p_curr_si_idx;
+
+    IPC_ASSERT( pkt_start_idx < UPCM_DID_MAX_SIT_ENT_NUM );
+
+    ipc_utils_pkt_dump_did_one_pkt(p_did, &pkt_start_idx);
+    pkt_start_idx = *p_curr_si_idx;
+
+    is_eol = KAL_FALSE;
+    for (*p_curr_si_idx = pkt_start_idx;
+         *p_curr_si_idx < UPCM_DID_MAX_SIT_ENT_NUM && !is_eol;
+         (*p_curr_si_idx)++) {
+
+        upcm_did_si *p_curr_si = &p_sit[*p_curr_si_idx];
+        is_eol = UPCM_DID_SI_GET_EOL(p_curr_si);
+        UPCM_DID_SI_SET_HIF_TYPE(p_curr_si, IPC_SI_HIF_TYPE_IGR);
+        upcm_did_si_free_data_buf(p_curr_si);
+    }
+}
+
+kal_bool ipc_utils_fill_did_si_from_meta(kal_bool is_need_adjust,
+                                         upcm_did *p_dst_did,
+                                         kal_uint32 *p_si_idx,
+                                         ipc_meta_info_des *p_pkt_info,
+                                         ipc_si_hif_type_e hif_type)
+{
+    upcm_did_si *p_sit = NULL;
+    upcm_did_si *p_si = NULL;
+    kal_uint16 base_psn = 0;
+    kal_uint16 psn = 0;
+    kal_uint32 num_igr_si = 0;
+    kal_uint32 i = 0;
+
+    IPC_ASSERT(p_dst_did && p_pkt_info && p_si_idx);
+
+    if(*p_si_idx >= UPCM_DID_MAX_SIT_ENT_NUM){
+        hif_trace_error(IPC_TR_FILL_DID_FROM_META_NG, *p_si_idx, is_need_adjust, p_dst_did);
+        return KAL_FALSE;
+    }
+
+    p_sit = UPCM_DID_GET_SIT_PTR(p_dst_did);
+
+    if (is_need_adjust) {
+        base_psn = UPCM_DID_GET_COUNT_L(p_dst_did);
+        psn = p_pkt_info->psn_countL;
+
+        /*
+         * DID PSN is continuous.
+         * if the coming PSN is smaller than previous, we need to allocate a new DID
+         */
+        if (psn < (base_psn + *p_si_idx)) {
+            return KAL_FALSE;
+        }
+
+        /* Calculate how many sit entry we need to skip */
+        num_igr_si = psn - (base_psn + *p_si_idx);
+        if ((*p_si_idx + num_igr_si) >= UPCM_DID_MAX_SIT_ENT_NUM) {
+            return KAL_FALSE;
+        }
+
+        /* Fill IGR packet to SIs for PSN correction */
+        for (i = 0; i < num_igr_si; i++) {
+            p_si = &(p_sit[*p_si_idx + i]);
+            UPCM_DID_SI_SET_EOL(p_si);
+            UPCM_DID_SI_CLR_F(p_si);
+            UPCM_DID_SI_SET_HIF_TYPE(p_si, IPC_SI_HIF_TYPE_IGR);
+        }
+    }
+
+    /* Fill the packet to the right position based on its PSN */
+    *p_si_idx += num_igr_si;
+    p_si = &(p_sit[*p_si_idx]);
+    UPCM_DID_SI_SET_EOL(p_si);
+    UPCM_DID_SI_SET_F(p_si);
+    UPCM_DID_SI_SET_LEN(p_si, p_pkt_info->len);
+    UPCM_DID_SI_SET_DATAPTR(p_si, p_pkt_info->addr);
+    UPCM_DID_SI_SET_HIF_TYPE(p_si, hif_type);
+    UPCM_DID_SI_SET_OFFSET(p_si, 0);
+
+    UPCM_DID_SET_PKT_NUM(p_dst_did, UPCM_DID_GET_PKT_NUM(p_dst_did) + 1);
+    UPCM_DID_SET_SEG_NUM(p_dst_did, UPCM_DID_GET_SEG_NUM(p_dst_did) + 1);
+    (*p_si_idx)++;
+
+    return KAL_TRUE;
+}
+
+void ipc_utils_pkt_dump_buf(msg_type msg_id,
+                            module_type src_mod,
+                            kal_uint8 *p_buf,
+                            kal_uint32 pkt_len)
+{
+    ilm_struct ilm = {0};
+    kal_uint8 *p_dump_info = NULL;
+    peer_buff_struct *p_peer = NULL;
+    kal_uint16 peer_buf_len = 0;
+
+    /* fill ilm parameter */
+    ilm.src_mod_id = src_mod;
+    ilm.dest_mod_id = MOD_DHL;
+    ilm.sap_id = IPCORE_USER_SENSITIVE_SAP;
+    ilm.msg_id = msg_id;
+
+    if (0 == pkt_len) {
+        return;
+    }
+
+    if (pkt_len > IPC_UTILS_PKT_DUMP_DEFAULT_SIZE) {
+        pkt_len = IPC_UTILS_PKT_DUMP_DEFAULT_SIZE;
+    }
+
+    /* allocate peer buffer and reset to 0 */
+    p_peer = construct_peer_buff(sizeof(kal_uint8)*pkt_len, 0, 0, TD_RESET);
+    p_dump_info = (kal_uint8*) get_peer_buff_pdu(p_peer, &peer_buf_len);
+
+    /* copy packet content */
+    QBM_CACHE_INVALID((kal_uint8*)(p_buf), pkt_len);
+    kal_mem_cpy(p_dump_info, p_buf, peer_buf_len);
+
+    ilm.local_para_ptr = NULL;
+    ilm.peer_buff_ptr = p_peer;
+
+    /* send to DHL */
+    dhl_log_primitive(&ilm);
+    destroy_ilm(&ilm);
+}
+
+void ipc_utils_pkt_dump_buff_gpd_list(qbm_gpd *p_head_gpd,
+                                      qbm_gpd *p_tail_gpd,
+                                      kal_bool is_uplink)
+{
+    qbm_gpd *p_curr_gpd = NULL;
+    qbm_gpd *p_next_gpd = NULL;
+    qbm_gpd *p_bd = NULL;
+    kal_uint8 *p_pkt = NULL;
+    kal_uint32 pkt_len = 0;
+    kal_bool is_eol = KAL_FALSE;
+
+    IPC_ASSERT(p_head_gpd && p_tail_gpd);
+
+    is_eol = KAL_FALSE;
+    for (p_curr_gpd = p_head_gpd; p_curr_gpd && !is_eol; p_curr_gpd = p_next_gpd) {
+        p_next_gpd = QBM_DES_GET_NEXT(p_curr_gpd);
+        is_eol = (p_curr_gpd == p_tail_gpd);
+
+        pkt_len = QBM_DES_GET_DATALEN(p_curr_gpd);
+        p_bd = QBM_DES_GET_DATAPTR(p_curr_gpd);
+        if ((0 != pkt_len) && (pkt_len == QBM_DES_GET_DATALEN(p_bd))) {
+            p_pkt = QBM_DES_GET_DATAPTR(p_bd);
+            if (is_uplink) {
+                IPC_UL_PKT_DUMP(p_pkt, pkt_len);
+            } else {
+                IPC_DL_PKT_DUMP(p_pkt, pkt_len);
+            }
+        }
+    }
+}
+
+void ipc_utils_pkt_dump_did_one_pkt(upcm_did *p_did, kal_uint32 *p_curr_si_idx)
+{
+    upcm_did_si *p_sit = NULL;
+    upcm_did_si *p_curr_si = NULL;
+    kal_uint32 pkt_start_idx = 0;
+    kal_bool is_eol = KAL_FALSE;
+    kal_uint32 pkt_len = 0;
+    kal_uint32 pkt_offset = 0;
+    kal_uint32 si_len = 0;
+    kal_uint8 *p_buf = NULL;
+    kal_uint8 *p_dump_info = NULL;
+    peer_buff_struct *p_peer = NULL;
+    kal_uint16 peer_buf_len = 0;
+
+    IPC_ASSERT((p_did) && (p_curr_si_idx));
+
+    p_sit = UPCM_DID_GET_SIT_PTR(p_did);
+    p_curr_si = &p_sit[*p_curr_si_idx];
+    p_buf = (kal_uint8*) UPCM_DID_SI_GET_DATAPTR(p_curr_si) + UPCM_DID_SI_GET_OFFSET(p_curr_si);
+    si_len = UPCM_DID_SI_GET_LEN(p_curr_si);
+    pkt_start_idx = *p_curr_si_idx;
+
+    IPC_ASSERT( pkt_start_idx < UPCM_DID_MAX_SIT_ENT_NUM );
+
+    ipc_utils_get_pkt_length(p_buf, si_len, &pkt_len);
+    if (pkt_len == 0 || pkt_len > IPC_UTILS_PKT_DUMP_DEFAULT_SIZE) {
+        /* Invalid packet length, use default size instead */
+        pkt_len = IPC_UTILS_PKT_DUMP_DEFAULT_SIZE;
+    }
+
+    p_peer = construct_peer_buff(sizeof(kal_uint8) *pkt_len, 0, 0, TD_RESET);
+    p_dump_info = (kal_uint8*) get_peer_buff_pdu(p_peer, &peer_buf_len);
+    pkt_offset = 0;
+
+    is_eol = KAL_FALSE;
+    while (*p_curr_si_idx < UPCM_DID_MAX_SIT_ENT_NUM) {
+        p_curr_si = &p_sit[*p_curr_si_idx];
+        p_buf = (kal_uint8*) UPCM_DID_SI_GET_DATAPTR(p_curr_si) + UPCM_DID_SI_GET_OFFSET(p_curr_si);
+        si_len = UPCM_DID_SI_GET_LEN(p_curr_si);
+        is_eol = UPCM_DID_SI_GET_EOL(p_curr_si);
+
+        /* copy packet content */
+        if (si_len <= peer_buf_len) {
+            QBM_CACHE_INVALID((kal_uint8*)(p_buf), si_len);
+            kal_mem_cpy(p_dump_info + pkt_offset, p_buf, si_len);
+            pkt_offset += si_len;
+            peer_buf_len -= si_len;
+        }
+
+        if (!is_eol) {
+            (*p_curr_si_idx)++;
+        } else {
+            break;
+        }
+    }
+
+    /* send to DHL */
+    ipc_utils_pkt_dump_w_peerbuf(MSG_IPC_DL_RAW_DATA, MOD_IPCORE, p_peer);
+}
+
+void ipc_utils_pkt_dump_did(upcm_did *p_did_head,
+                            upcm_did *p_did_tail,
+                            ipc_si_hif_type_e hif_type)
+{
+    upcm_did *p_did = NULL;
+    upcm_did *p_next_did = NULL;
+    kal_bool is_eol = KAL_FALSE;
+    kal_uint32 seg_num = 0;
+    kal_uint32 cur_si_idx = 0;
+    upcm_did_si *p_did_si = NULL;
+    kal_bool free_all = KAL_FALSE;
+
+    /* chek if DID input is NULL */
+    ASSERT(p_did_head && p_did_tail);
+
+    free_all = (IPC_SI_HIF_TYPE_MAX == hif_type);
+
+    is_eol = KAL_FALSE;
+    for (p_did = p_did_head; p_did && !is_eol; p_did = p_next_did) {
+        p_next_did = UPCM_DID_GET_NEXT(p_did);
+        is_eol = (p_did == p_did_tail) ? KAL_TRUE : KAL_FALSE;
+        seg_num = UPCM_DID_GET_SEG_NUM(p_did);
+
+        for (cur_si_idx = 0; cur_si_idx < seg_num; cur_si_idx++) {
+            p_did_si = &p_did->sit[cur_si_idx];
+
+            /* skip si if hif_type is not equal to specified value*/
+            if ((hif_type != UPCM_DID_SI_GET_HIF_TYPE(p_did_si)) && !free_all) {
+                continue;
+            }
+
+            ipc_utils_pkt_dump_did_one_pkt(p_did, &cur_si_idx);
+        }
+    }
+}
+
+void ipc_utils_dump_data(void *p_data, kal_uint32 bytes)
+{
+    kal_uint32 i = 0;
+    /* 4bytes alignment */
+    kal_uint32 *p_d = (kal_uint32*)((int)p_data & (~0X3));
+
+    for (i = 0; i*4 < bytes; i = i + 4) {
+        hif_data_trace(MD_TRC_IPC_DATA_DUMP_TRACE,i*4 , p_d[i], p_d[i+1], p_d[i+2], p_d[i+3]);
+    }
+}
+
+void ipc_utils_gpd_list_del_entry(qbm_gpd **p_first_gpd,
+                                  qbm_gpd **p_last_gpd,
+                                  qbm_gpd **p_curr_gpd,
+                                  qbm_gpd **p_prev_gpd,
+                                  qbm_gpd **p_next_gpd)
+{
+    if (*p_curr_gpd == *p_first_gpd) {
+        if (*p_curr_gpd == *p_last_gpd) {
+            *p_first_gpd = NULL;
+            *p_last_gpd = NULL;
+        } else {
+            IPC_ASSERT(*p_next_gpd);
+            *p_first_gpd = *p_next_gpd;
+        }
+        *p_prev_gpd = NULL;
+    } else {
+        IPC_ASSERT(*p_prev_gpd);
+        if (*p_curr_gpd == *p_last_gpd) {
+            *p_last_gpd = *p_prev_gpd;
+            QBM_DES_SET_NEXT(*p_prev_gpd, NULL);
+        } else {
+            IPC_ASSERT(*p_next_gpd);
+            QBM_DES_SET_NEXT(*p_prev_gpd, *p_next_gpd);
+        }
+    }
+    QBM_DES_SET_NEXT(*p_curr_gpd, NULL);
+}
+
+void ipc_utils_unite_gpd(kal_bool is_uplink,
+                         qbm_gpd *p_gpd_in,
+                         qbm_gpd **pp_gpd_out)
+{
+    IPC_ASSERT(p_gpd_in);
+    IPC_ASSERT(pp_gpd_out);
+
+    /*
+     * Check if this GPD is needed to unite:
+     *
+     * 1. This GPD has BD list.
+     * 2. First BD (containing data) does not have full data within it.
+     */
+    {
+        qbm_gpd* p_bd = NULL;
+
+        if (!QBM_DES_GET_BDP(p_gpd_in)) {
+            goto no_change;
+        }
+
+        /* get 1st bd data ptr */
+        p_bd = QBM_DES_GET_DATAPTR(p_gpd_in);
+
+        /* Loop to trace 1st DL BD with data buffer */
+        while (p_bd && (QBM_DES_GET_DATALEN(p_bd) == 0)) {
+            p_bd = (QBM_DES_GET_EOL(p_bd)) ? (NULL) : ((qbm_gpd*) QBM_DES_GET_NEXT(p_bd));
+        }
+
+        /* No any BD have data */
+        if (NULL == p_bd) {
+            hif_trace_error(IPC_TR_GPD_UNITE_NULL_BD_LIST, is_uplink, p_gpd_in);
+            goto no_change;
+        }
+
+        if (QBM_DES_GET_DATALEN(p_gpd_in) == QBM_DES_GET_DATALEN(p_bd)) {
+            goto no_change;
+        }
+    }
+
+    /* This packet is divided into several pieces of data segment, unite them into single one. */
+    {
+        kal_uint32 total_len = 0;
+        kal_uint32 copied_len = 0;
+        kal_uint8 *p_buff = 0;
+
+        total_len = QBM_DES_GET_DATALEN(p_gpd_in);
+        if (0 == total_len) {
+            hif_trace_error(IPC_TR_GPD_UNITE_ZERO_LENGTH_GPD, is_uplink, p_gpd_in);
+            goto no_change;
+        }
+
+        if (1 != qbmt_alloc_q_no_tail(is_uplink ? QBM_TYPE_NET_UL_SHRD : QBM_TYPE_NET_DL,
+                                      1,
+                                      (void**) pp_gpd_out,
+                                      (void**) pp_gpd_out)) {
+            hif_trace_error(IPC_TR_GPD_UNITE_ALLOC_GPD_NG, is_uplink, p_gpd_in, total_len);
+            goto unite_failed;
+        }
+
+        /* Copy data from input GPD to output GPD */
+        IPC_ASSERT(*pp_gpd_out);
+        ipc_utils_set_gpd_datalen(*pp_gpd_out, total_len, (void**) &p_buff);
+        IPC_ASSERT(p_buff);
+
+        if (KAL_TRUE != ipc_utils_gpd_copy(p_buff, total_len, &copied_len, p_gpd_in, p_gpd_in)) {
+            hif_trace_error(IPC_TR_GPD_UNITE_GPD_COPY_NG, is_uplink, p_buff, total_len, copied_len, p_gpd_in);
+            /* Free allocated new GPD */
+            qbmt_dest_q(*pp_gpd_out, *pp_gpd_out);
+            goto unite_failed;
+        }
+
+        /* Sync SW control field from UPCM for DL traffic */
+        if (KAL_FALSE == is_uplink) {
+            /* SW control field is from UPCM */
+            kal_mem_cpy((void*) QBM_DES_GET_SW_CTRL_FIELD(*pp_gpd_out), (void*) QBM_DES_GET_SW_CTRL_FIELD(p_gpd_in), sizeof(upcm_dlvr_dl_info_t));
+        }
+    }
+
+    /* Unite done : return new GPD. */
+    hif_data_trace(MD_TRC_IPC_GE_UNITED_GPD, is_uplink, p_gpd_in, *pp_gpd_out, QBM_DES_GET_DATALEN(*pp_gpd_out));
+    IPC_ASSERT(*pp_gpd_out);
+    return;
+
+no_change :
+    *pp_gpd_out = p_gpd_in;
+    return;
+
+unite_failed :
+    hif_trace_error(IPC_TR_GPD_UNITE_FAILED, is_uplink, p_gpd_in);
+    *pp_gpd_out = NULL;
+    return;
+}
+
+kal_bool ipc_utils_sit_to_gpd(qbm_type type,
+                              upcm_did *p_did,
+                              kal_uint32 curr_si_idx,
+                              kal_uint32 pkt_len,
+                              qbm_gpd **pp_gpd_out)
+{
+    kal_uint8 *p_gpd_data = NULL;
+    upcm_did_si *sit = UPCM_DID_GET_SIT_PTR(p_did);
+    kal_uint32 pkt_start_idx = curr_si_idx;
+    kal_uint8 *p_src_buf = NULL;
+    kal_uint32 dst_len_copied = 0;
+    kal_bool end_of_seg_list = KAL_FALSE;
+
+    IPC_ASSERT((p_did) && (pkt_start_idx < UPCM_DID_MAX_SIT_ENT_NUM));
+
+    if ((QBM_TYPE_NET_DL == type) && (QBM_NET_DL_DATA_LEN < pkt_len)) {
+        /* Packet len is more than gpd buffer memory*/
+        hif_trace_error(IPC_TR_SIT_TO_GPD_FAIL, __FUNCTION__, pkt_len, type, p_did, curr_si_idx);
+        *pp_gpd_out = NULL;
+        return KAL_FALSE;
+    }
+
+    if (1 != qbmt_alloc_q_no_tail(type,
+                                  1,
+                                  (void**)pp_gpd_out,
+                                  (void**)pp_gpd_out)) {
+        hif_trace_error(IPC_TR_SI_UNITE_ALLOC_GPD_NG, type, p_did, curr_si_idx, pkt_len);
+        *pp_gpd_out = NULL;
+        return KAL_FALSE;
+    }
+
+    IPC_ASSERT(*pp_gpd_out);
+    ipc_utils_set_gpd_datalen(*pp_gpd_out, pkt_len, (void**)&p_gpd_data);
+    IPC_ASSERT(p_gpd_data);
+
+    dst_len_copied = 0;
+    end_of_seg_list = KAL_FALSE;
+    for (curr_si_idx = pkt_start_idx; curr_si_idx < UPCM_DID_MAX_SIT_ENT_NUM && !end_of_seg_list; curr_si_idx++) {
+        upcm_did_si *p_curr_si = &sit[curr_si_idx];
+        end_of_seg_list = UPCM_DID_SI_GET_EOL(p_curr_si);
+
+        if (UPCM_DID_SI_GET_LEN(p_curr_si)) {
+            p_src_buf = ((kal_uint8*) UPCM_DID_SI_GET_DATAPTR(p_curr_si)) + UPCM_DID_SI_GET_OFFSET(p_curr_si);
+            QBM_CACHE_INVALID(p_src_buf, UPCM_DID_SI_GET_LEN(p_curr_si));
+            kal_mem_cpy(p_gpd_data + dst_len_copied, p_src_buf, UPCM_DID_SI_GET_LEN(p_curr_si));
+            dst_len_copied += UPCM_DID_SI_GET_LEN(p_curr_si);
+        }
+    }
+
+    QBM_CACHE_FLUSH(p_gpd_data, dst_len_copied);
+    return KAL_TRUE;
+}
+
+kal_uint16 ipc_utils_calc_tcp_checksum(kal_bool is_ipv4,
+                                       kal_uint8 *src_addr,
+                                       kal_uint8 *dst_addr,
+                                       kal_uint8 *tcp_header,
+                                       kal_uint32 tcp_len)
+{
+    kal_uint32 sum32 = 0;
+    kal_uint32 length = 0;
+    kal_uint16 sum16 = 0;
+
+    /* It's designed for length < 2^16. */
+    IPC_ASSERT(tcp_len <= (kal_uint32)(is_ipv4 ? 65507 : 65487));
+
+    /* Pseudo-header. */
+    sum32 = IPC_H2N_2B(tcp_len); /* TCP length, assue it's less than 2^16. */
+    sum32 += IPC_H2N_2B(IPC_HDR_PROT_TCP); /* Next Header */
+    length = ((is_ipv4) ? IPC_HDR_V4_ADDR_SIZE : IPC_HDR_V6_ADDR_SIZE);
+    sum32 += ipc_utils_calc_checksum16(src_addr, length);
+    sum32 += ipc_utils_calc_checksum16(dst_addr, length);
+
+    /* TCP header and data. */
+    sum32 += ipc_utils_calc_checksum16(tcp_header, tcp_len);
+
+    sum32 = (sum32 & 0xffff) + (sum32 >> 16); /* add high word and low word. */
+    sum16 = (kal_uint16)((sum32 & 0xffff) + (sum32 >> 16)); /* add carry */
+    sum16 = ~sum16;
+
+    return IPC_H2N_2B(sum16);
+}
+
+kal_uint16 ipc_utils_calc_udp_checksum(kal_bool is_ipv4,
+                                       kal_uint8 *src_addr,
+                                       kal_uint8 *dst_addr,
+                                       kal_uint8 *udp_header,
+                                       kal_uint32 udp_len)
+{
+    kal_uint32 sum32 = 0;
+    kal_uint32 length = 0;
+    kal_uint16 sum16 = 0;
+
+    /* It's designed for length < 2^16. */
+    IPC_ASSERT(udp_len <= (kal_uint32)(is_ipv4 ? 65507 : 65487));
+
+    /* Pseudo-header. */
+    sum32 = IPC_H2N_2B(udp_len); /* UDP length, assue it's less than 2^16. */
+    sum32 += IPC_H2N_2B(IPC_HDR_PROT_UDP); /* Next Header */
+    length = ((is_ipv4) ? IPC_HDR_V4_ADDR_SIZE : IPC_HDR_V6_ADDR_SIZE);
+    sum32 += ipc_utils_calc_checksum16(src_addr, length);
+    sum32 += ipc_utils_calc_checksum16(dst_addr, length);
+
+    /* UDP header and data. */
+    sum32 += ipc_utils_calc_checksum16(udp_header, udp_len);
+
+    sum32 = (sum32 & 0xffff) + (sum32 >> 16); /* add high word and low word. */
+    sum16 = (kal_uint16)((sum32 & 0xffff) + (sum32 >> 16)); /* add carry */
+    sum16 = ~sum16;
+
+    /*
+     * 2015/07/07 Peter.Hsu
+     * IPv6 UDP with zero-checksum is invalid. (RFC 6935)
+     * If the checksum computation is 0, it should be replaced by 0xFFFF.
+     */
+    if (0 == sum16) {
+        sum16 = ~sum16;
+    }
+    return IPC_H2N_2B(sum16);
+}
+
+kal_uint16 ipc_utils_calc_ipv4_checksum(kal_uint8 *ip_header)
+{
+    kal_uint16  sum16 = 0;
+
+    sum16 = ipc_utils_calc_checksum16(ip_header, IPC_HDR_V4_GET_IHL(ip_header));
+    sum16 = ~sum16;
+    return IPC_H2N_2B(sum16);
+}
+
+kal_uint16 ipc_utils_calc_icmp_checksum(kal_uint8 *ip_header, kal_uint32 length)
+{
+    kal_uint16  sum16 = 0;
+
+    sum16 = ipc_utils_calc_checksum16(ip_header, length);
+    sum16 = ~sum16;
+    return IPC_H2N_2B(sum16);
+}
+
diff --git a/mcu/middleware/hif/ipcore/src/pfm_garbage_filter.c b/mcu/middleware/hif/ipcore/src/pfm_garbage_filter.c
new file mode 100644
index 0000000..5885d78
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/pfm_garbage_filter.c
@@ -0,0 +1,1556 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2014
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   pfm_garbage_filter.c
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   Packet Filter Manager customed functions for feature: Garbage Filter.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+#include "ipc_api.h"
+#include "ipc_enums.h"
+#include "ipc_filter_priority.h"
+#include "ipc_debug.h"
+#include "ipc_filter.h"
+#include "ipc_packet_parser.h"
+
+#include "pfm_defs.h"
+#include "pfm_enums.h"
+#include "pfm_object.h"
+
+#define PFM_GARBAGE_FILTER_MAX_FILTER   128
+#define PFM_INVALID_FILTER_ID           -10
+#define PFM_STR_FILTER_NETIF_MAX_NUM    16
+#define PFM_STR_FILTER_MAGIC_CODE       0x1798
+#define PFM_UL_ICMP_PING_WHITELIST_LOW_PRIORITY   2
+#define PFM_UL_ICMP_PING_WHITELIST_HIGH_PRIORITY  1
+/*------------------------------------------------------------------------------
+ * Private data structure.
+ *----------------------------------------------------------------------------*/
+typedef struct _pfm_garbage_filter_t {
+    kal_int32   filter_id;
+    kal_uint8   ip_type;
+    kal_uint8   protocol;
+    kal_uint16  dst_port;
+    kal_uint32  magic_code;
+} pfm_garbage_filter_t;
+
+typedef struct _pfmStrFilterNetifInfo {
+    kal_uint32 index;
+    kal_uint32 netif_id;
+    kal_uint8  filter_num;
+    struct _pfmStrFilterInfo *p_head_filter;
+} pfmStrFilterNetifInfo;
+
+typedef struct _pfmStrFilterInfo {
+/* Following elements should be aligned with pfm_str_filter_t*/ 
+    kal_int32   filter_id;                              /* user defined index */
+    kal_uint32  netif_id;
+    kal_uint16  filter_len;
+    kal_uint16  mask_len;
+    kal_uint8   filter_str[PFM_STR_FILTER_MAX_SIZE];
+    kal_uint8   mask_str[PFM_STR_FILTER_MAX_SIZE];
+    kal_uint32  magic_code;
+/* end */      
+    struct _pfmStrFilterInfo *p_next_filter;
+    struct _pfmStrFilterNetifInfo *p_netif;
+} pfmStrFilterInfo;
+
+/*------------------------------------------------------------------------------
+ * Private variables.
+ *----------------------------------------------------------------------------*/
+static kal_int32 g_fin_ack_filter_id_v4 = PFM_INVALID_FILTER_ID;
+static kal_int32 g_fin_ack_filter_id_v6 = PFM_INVALID_FILTER_ID;
+static kal_int32 g_igmp_filter_id_v4 = PFM_INVALID_FILTER_ID;
+static kal_int32 g_igmp_filter_id_v6 = PFM_INVALID_FILTER_ID;
+static kal_int32 g_udp_filter_id_v4 = PFM_INVALID_FILTER_ID;
+static kal_int32 g_udp_filter_id_v6 = PFM_INVALID_FILTER_ID;
+static pfmStrFilterInfo g_pfm_str_filter_pool[PFM_STR_FILTER_MAX_NUM];
+static pfmStrFilterNetifInfo g_pfm_str_filter_netif_pool[PFM_STR_FILTER_NETIF_MAX_NUM];
+static kal_uint32 g_pfm_str_filter_pool_mask = 0;
+static kal_uint32 g_pfm_str_filter_num = 0;
+static kal_uint32 g_pfm_str_filter_netif_pool_mask = 0;
+static kal_uint32 g_pfm_str_filter_netif_num = 0;
+static kal_int32 g_pfm_str_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_icmpv4_echo_req_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_icmpv4_echo_reply_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_icmpv6_echo_req_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_icmpv6_echo_reply_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_ul_disable_all_packets_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_ul_icmpv4_echo_req_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_ul_icmpv4_echo_reply_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_ul_icmpv6_echo_req_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_ul_icmpv6_echo_reply_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_ul_icmpv6_rs_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+static kal_int32 g_ul_non_ping_filter_id = PFM_INVALID_FILTER_ID;
+static pfm_garbage_str_wake_type_pkt_f g_funcptr_mbim_wake_type_pkt_cbk = NULL;
+static void* g_priv_data = NULL;
+
+/*
+* API to register PFM callback function for MBIM WAKE REASON wake type pkt 
+*/
+void pfm_reg_cbk_wake_type_pkt(pfm_garbage_str_wake_type_pkt_f pf_wake_type_pkt, void* priv_data)
+{
+    hif_trace_info(PFM_TR_REG_CBK_WAKE_TYPE_PKT, __FUNCTION__, pf_wake_type_pkt);
+    PFM_SPIN_LOCK(pfm_spinlock_g);
+    g_funcptr_mbim_wake_type_pkt_cbk = pf_wake_type_pkt;
+    g_priv_data = priv_data;
+    PFM_SPIN_UNLOCK(pfm_spinlock_g);
+}
+
+/*
+* API to De-register PFM callback function for MBIM WAKE REASON wake type pkt
+*/
+void pfm_dereg_cbk_wake_type_pkt()
+{
+    hif_trace_info(PFM_TR_DEREG_CBK_WAKE_TYPE_PKT, __FUNCTION__);
+    PFM_SPIN_LOCK(pfm_spinlock_g);
+    g_funcptr_mbim_wake_type_pkt_cbk = NULL;
+    g_priv_data = NULL;
+    PFM_SPIN_UNLOCK(pfm_spinlock_g);
+}
+
+/*------------------------------------------------------------------------------
+ * Private functions.
+ *----------------------------------------------------------------------------*/
+
+/*!
+ * Callback function with packet information to process the IP datagram filtered.
+ * Reply TCP RST packet to the sender of the garbage TCP SYN packet.
+ *
+ * @param   info_p [IN] Related information of filtered out GPDs.
+ * @param   context [IN] A context specified while registering the filter.
+ * @param   filter_id [IN] Corresponding registered filter ID.
+ * @param   head_gpd [IN] Pointer head of the GPD list for the IP datagram filtered.
+ * @param   tail_gpd [IN] Pointer tail of the GPD list for the IP datagram filtered.
+ * @param   length [IN] Bytes of buffers used in the GPD list.
+ */
+void pfm_ipc_dl_filter_with_info_cb(ipc_filter_info_t *info_p,
+    void                   *context,
+    kal_int32               filter_id,
+    qbm_gpd                *head_gpd,
+    qbm_gpd                *tail_gpd,
+    kal_uint32              length)
+{
+    ipc_pkt_t       ipc_pkt;
+    qbm_gpd        *ul_gpd;
+    qbm_gpd        *bd;
+    kal_uint8      *p_data;
+    kal_uint8      *p_packet = NULL;
+    kal_uint8      *src_addr;
+    kal_uint8      *dst_addr;
+    kal_uint8      *p_tcp_header;
+    kal_uint32      ip_header_len;
+    kal_bool        is_ipv4;
+
+    if (!QBM_DES_GET_BDP(head_gpd)) {
+        p_packet = QBM_DES_GET_DATAPTR(head_gpd);
+    } else {
+        /* get 1st bd data ptr */
+        bd = QBM_DES_GET_DATAPTR(head_gpd);
+
+        /* Loop to trace 1st DL BD with data buffer */
+        while (bd && (QBM_DES_GET_DATALEN(bd) == 0)) {
+            bd = (QBM_DES_GET_EOL(bd)) ? (NULL) : ((qbm_gpd*) QBM_DES_GET_NEXT(bd));
+        }
+
+        /* No any BD have data */
+        if (NULL == bd) {
+            hif_trace_error(PFM_TR_GARBAGE_FILTER_ZERO_LENGTH_GPD, head_gpd);
+            goto free_gpd;
+        }
+
+        p_packet = QBM_DES_GET_DATAPTR(bd);
+    }
+
+    if (IPC_HDR_IS_V4(p_packet)) {
+        is_ipv4 = KAL_TRUE;
+
+        if (IPC_HDR_PROT_TCP != IPC_HDR_V4_GET_PROTOCOL(p_packet)) {
+            /* Only For TCP packet */
+            hif_trace_error(PFM_TR_GARBAGE_FILTER_NON_TCP_PACKET, head_gpd, IPC_HDR_V4_GET_PROTOCOL(p_packet));
+            goto free_gpd;
+        }
+
+        /* Send IPv4 TCP RST */
+        ip_header_len = (kal_uint32) IPC_HDR_V4_GET_IHL(p_packet);
+        p_tcp_header = p_packet + ip_header_len;
+
+        src_addr = IPC_HDR_V4_GET_DST_ADDR(p_packet);
+        dst_addr = IPC_HDR_V4_GET_SRC_ADDR(p_packet);
+    } else {
+        hif_trace_error(PFM_TR_GARBAGE_FILTER_NON_TCP_PACKET, head_gpd, IPC_HDR_V4_GET_PROTOCOL(p_packet));
+        goto free_gpd;
+    }
+
+    /* Allocate a UL GPD */
+    ul_gpd = QBM_ALLOC_ONE(QBM_TYPE_NET_UL);
+    if (!ul_gpd) {
+        hif_trace_info(PFM_TR_GARBAGE_FILTER_REPLY_RST_FAIL, 0, IPC_HDR_TCP_GET_DST_PORT(p_tcp_header));
+        return;
+    }
+
+    bd = QBM_DES_GET_DATAPTR(ul_gpd);
+    p_data = QBM_DES_GET_DATAPTR(bd);
+
+    /* Fill IP/TCP header */
+    {
+        kal_uint16          sum16;
+        kal_uint32          tcp_header_len;
+        kal_uint32          total_len;
+        kal_uint8           *ip_header;     // ip_header for output packet
+        kal_uint8           *tcp_header;    // tcp_header for output packet
+
+        ip_header_len = IPC_HDR_V4_HEADER_SIZE;
+        tcp_header_len = IPC_HDR_TCP_HEADER_SIZE;
+        total_len = ip_header_len + tcp_header_len;
+
+        ip_header = p_data;
+        tcp_header = ip_header + ip_header_len;
+
+        /* Fill TCP header */
+        IPC_HDR_TCP_SET_SRC_PORT(tcp_header, IPC_HDR_TCP_GET_DST_PORT(p_tcp_header));
+        IPC_HDR_TCP_SET_DST_PORT(tcp_header, IPC_HDR_TCP_GET_SRC_PORT(p_tcp_header));
+        IPC_HDR_TCP_SET_SEQ_NUM(tcp_header, IPC_HDR_TCP_GET_ACK_NUM(p_tcp_header));
+        IPC_HDR_TCP_SET_ACK_NUM(tcp_header, IPC_HDR_TCP_GET_SEQ_NUM(p_tcp_header) + 1);
+        IPC_HDR_TCP_SET_OFFSET(tcp_header, IPC_HDR_TCP_HEADER_SIZE);
+        IPC_HDR_TCP_SET_RESERVED(tcp_header, 0);
+        IPC_HDR_TCP_SET_FLAGS(tcp_header, IPC_HDR_TCP_FLAG_RST | IPC_HDR_TCP_FLAG_ACK);
+        IPC_HDR_TCP_SET_WINDOW(tcp_header, 0);
+        IPC_HDR_TCP_SET_CHECKSUM(tcp_header, 0);
+        IPC_HDR_TCP_SET_URGENT_PTR(tcp_header, 0);
+        sum16 = ipc_calc_tcp_checksum(is_ipv4, src_addr, dst_addr, tcp_header, tcp_header_len);
+        IPC_HDR_TCP_SET_CHECKSUM(tcp_header, sum16);
+
+        IPC_HDR_V4_RESET_VER_IHL_DSCP_ECN(ip_header);
+        IPC_HDR_V4_SET_DSCP(ip_header, IPC_HDR_V4_GET_DSCP(p_packet));
+        IPC_HDR_V4_SET_TOTAL_LENGTH(ip_header, total_len);
+        IPC_HDR_V4_SET_IDENTITY(ip_header, 0);
+        IPC_HDR_V4_SET_FLAGS(ip_header, 0);
+        IPC_HDR_V4_SET_FRAG_OFFSET(ip_header, 0);
+        IPC_HDR_V4_SET_TTL(ip_header, IPC_DEF_TTL);
+        IPC_HDR_V4_SET_PROTOCOL(ip_header, IPC_HDR_PROT_TCP);
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, 0);
+        IPC_HDR_V4_SET_SRC_ADDR(ip_header, src_addr);
+        IPC_HDR_V4_SET_DST_ADDR(ip_header, dst_addr);
+        sum16 = ipc_calc_ipv4_checksum(ip_header);
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, sum16);
+
+        QBM_CACHE_FLUSH(ip_header, total_len);
+
+        QBM_DES_SET_DATALEN(bd, total_len);
+        qbm_cal_set_checksum(bd);
+
+        QBM_DES_SET_DATALEN(ul_gpd, total_len);
+        qbm_cal_set_checksum(ul_gpd);
+    }
+
+    kal_mem_set(&ipc_pkt, 0, sizeof(ipc_pkt));
+    ipc_pkt.isGPD = KAL_TRUE;
+    ipc_pkt.head = ul_gpd;
+    ipc_pkt.tail = ul_gpd;
+    ipc_send_ul_pkt_multiple_ps(&ipc_pkt, NULL, info_p->ebi, info_p->proto_idx);
+
+    hif_trace_info(PFM_TR_GARBAGE_FILTER_REPLY_RST, 0, IPC_HDR_TCP_GET_DST_PORT(p_tcp_header));
+
+free_gpd : 
+    if (p_packet) {
+        pfm_matched_packet_trace(info_p->ebi, p_packet, PFM_MATCHED_PACKET_DUMP_SIZE);
+    }
+    qbmt_dest_q(head_gpd, tail_gpd);
+}
+
+void pfm_garbage_filter_register_parser(void *buf,
+                                        kal_uint32 filter_cnt,
+                                        kal_bool uplink)
+{
+    kal_uint32              idx;
+    pfm_garbage_filter_t *raw_filters = (pfm_garbage_filter_t *) buf;
+    ipc_filter_rules_t      rules;
+
+    for (idx = 0; idx < filter_cnt; idx++) {
+        kal_mem_set(&rules, 0, sizeof(rules));
+
+        if (PFM_FILTER_STRUCT_MAGIC_CODE != raw_filters[idx].magic_code) {
+            hif_trace_error(PFM_TR_GARBAGE_FILTER_WRONG_MAGIC_CODE, __FUNCTION__, idx);
+            PFM_ASSERT(KAL_FALSE);
+            return;
+        }
+
+        if ((IPC_IP_TYPE_IPV4 != raw_filters[idx].ip_type) || (IPC_HDR_PROT_TCP != raw_filters[idx].protocol)) {
+            hif_trace_error(PFM_TR_GARBAGE_FILTER_INVALID_PARAMS, raw_filters[idx].ip_type, raw_filters[idx].protocol);
+            PFM_ASSERT(KAL_FALSE);
+            return;
+        }
+
+        hif_trace_info(PFM_TR_GARBAGE_FILTER_REG_PARSER, raw_filters[idx].filter_id, raw_filters[idx].ip_type, raw_filters[idx].protocol, raw_filters[idx].dst_port);
+
+        rules.features = IPC_FILTER_FEATURE_BWM;
+        rules.priority = raw_filters[idx].filter_id + IPC_DL_FILTER_PRIORITY_PFM_GARBAGE_FILTER_BEGIN;
+        rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_DST_PORT | IPC_FILTER_BY_TCP_FLAGS;
+        rules.ip_type = IPC_IP_TYPE_IPV4;
+        rules.protocol = IPC_HDR_PROT_TCP;
+        rules.dst_port = raw_filters[idx].dst_port;
+        rules.tcp_flags = IPC_HDR_TCP_FLAG_SYN;
+
+        if (PFM_GARBAGE_FILTER_MAX_FILTER < raw_filters[idx].filter_id) {
+            hif_trace_error(PFM_TR_GARBAGE_FILTER_INVALID_FILTER_ID, __FUNCTION__);
+            PFM_ASSERT(KAL_FALSE);
+        } else {
+            pfm_register_filter_cbk(PFM_GARBAGE_FILTER_SET_ID, raw_filters[idx].filter_id, KAL_FALSE, &rules, NULL, NULL);
+        }
+    }
+
+    /* Register filter to trap all left TCP SYN packets. */
+    kal_mem_set(&rules, 0, sizeof(rules));
+    rules.priority = IPC_DL_FILTER_PRIORITY_PFM_GARBAGE_FILTER_END;
+    rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_TCP_FLAGS;
+    rules.ip_type = IPC_IP_TYPE_IPV4;
+    rules.protocol = IPC_HDR_PROT_TCP;
+    rules.tcp_flags = IPC_HDR_TCP_FLAG_SYN;
+    pfm_register_filter_with_info_cbk(PFM_GARBAGE_FILTER_SET_ID,
+    PFM_GARBAGE_FILTER_MAX_FILTER, KAL_FALSE, &rules, pfm_ipc_dl_filter_with_info_cb, NULL);
+}
+
+void pfm_garbage_filter_deregister_callback(void *buf,
+                                            kal_uint32 filter_cnt,
+                                            kal_bool uplink)
+{
+    kal_int32 *filters_buf = buf;
+    pfm_internal_filter_set_t *filter_set = NULL;
+    pfm_internal_filter_set_t *filter_set_list = pfm_get_filter_set_list(uplink);
+    kal_int32 idx;
+
+    filter_set = pfm_get_filter_set_by_id(filter_set_list, NUM_OF_PFM_FILTER_SET_ID, PFM_GARBAGE_FILTER_SET_ID);
+    if (filter_set) {
+        hif_trace_info(PFM_TR_DEREG_FILTERS_INFO, uplink, PFM_GARBAGE_FILTER_SET_ID, filter_cnt);
+        if (-1 == filter_cnt) {
+            /* Deregister all filters. */
+            for (idx = 0; idx < PFM_FILTER_SET_MAX_SIZE; idx++) {
+                if (-1 != filter_set->filters[idx]) {
+                    pfm_deregister_filter((uplink == 1) ? KAL_TRUE : KAL_FALSE, filter_set, idx);
+                    if (0 == filter_set->filter_cnt) {
+                        pfm_delete_filter_set(filter_set);
+                        break;
+                    }
+                }
+            }
+        } else {
+            /* Deregister the specified filters. */
+            if (filter_cnt <= filter_set->filter_cnt) {
+                for (idx = 0; idx < filter_cnt; idx++) {
+                    pfm_deregister_filter((uplink == 1) ? KAL_TRUE : KAL_FALSE, filter_set, filters_buf[idx]);
+                    if (0 == filter_set->filter_cnt) {
+                        PFM_ASSERT(idx == (filter_cnt - 1));
+                        pfm_delete_filter_set(filter_set);
+                    }
+                }
+            } else {
+                PFM_ASSERT(KAL_FALSE);
+            }
+        }
+    } else {
+        hif_trace_error(PFM_TR_DEREG_FILTERS_FILTER_SET_NOT_FOUND, uplink, PFM_GARBAGE_FILTER_SET_ID);
+    }
+
+    return;
+}
+
+void pfm_fin_ack_filter_cbk(ipc_filter_info_t *info_p,
+                            void *context,
+                            kal_int32 filter_id,
+                            qbm_gpd *head_gpd,
+                            qbm_gpd *tail_gpd,
+                            kal_uint32 length)
+{
+    ipc_pkt_t ipc_pkt;
+    qbm_gpd *ul_gpd;
+    qbm_gpd *bd;
+    kal_uint8 *p_data;
+    kal_uint8 *p_packet = NULL;
+    kal_uint8 *src_addr;
+    kal_uint8 *dst_addr;
+    kal_uint8 *p_tcp_header;
+    kal_uint32 ip_header_len;
+    kal_bool is_ipv4;
+
+    hif_data_trace(MD_TRC_PFM_DL_RECEIVED_FILTER_PACKET, head_gpd, tail_gpd);
+
+    if (!QBM_DES_GET_BDP(head_gpd)) {
+        p_packet = QBM_DES_GET_DATAPTR(head_gpd);
+    } else {
+        /* get 1st bd data ptr */
+        bd = QBM_DES_GET_DATAPTR(head_gpd);
+
+        /* Loop to trace 1st DL BD with data buffer */
+        while (bd && (QBM_DES_GET_DATALEN(bd) == 0)) {
+            bd = (QBM_DES_GET_EOL(bd)) ? (NULL) : ((qbm_gpd*) QBM_DES_GET_NEXT(bd));
+        }
+
+        /* No any BD have data */
+        if (NULL == bd) {
+            hif_trace_error(PFM_TR_GARBAGE_FILTER_ZERO_LENGTH_GPD, head_gpd);
+            goto free_gpd;
+        }
+
+        p_packet = QBM_DES_GET_DATAPTR(bd);
+    }
+
+    if (IPC_HDR_IS_V4(p_packet)) {
+        is_ipv4 = KAL_TRUE;
+
+        if (IPC_HDR_PROT_TCP != IPC_HDR_V4_GET_PROTOCOL(p_packet)) {
+            /* Only For TCP packet */
+            hif_trace_error(PFM_TR_GARBAGE_FILTER_NON_TCP_PACKET, head_gpd, IPC_HDR_V4_GET_PROTOCOL(p_packet));
+            goto free_gpd;
+        }
+
+        /* Send IPv4 TCP RST */
+        ip_header_len = (kal_uint32) IPC_HDR_V4_GET_IHL(p_packet);
+        p_tcp_header = p_packet + ip_header_len;
+
+        src_addr = IPC_HDR_V4_GET_DST_ADDR(p_packet);
+        dst_addr = IPC_HDR_V4_GET_SRC_ADDR(p_packet);
+    } else if (IPC_HDR_IS_V6(p_packet)) {
+        is_ipv4 = KAL_FALSE;
+
+        if (IPC_HDR_PROT_TCP != IPC_HDR_V6_GET_NH_TYPE(p_packet)) {
+            /* Only For TCP packet */
+            hif_trace_error(PFM_TR_GARBAGE_FILTER_NON_TCP_PACKET, head_gpd, IPC_HDR_V6_GET_NH_TYPE(p_packet));
+            goto free_gpd;
+        }
+
+        /* Send IPv6 TCP RST */
+        p_tcp_header = p_packet + IPC_HDR_V6_HEADER_SIZE;
+
+        src_addr = IPC_HDR_V6_GET_DST_ADDR(p_packet);
+        dst_addr = IPC_HDR_V6_GET_SRC_ADDR(p_packet);
+    } else {
+        hif_trace_error(PFM_TR_GARBAGE_FILTER_NON_TCP_PACKET, head_gpd, IPC_HDR_V4_GET_PROTOCOL(p_packet));
+        goto free_gpd;
+    }
+
+    /* Allocate a UL GPD */
+    ul_gpd = QBM_ALLOC_ONE(QBM_TYPE_NET_UL);
+    if (!ul_gpd) {
+        hif_trace_info(PFM_TR_GARBAGE_FILTER_REPLY_RST_FAIL, 0, IPC_HDR_TCP_GET_DST_PORT(p_tcp_header));
+        return;
+    }
+
+    bd = QBM_DES_GET_DATAPTR(ul_gpd);
+    p_data = QBM_DES_GET_DATAPTR(bd);
+
+    /* Fill IP/TCP header */
+    {
+        kal_uint16 sum16;
+        kal_uint32 tcp_header_len;
+        kal_uint32 total_len;
+        kal_uint8 *ip_header;     // ip_header for output packet
+        kal_uint8 *tcp_header;    // tcp_header for output packet
+
+        ip_header_len = is_ipv4 ? IPC_HDR_V4_HEADER_SIZE : IPC_HDR_V6_HEADER_SIZE;
+        tcp_header_len = IPC_HDR_TCP_HEADER_SIZE;
+        total_len = ip_header_len + tcp_header_len;
+        ip_header = p_data;
+        tcp_header = ip_header + ip_header_len;
+
+        /* Fill TCP header */
+        IPC_HDR_TCP_SET_SRC_PORT(tcp_header, IPC_HDR_TCP_GET_DST_PORT(p_tcp_header));
+        IPC_HDR_TCP_SET_DST_PORT(tcp_header, IPC_HDR_TCP_GET_SRC_PORT(p_tcp_header));
+        IPC_HDR_TCP_SET_SEQ_NUM(tcp_header, IPC_HDR_TCP_GET_ACK_NUM(p_tcp_header));
+        IPC_HDR_TCP_SET_ACK_NUM(tcp_header, IPC_HDR_TCP_GET_SEQ_NUM(p_tcp_header) + 1);
+        IPC_HDR_TCP_SET_OFFSET(tcp_header, IPC_HDR_TCP_HEADER_SIZE);
+        IPC_HDR_TCP_SET_RESERVED(tcp_header, 0);
+        IPC_HDR_TCP_SET_FLAGS(tcp_header, IPC_HDR_TCP_FLAG_RST | IPC_HDR_TCP_FLAG_ACK);
+        IPC_HDR_TCP_SET_WINDOW(tcp_header, 0);
+        IPC_HDR_TCP_SET_CHECKSUM(tcp_header, 0);
+        IPC_HDR_TCP_SET_URGENT_PTR(tcp_header, 0);
+        sum16 = ipc_calc_tcp_checksum(is_ipv4, src_addr, dst_addr, tcp_header, tcp_header_len);
+        IPC_HDR_TCP_SET_CHECKSUM(tcp_header, sum16);
+
+        if (is_ipv4) {
+            IPC_HDR_V4_RESET_VER_IHL_DSCP_ECN(ip_header);
+            IPC_HDR_V4_SET_DSCP(ip_header, IPC_HDR_V4_GET_DSCP(p_packet));
+            IPC_HDR_V4_SET_TOTAL_LENGTH(ip_header, total_len);
+            IPC_HDR_V4_SET_IDENTITY(ip_header, 0);
+            IPC_HDR_V4_SET_FLAGS(ip_header, 0);
+            IPC_HDR_V4_SET_FRAG_OFFSET(ip_header, 0);
+            IPC_HDR_V4_SET_TTL(ip_header, IPC_DEF_TTL);
+            IPC_HDR_V4_SET_PROTOCOL(ip_header, IPC_HDR_PROT_TCP);
+            IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, 0);
+            IPC_HDR_V4_SET_SRC_ADDR(ip_header, src_addr);
+            IPC_HDR_V4_SET_DST_ADDR(ip_header, dst_addr);
+            sum16 = ipc_calc_ipv4_checksum(ip_header);
+            IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, sum16);
+        } else {
+            IPC_HDR_V6_RESET_VER_TC_FL(ip_header);
+            IPC_HDR_V6_SET_TC(ip_header, IPC_HDR_V6_GET_TC(p_packet));
+            IPC_HDR_V6_SET_FLOW_LABEL(ip_header, IPC_HDR_V6_GET_FLOW_LABEL(p_packet));
+            IPC_HDR_V6_SET_LENGTH(ip_header, total_len);
+            IPC_HDR_V6_SET_NH_TYPE(ip_header, IPC_HDR_PROT_TCP);
+            IPC_HDR_V6_SET_HOP_LIMIT(ip_header, IPC_HDR_V6_GET_HOP_LIMIT(p_packet));
+            IPC_HDR_V6_SET_SRC_ADDR(ip_header, src_addr);
+            IPC_HDR_V6_SET_DST_ADDR(ip_header, dst_addr);
+        }
+
+        QBM_CACHE_FLUSH(ip_header, total_len);
+        QBM_DES_SET_DATALEN(bd, total_len);
+        qbm_cal_set_checksum(bd);
+        QBM_DES_SET_DATALEN(ul_gpd, total_len);
+        qbm_cal_set_checksum(ul_gpd);
+    }
+
+    kal_mem_set(&ipc_pkt, 0, sizeof(ipc_pkt));
+    ipc_pkt.isGPD = KAL_TRUE;
+    ipc_pkt.head = ul_gpd;
+    ipc_pkt.tail = ul_gpd;
+    ipc_send_ul_pkt_multiple_ps(&ipc_pkt, NULL, info_p->ebi, info_p->proto_idx);
+    hif_trace_info(PFM_TR_FIN_ACK_FILTER_REPLY_RST, ul_gpd, IPC_HDR_TCP_GET_DST_PORT(p_tcp_header));
+
+free_gpd :
+    if (p_packet) {
+        pfm_matched_packet_trace(info_p->ebi, p_packet, PFM_MATCHED_PACKET_DUMP_SIZE);
+    }
+    qbmt_dest_q(head_gpd, tail_gpd);
+}
+
+void pfm_fin_ack_filter_register_parser(void *buf,
+                                        kal_uint32 filter_cnt,
+                                        kal_bool uplink)
+{
+    ipc_filter_rules_t v4_rules = {0};
+    ipc_filter_rules_t v6_rules = {0};
+
+    v4_rules.features = IPC_FILTER_FEATURE_PFM_DL;
+    v4_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_TCP_FLAGS;
+    v4_rules.protocol = IPC_HDR_PROT_TCP;
+    v4_rules.tcp_flags = IPC_HDR_TCP_FLAG_ACK | IPC_HDR_TCP_FLAG_FIN;
+    v4_rules.features |= IPC_FILTER_FEATURE_CLONE;
+    v4_rules.ip_type = IPC_IP_TYPE_IPV4;
+
+    v6_rules.features = IPC_FILTER_FEATURE_PFM_DL;
+    v6_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_TCP_FLAGS;
+    v6_rules.protocol = IPC_HDR_PROT_TCP;
+    v6_rules.tcp_flags = IPC_HDR_TCP_FLAG_ACK | IPC_HDR_TCP_FLAG_FIN;
+    v6_rules.features |= IPC_FILTER_FEATURE_CLONE;
+    v6_rules.ip_type = IPC_IP_TYPE_IPV6;
+
+    if (PFM_INVALID_FILTER_ID == g_fin_ack_filter_id_v4) {
+        g_fin_ack_filter_id_v4 = ipc_register_dl_filter_with_info_cbk(&v4_rules, pfm_fin_ack_filter_cbk, NULL);
+        hif_trace_info(PFM_TR_FIN_ACK_FILTER_REGISTER_FILTER_ID_V4, g_fin_ack_filter_id_v4);
+        if (0 > g_fin_ack_filter_id_v4) {
+            hif_trace_error(PFM_TR_FIN_ACK_FILTER_REGISTER_FILTER_FAILED);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_FIN_ACK_FILTER_NO_ACTION_V4, g_fin_ack_filter_id_v4);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_fin_ack_filter_id_v6) {
+        g_fin_ack_filter_id_v6 = ipc_register_dl_filter_with_info_cbk(&v6_rules, pfm_fin_ack_filter_cbk, NULL);
+        hif_trace_info(PFM_TR_FIN_ACK_FILTER_REGISTER_FILTER_ID_V6, g_fin_ack_filter_id_v6);
+        if (0 > g_fin_ack_filter_id_v6) {
+            hif_trace_error(PFM_TR_FIN_ACK_FILTER_REGISTER_FILTER_FAILED);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_FIN_ACK_FILTER_NO_ACTION_V6, g_fin_ack_filter_id_v6);
+    }
+
+    return;
+}
+
+void pfm_fin_ack_filter_deregister_callback(void *buf,
+                                            kal_uint32 filter_cnt,
+                                            kal_bool uplink)
+{
+    ipc_deregister_dl_filter(g_fin_ack_filter_id_v4);
+    ipc_deregister_dl_filter(g_fin_ack_filter_id_v6);
+    g_fin_ack_filter_id_v4 = PFM_INVALID_FILTER_ID;
+    g_fin_ack_filter_id_v6 = PFM_INVALID_FILTER_ID;
+
+    hif_trace_info(PFM_TR_FIN_ACK_FILTER_DEREGISTER_FILTER, g_fin_ack_filter_id_v4, g_fin_ack_filter_id_v6);
+    return;
+}
+
+void pfm_udp_igmp_filter_cbk(ipc_filter_info_t *info_p,
+                             void *context,
+                             kal_int32 filter_id,
+                             qbm_gpd *head_gpd,
+                             qbm_gpd *tail_gpd,
+                             kal_uint32 length)
+{
+    hif_trace_info(PFM_TR_UDP_IGMP_FILTER_DROP, __FUNCTION__, filter_id);
+    qbmt_dest_q(head_gpd, tail_gpd);
+
+    return;
+}
+
+void pfm_udp_igmp_filter_register_parser(void *buf,
+                                         kal_uint32 filter_cnt,
+                                         kal_bool uplink)
+{
+    ipc_filter_rules_t igmp_v4_rules = {0};
+    ipc_filter_rules_t igmp_v6_rules = {0};
+    ipc_filter_rules_t udp_v4_rules = {0};
+    ipc_filter_rules_t udp_v6_rules = {0};
+
+    igmp_v4_rules.features = IPC_FILTER_FEATURE_PFM_DL;
+    igmp_v4_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_NETIF_ID;
+    igmp_v4_rules.protocol = IPC_HDR_PROT_IGMP;
+    igmp_v4_rules.netif_id = IPC_NETIF_ID_ETH_BEGIN;
+    igmp_v4_rules.ip_type = IPC_IP_TYPE_IPV4;
+
+    igmp_v6_rules.features = IPC_FILTER_FEATURE_PFM_DL;
+    igmp_v6_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_NETIF_ID;
+    igmp_v6_rules.protocol = IPC_HDR_PROT_IGMP;
+    igmp_v6_rules.netif_id = IPC_NETIF_ID_ETH_BEGIN;
+    igmp_v6_rules.ip_type = IPC_IP_TYPE_IPV6;
+
+    if (PFM_INVALID_FILTER_ID == g_igmp_filter_id_v4) {
+        g_igmp_filter_id_v4 = ipc_register_ul_filter_with_info_cbk(&igmp_v4_rules, pfm_udp_igmp_filter_cbk, NULL);
+        hif_trace_info(PFM_TR_IGMP_FILTER_REGISTER_FILTER_ID_V4, __FUNCTION__, g_igmp_filter_id_v4);
+        if (0 > g_igmp_filter_id_v4) {
+            hif_trace_error(PFM_TR_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_FILTER_REGISTER_NO_ACTION, __FUNCTION__, g_igmp_filter_id_v4);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_igmp_filter_id_v6) {
+        g_igmp_filter_id_v6 = ipc_register_ul_filter_with_info_cbk(&igmp_v6_rules, pfm_udp_igmp_filter_cbk, NULL);
+        hif_trace_info(PFM_TR_IGMP_FILTER_REGISTER_FILTER_ID_V6, __FUNCTION__, g_igmp_filter_id_v6);
+        if (0 > g_igmp_filter_id_v6) {
+            hif_trace_error(PFM_TR_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_FILTER_REGISTER_NO_ACTION, __FUNCTION__, g_igmp_filter_id_v6);
+    }
+
+    udp_v4_rules.features = IPC_FILTER_FEATURE_PFM_DL;
+    udp_v4_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_NETIF_ID;
+    udp_v4_rules.protocol = IPC_HDR_PROT_UDP;
+    udp_v4_rules.netif_id = IPC_NETIF_ID_ETH_BEGIN;
+    udp_v4_rules.ip_type = IPC_IP_TYPE_IPV4;
+
+    udp_v6_rules.features = IPC_FILTER_FEATURE_PFM_DL;
+    udp_v6_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_NETIF_ID;
+    udp_v6_rules.protocol = IPC_HDR_PROT_UDP;
+    udp_v6_rules.netif_id = IPC_NETIF_ID_ETH_BEGIN;
+    udp_v6_rules.ip_type = IPC_IP_TYPE_IPV6;
+
+    if (PFM_INVALID_FILTER_ID == g_udp_filter_id_v4) {
+        g_udp_filter_id_v4 = ipc_register_ul_filter_with_info_cbk(&udp_v4_rules, pfm_udp_igmp_filter_cbk, NULL);
+        hif_trace_info(PFM_TR_UDP_FILTER_REGISTER_FILTER_ID_V4, __FUNCTION__, g_udp_filter_id_v4);
+        if (0 > g_udp_filter_id_v4) {
+            hif_trace_error(PFM_TR_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_FILTER_REGISTER_NO_ACTION, __FUNCTION__, g_udp_filter_id_v4);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_udp_filter_id_v6) {
+        g_udp_filter_id_v6 = ipc_register_ul_filter_with_info_cbk(&udp_v6_rules, pfm_udp_igmp_filter_cbk, NULL);
+        hif_trace_info(PFM_TR_UDP_FILTER_REGISTER_FILTER_ID_V4, __FUNCTION__, g_udp_filter_id_v6);
+        if (0 > g_udp_filter_id_v6) {
+            hif_trace_error(PFM_TR_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_FILTER_REGISTER_NO_ACTION, __FUNCTION__, g_udp_filter_id_v6);
+    }
+
+    return;
+}
+
+void pfm_udp_igmp_filter_deregister_callback(void *buf,
+                                             kal_uint32 filter_cnt,
+                                             kal_bool uplink)
+{
+    ipc_deregister_dl_filter(g_igmp_filter_id_v4);
+    ipc_deregister_dl_filter(g_igmp_filter_id_v6);
+    ipc_deregister_dl_filter(g_udp_filter_id_v4);
+    ipc_deregister_dl_filter(g_udp_filter_id_v6);
+    g_igmp_filter_id_v4 = PFM_INVALID_FILTER_ID;
+    g_igmp_filter_id_v6 = PFM_INVALID_FILTER_ID;
+    g_udp_filter_id_v4 = PFM_INVALID_FILTER_ID;
+    g_udp_filter_id_v6 = PFM_INVALID_FILTER_ID;
+
+    hif_trace_info(PFM_TR_DEGISTER_IGMP_FILTER, __FUNCTION__, g_igmp_filter_id_v4, g_igmp_filter_id_v6);
+    hif_trace_info(PFM_TR_DEGISTER_UDP_FILTER, __FUNCTION__, g_udp_filter_id_v4, g_udp_filter_id_v6);
+
+    return;
+}
+
+static kal_int32 pfm_str_find_empty_object_idx(kal_uint32 *mask, kal_uint32 max_num, kal_uint32 *total_num)
+{
+    kal_uint32 i;
+
+    for(i = 0; i < max_num; i ++)
+    {
+        if( 0 == ((1 << i) & (*mask))){
+            *mask = (*mask) | (1 << i);
+            (*total_num)++;
+            return i;
+        }
+    }
+    return -1;
+}
+
+static void pfm_str_release_object_by_idx(kal_uint32 index, kal_uint32 *mask, kal_uint32 *total_num)
+{
+    *mask = (*mask) & ~(1 << index);
+    (*total_num)--;
+    return;
+}
+
+static pfmStrFilterNetifInfo* pfm_str_find_netif_by_id(kal_uint32 netif_id)
+{
+    kal_uint32 i = 0;
+
+    for(i = 0; i < PFM_STR_FILTER_NETIF_MAX_NUM; i++){
+        if(g_pfm_str_filter_netif_pool_mask & (1 << i)){
+            if( netif_id == g_pfm_str_filter_netif_pool[i].netif_id){
+                return &g_pfm_str_filter_netif_pool[i];
+            }
+        }
+    }
+    return NULL;
+}
+
+static void pfm_str_netif_remove_filter_by_id(pfmStrFilterNetifInfo *p_netif_info, kal_uint32 filter_id)
+{
+    pfmStrFilterInfo *filter = NULL;
+    pfmStrFilterInfo *prev_filter = NULL;
+
+    if((NULL == p_netif_info) || (0 == p_netif_info->filter_num)){
+        return;
+    }
+
+    filter = p_netif_info->p_head_filter;
+
+    while(NULL != filter){
+        if(filter_id == filter->filter_id){
+            if(NULL == prev_filter){
+                /* 1st filter */
+                p_netif_info->p_head_filter = filter->p_next_filter;
+            }else{
+                /* Non 1st filter */
+                prev_filter->p_next_filter = filter->p_next_filter;
+            }
+            p_netif_info->filter_num--;
+            break;
+        }
+        prev_filter = filter;
+        filter = filter->p_next_filter;
+    }
+    return;
+}
+
+static void pfm_garbage_str_forward_matched_pkt(const kal_uint8 *packet_buff, kal_int32 packet_len, kal_int32 pfm_filter_id)
+{
+    pfm_garbage_str_wake_type_pkt_f pf_wake_type_pkt_cbk = NULL;
+    void* priv_data = NULL;
+
+    PFM_SPIN_LOCK(pfm_spinlock_g);
+    pf_wake_type_pkt_cbk = g_funcptr_mbim_wake_type_pkt_cbk;
+    priv_data = g_priv_data;
+    PFM_SPIN_UNLOCK(pfm_spinlock_g);
+    
+    if (pf_wake_type_pkt_cbk) {
+        hif_trace_info(PFM_TR_GARBAGE_STR_FILTER_PKT_FW, __FUNCTION__, pf_wake_type_pkt_cbk, packet_buff, packet_len, pfm_filter_id);
+        pf_wake_type_pkt_cbk(packet_buff, packet_len, pfm_filter_id, priv_data);
+    } else {
+        /*no callback registered for wake type packet*/
+        hif_trace_error(PFM_TR_GARBAGE_STR_FILTER_CBK_NULL, __FUNCTION__);
+    }
+    return;
+}
+
+static void pfm_garbage_str_filter_with_info_cb(ipc_filter_info_t *info_p,
+                                         void *context,
+                                         kal_int32 filter_id,
+                                         qbm_gpd *head_gpd,
+                                         qbm_gpd *tail_gpd,
+                                         kal_uint32 length)
+{
+    qbmt_dest_q(head_gpd, tail_gpd);
+    return;
+}
+
+kal_bool pfm_garbage_str_cust_filter_cbk(const kal_uint8 *p_pkt,
+                                         kal_int32 pkt_len,
+                                         kal_int32 filter_id,
+                                         void *p_args)
+{
+    kal_uint32 j = 0;
+    kal_uint32 netif_id = 0;
+    kal_bool is_matched = KAL_FALSE;
+    pfmStrFilterInfo *p_filter_info = NULL;
+    pfmStrFilterNetifInfo *p_netif_info = NULL;
+    ipc_filter_info_t *p_ipc_info = NULL;
+    kal_uint8 *p_in_pkt = NULL;
+    upcm_did *p_did = NULL;
+    upcm_did_si *p_si = NULL;
+    kal_uint8 *p_tmp_buf = NULL;
+    kal_bool result = KAL_FALSE;
+
+    p_ipc_info = (ipc_filter_info_t *)p_args;
+    netif_id = p_ipc_info->netif_id;
+    p_netif_info = pfm_str_find_netif_by_id(netif_id);
+
+    /* if packet is not continueous, merge it */
+    if(IPC_FI_DESC_TYPE_DID == p_ipc_info->src_desc_type){
+        p_did = p_ipc_info->src_desc_ptr;
+        p_si = UPCM_DID_GET_SIT_ENTRY_PTR(p_did, p_ipc_info->src_desc_indx);
+        p_tmp_buf = get_ctrl_buffer(pkt_len);
+        if(NULL == p_tmp_buf){
+            goto _return;
+        }
+        result = ipc_get_continuous_content_did(p_si->p_data, UPCM_DID_SI_GET_OFFSET(p_si), p_did, p_ipc_info->src_desc_indx, pkt_len, &p_in_pkt, p_tmp_buf);
+        if(KAL_FALSE == result){
+            goto _return;
+        }
+    }
+
+    if(NULL != p_netif_info){
+        p_filter_info = p_netif_info->p_head_filter;
+        while ((NULL != p_filter_info) && (KAL_FALSE == is_matched)) {
+            if (pkt_len >= p_filter_info->filter_len) {
+                for (j = 0 ; j < p_filter_info->filter_len; j++) {
+                    if (0 == p_filter_info->mask_str[j]) {
+                        continue;
+                    }
+                    if(NULL != p_in_pkt){
+                        if ((p_filter_info->mask_str[j] & p_in_pkt[j]) !=
+                            (p_filter_info->mask_str[j] & p_filter_info->filter_str[j])) {
+                            is_matched = KAL_FALSE;
+                            break;
+                        }
+                    }else{
+                        if ((p_filter_info->mask_str[j] & p_pkt[j]) !=
+                            (p_filter_info->mask_str[j] & p_filter_info->filter_str[j])) {
+                            is_matched = KAL_FALSE;
+                            break;
+                        }
+                    }
+                    is_matched = KAL_TRUE;
+                    pfm_garbage_str_forward_matched_pkt(p_in_pkt ? p_in_pkt : p_pkt, pkt_len, p_filter_info->filter_id);
+                }
+            }
+            p_filter_info = p_filter_info->p_next_filter;
+        }
+    }
+
+_return:
+    if(NULL != p_tmp_buf){
+        free_ctrl_buffer(p_tmp_buf);    
+    }
+
+    return !is_matched;
+}
+
+void pfm_garbage_str_filter_register_parser(void *buf,
+                                            kal_uint32 filter_cnt,
+                                            kal_bool uplink)
+{
+    kal_uint8 i = 0;
+    kal_uint32 index = 0;
+    pfm_str_filter_t *p_single_filter = (pfm_str_filter_t*)buf;
+    pfmStrFilterInfo *p_filter_info = NULL;
+    pfmStrFilterNetifInfo *p_netif = NULL;
+    ipc_filter_rules_t wildcard_rule = {0};
+    ipc_filter_ntfy_ctxt_t ntfy_context = {0};
+    pfm_internal_filter_set_t *p_filter_set = NULL;
+    pfm_internal_filter_set_t *p_filter_set_list = pfm_get_filter_set_list(uplink);
+
+    hif_trace_info(PFM_TR_GARBAGE_STR_FILTER_CMD_PARSER, __FUNCTION__, KAL_TRUE, buf, filter_cnt, uplink);
+    PFM_ASSERT(NULL != buf);
+    PFM_ASSERT(KAL_FALSE == uplink);
+
+    p_filter_set = pfm_get_filter_set_by_id(p_filter_set_list, NUM_OF_PFM_FILTER_SET_ID, PFM_GARBAGE_STR_FILTER_SET_ID);
+
+    PFM_ASSERT(NULL != p_filter_set);
+    
+    /* Store string filter */
+    for(i = 0; i < filter_cnt; i++){
+        if(PFM_STR_FILTER_MAGIC_CODE != p_single_filter->magic_code) {
+            hif_trace_info(PFM_TR_GARBAGE_FILTER_WRONG_MAGIC_CODE, __FUNCTION__, i);
+            PFM_ASSERT(KAL_FALSE);
+            return;
+        }
+
+        if (PFM_GARBAGE_FILTER_MAX_FILTER < p_single_filter->filter_id) {
+            hif_trace_error(PFM_TR_GARBAGE_FILTER_INVALID_FILTER_ID, __FUNCTION__);
+            PFM_ASSERT(KAL_FALSE);
+        }
+
+        hif_trace_info(PFM_TR_GARBAGE_STR_FILTER_REG_PARSER, __FUNCTION__, p_single_filter->filter_id, p_single_filter->netif_id, p_single_filter->filter_len, p_single_filter->mask_len);
+
+        /* Check if filter_id is already used */
+        if(-1 != p_filter_set->filters[p_single_filter->filter_id]){
+            /* remove previous first */
+            hif_trace_info(PFM_TR_GARBAGE_STR_FILTER_FLT_ID_EXIST, __FUNCTION__, p_single_filter->filter_id);
+            index = p_filter_set->filters[p_single_filter->filter_id];
+            p_filter_info = &g_pfm_str_filter_pool[index];
+            p_netif = pfm_str_find_netif_by_id(p_filter_info->netif_id);
+            PFM_ASSERT(NULL != p_netif);
+            
+            pfm_str_netif_remove_filter_by_id(p_netif, p_single_filter->filter_id);
+            pfm_str_release_object_by_idx(index, &g_pfm_str_filter_pool_mask, &g_pfm_str_filter_num);
+            p_filter_set->filters[p_single_filter->filter_id] = -1;
+            p_filter_set->filter_cnt--;
+
+            if(0 == p_netif->filter_num){
+                pfm_str_release_object_by_idx(p_netif->index, &g_pfm_str_filter_netif_pool_mask, &g_pfm_str_filter_netif_num);
+            }
+        }
+        
+        p_netif = pfm_str_find_netif_by_id(p_single_filter->netif_id);
+        if(NULL == p_netif)
+        {
+            /* Allocate new one */
+            index = pfm_str_find_empty_object_idx(&g_pfm_str_filter_netif_pool_mask, PFM_STR_FILTER_NETIF_MAX_NUM, &g_pfm_str_filter_netif_num);
+            if(-1 == index)
+            {
+                hif_trace_info(PFM_TR_GARBAGE_STR_FILTER_NETIF_ALLOC_NG, __FUNCTION__, g_pfm_str_filter_netif_pool_mask, g_pfm_str_filter_netif_num, p_single_filter->netif_id);
+                PFM_ASSERT(KAL_FALSE);
+            }
+            p_netif = &g_pfm_str_filter_netif_pool[index];
+            kal_mem_set(p_netif, 0, sizeof(pfmStrFilterNetifInfo));
+            p_netif->netif_id = p_single_filter->netif_id;
+            p_netif->index = index;
+        }
+        
+        index = pfm_str_find_empty_object_idx(&g_pfm_str_filter_pool_mask, PFM_STR_FILTER_MAX_NUM, &g_pfm_str_filter_num);
+        if(-1 == index){
+            hif_trace_info(PFM_TR_GARBAGE_STR_FILTER_ALLOC_NG, __FUNCTION__, g_pfm_str_filter_pool_mask, g_pfm_str_filter_num, p_single_filter->filter_id);
+            PFM_ASSERT(KAL_FALSE);
+            return;
+        }
+        p_filter_info = &g_pfm_str_filter_pool[index];
+        kal_mem_set(p_filter_info, 0, sizeof(pfmStrFilterInfo));
+
+        kal_mem_cpy(p_filter_info, p_single_filter, sizeof(pfm_str_filter_t));
+        p_filter_info->p_netif = p_netif;
+        p_filter_info->p_next_filter = NULL;
+
+        if(NULL == p_netif->p_head_filter){
+            p_netif->p_head_filter = p_filter_info;
+        }else{
+            p_filter_info->p_next_filter = p_netif->p_head_filter;
+            p_netif->p_head_filter = p_filter_info;
+        }
+        p_netif->filter_num++;
+
+        p_filter_set->filter_cnt++;
+        p_filter_set->filters[p_single_filter->filter_id] = index;
+        p_single_filter++;
+    }
+    if(PFM_INVALID_FILTER_ID == g_pfm_str_filter_id){
+        /* Switch IPCORE DL mode to SW mode*/
+        ipc_filter_switch_dl_mode(IPC_SW_DL_MODE_STR);
+    
+        /* Register filter to IPCORE */
+        wildcard_rule.features = IPC_FILTER_FEATURE_PFM_DL | IPC_FILTER_FEATURE_CUST_FILTER_W_INFO | IPC_FILTER_FEATURE_WC;
+        wildcard_rule.cust_cbk_func = pfm_garbage_str_cust_filter_cbk;
+        wildcard_rule.priority = IPC_DL_FILTER_PRIORITY_PFM_GARBAGE_FILTER_END;
+        ntfy_context.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+        ntfy_context.ntfy_mod.with_info_cbk_func = pfm_garbage_str_filter_with_info_cb;
+    
+        g_pfm_str_filter_id = ipc_reg_filter(DL_DIRECT, &wildcard_rule, &ntfy_context);
+
+        hif_trace_error(PFM_TR_GARBAGE_STR_FILTER_IPC_FILTER_ID, __FUNCTION__, g_pfm_str_filter_id);
+
+        PFM_ASSERT(-1 != g_pfm_str_filter_id);
+    }
+
+    return;
+}
+
+void pfm_garbage_str_filter_deregister_callback(void *buf,
+                                                kal_uint32 filter_cnt,
+                                                kal_bool uplink)
+{
+    kal_uint32 i = 0;
+    kal_uint32 netif_id = 0;
+    kal_int32 *filter_ids = (kal_int32*) buf;
+    pfm_internal_filter_set_t *p_filter_set = NULL;
+    pfm_internal_filter_set_t *p_filter_set_list = pfm_get_filter_set_list(uplink);
+    pfmStrFilterInfo *p_filter_info = NULL;
+    kal_uint32 filter_idx_internal = 0;
+    pfmStrFilterNetifInfo* p_netif_info = NULL;
+
+    hif_trace_info(PFM_TR_GARBAGE_STR_FILTER_CMD_PARSER, __FUNCTION__, KAL_FALSE, buf, filter_cnt, uplink);
+    
+    p_filter_set = pfm_get_filter_set_by_id(p_filter_set_list, NUM_OF_PFM_FILTER_SET_ID, PFM_GARBAGE_STR_FILTER_SET_ID);
+
+    PFM_ASSERT(NULL != p_filter_set);
+    
+    if(-1 == filter_cnt){
+        /* Deregister all filters */
+        for(i = 0; i < PFM_STR_FILTER_MAX_NUM; i++){
+            if(g_pfm_str_filter_pool_mask & (1 << i)){
+                pfm_str_release_object_by_idx(i, &g_pfm_str_filter_pool_mask, &g_pfm_str_filter_num);
+                p_filter_info = &g_pfm_str_filter_pool[i];
+                p_filter_set->filters[p_filter_info->filter_id] = -1;
+                p_filter_set->filter_cnt--;
+            }
+        }
+        for(i = 0; i < PFM_STR_FILTER_NETIF_MAX_NUM; i++){
+            if(g_pfm_str_filter_netif_pool_mask & (1 << i)){
+                pfm_str_release_object_by_idx(i, &g_pfm_str_filter_netif_pool_mask, &g_pfm_str_filter_netif_num);
+            }
+        }   
+        PFM_ASSERT(!g_pfm_str_filter_num && !g_pfm_str_filter_netif_num && !p_filter_set->filter_cnt);
+    }else{
+        /* Deregister specific filters */
+        PFM_ASSERT(NULL != buf);
+        if(filter_cnt <= g_pfm_str_filter_num){
+            for(i = 0; i < filter_cnt; i++){
+                if((filter_ids[i] < 0) || (filter_ids[i] > PFM_FILTER_SET_MAX_SIZE)){
+                    PFM_ASSERT(KAL_FALSE);
+                    return;
+                }
+                filter_idx_internal = (kal_uint32)p_filter_set->filters[filter_ids[i]];
+                PFM_ASSERT(g_pfm_str_filter_pool_mask & (1 << filter_idx_internal));
+                p_filter_info = &g_pfm_str_filter_pool[filter_idx_internal];
+                netif_id = p_filter_info->netif_id;
+                p_netif_info = pfm_str_find_netif_by_id(netif_id);
+                PFM_ASSERT(NULL != p_netif_info);
+                
+                pfm_str_netif_remove_filter_by_id(p_netif_info, filter_ids[i]);
+                pfm_str_release_object_by_idx(filter_idx_internal, &g_pfm_str_filter_pool_mask, &g_pfm_str_filter_num);
+                p_filter_set->filters[filter_ids[i]] = -1;
+                p_filter_set->filter_cnt--;
+
+                if(0 == p_netif_info->filter_num){
+                    pfm_str_release_object_by_idx(p_netif_info->index, &g_pfm_str_filter_netif_pool_mask, &g_pfm_str_filter_netif_num);
+                }
+            }
+        }else{
+            hif_trace_info(PFM_TR_GARBAGE_STR_FILTER_DEREG_CNT_NG, __FUNCTION__);
+            PFM_ASSERT(KAL_FALSE);
+        }
+    }
+
+    if(0 == p_filter_set->filter_cnt){
+        hif_trace_info(PFM_TR_GARBAGE_STR_FILTER_DEREG_DEL, __FUNCTION__, g_pfm_str_filter_id);
+        pfm_delete_filter_set(p_filter_set);
+
+        if(PFM_INVALID_FILTER_ID != g_pfm_str_filter_id){
+            ipc_dereg_filter(g_pfm_str_filter_id);
+            g_pfm_str_filter_id = PFM_INVALID_FILTER_ID;
+        }
+        /* Switch IPCORE DL mode to HW mode*/
+        ipc_filter_switch_dl_mode(IPC_HW_DL_MODE_STR);
+    }
+        
+    return;
+}
+
+void pfm_icmp_ping_filter_with_info_cb(ipc_filter_info_t *info_p,
+                                         void *context,
+                                         kal_int32 filter_id,
+                                         qbm_gpd *head_gpd,
+                                         qbm_gpd *tail_gpd,
+                                         kal_uint32 length)
+{
+    qbmt_dest_q(head_gpd, tail_gpd);
+    return;
+}
+
+kal_bool pfm_icmp_ping_filter_cust_cbk(const kal_uint8 *p_pkt,
+                                         kal_int32 pkt_len,
+                                         kal_int32 filter_id,
+                                         void *p_args)
+{
+	/* Do nothing */
+    return KAL_FALSE;
+}
+
+void pfm_icmp_ping_filter_register_parser(void *buf,
+                                         kal_uint32 filter_cnt,
+                                         kal_bool uplink)
+{
+    ipc_filter_rules_t icmpv4_req_rules = {0};
+    ipc_filter_rules_t icmpv4_reply_rules = {0};
+    ipc_filter_rules_t icmpv6_req_rules = {0};
+    ipc_filter_rules_t icmpv6_reply_rules = {0};
+    ipc_filter_ntfy_ctxt_t ntfy_context = {0};
+
+    ntfy_context.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+    ntfy_context.ntfy_mod.with_info_cbk_func = pfm_icmp_ping_filter_with_info_cb;
+
+    if (PFM_INVALID_FILTER_ID == g_icmpv4_echo_req_filter_id) {  
+        /* Register ICMPV4 Echo Request filter to IPCORE */
+        icmpv4_req_rules.features = IPC_FILTER_FEATURE_PFM_DL | IPC_FILTER_FEATURE_CUST_FILTER_W_INFO;
+        icmpv4_req_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_ICMPV4_TYPE;
+        icmpv4_req_rules.protocol = IPC_HDR_PROT_ICMP;
+        icmpv4_req_rules.ip_type = IPC_IP_TYPE_IPV4;
+        icmpv4_req_rules.icmpv4_type = IPC_HDR_ICMP_TYPE_ECHO_REQUEST;
+        icmpv4_req_rules.cust_cbk_func = pfm_icmp_ping_filter_cust_cbk;
+    
+        g_icmpv4_echo_req_filter_id = ipc_reg_filter(DL_DIRECT, &icmpv4_req_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_ICMPV4_PING_REQ_FILTER_IPC_FILTER_ID, __FUNCTION__, g_icmpv4_echo_req_filter_id);
+        if (0 > g_icmpv4_echo_req_filter_id) {
+            hif_trace_error(PFM_TR_ICMP_PING_FILTER_REGISTER_FAILED, __FUNCTION__, __LINE__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_ICMP_PING_FILTER_NO_ACTION, __FUNCTION__,  __LINE__, g_icmpv4_echo_req_filter_id);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_icmpv4_echo_reply_filter_id) {  
+        /* Register ICMPV4 Echo Reply filter to IPCORE */
+        icmpv4_reply_rules.features = IPC_FILTER_FEATURE_PFM_DL | IPC_FILTER_FEATURE_CUST_FILTER_W_INFO;
+        icmpv4_reply_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_ICMPV4_TYPE;
+        icmpv4_reply_rules.protocol = IPC_HDR_PROT_ICMP;
+        icmpv4_reply_rules.ip_type = IPC_IP_TYPE_IPV4;
+        icmpv4_reply_rules.icmpv4_type = IPC_HDR_ICMP_TYPE_ECHO_REPLY;
+        icmpv4_reply_rules.cust_cbk_func = pfm_icmp_ping_filter_cust_cbk;
+
+        g_icmpv4_echo_reply_filter_id = ipc_reg_filter(DL_DIRECT, &icmpv4_reply_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_ICMPV4_PING_REPLY_FILTER_IPC_FILTER_ID, __FUNCTION__, g_icmpv4_echo_reply_filter_id);
+        if (0 > g_icmpv4_echo_reply_filter_id) {
+            hif_trace_error(PFM_TR_ICMP_PING_FILTER_REGISTER_FAILED, __FUNCTION__, __LINE__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_ICMP_PING_FILTER_NO_ACTION, __FUNCTION__,  __LINE__, g_icmpv4_echo_reply_filter_id);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_icmpv6_echo_req_filter_id) {  
+        /* Register ICMPV6 Echo Request filter to IPCORE */
+        icmpv6_req_rules.features = IPC_FILTER_FEATURE_PFM_DL | IPC_FILTER_FEATURE_CUST_FILTER_W_INFO;
+        icmpv6_req_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_ICMPV6_TYPE;
+        icmpv6_req_rules.protocol = IPC_HDR_PROT_ICMPV6;
+        icmpv6_req_rules.ip_type = IPC_IP_TYPE_IPV6;
+        icmpv6_req_rules.icmpv6_type = IPC_HDR_ICMPV6_TYPE_ECHO_REQUEST;
+        icmpv6_req_rules.cust_cbk_func = pfm_icmp_ping_filter_cust_cbk;
+    
+        g_icmpv6_echo_req_filter_id = ipc_reg_filter(DL_DIRECT, &icmpv6_req_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_ICMPV6_PING_REQ_FILTER_IPC_FILTER_ID, __FUNCTION__, g_icmpv6_echo_req_filter_id);
+        if (0 > g_icmpv6_echo_req_filter_id) {
+            hif_trace_error(PFM_TR_ICMP_PING_FILTER_REGISTER_FAILED, __FUNCTION__, __LINE__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_ICMP_PING_FILTER_NO_ACTION, __FUNCTION__,  __LINE__, g_icmpv6_echo_req_filter_id);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_icmpv6_echo_reply_filter_id) {  
+        /* Register ICMPV6 Echo Reply filter to IPCORE */
+        icmpv6_reply_rules.features = IPC_FILTER_FEATURE_PFM_DL | IPC_FILTER_FEATURE_CUST_FILTER_W_INFO;
+        icmpv6_reply_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_ICMPV6_TYPE;
+        icmpv6_reply_rules.protocol = IPC_HDR_PROT_ICMPV6;
+        icmpv6_reply_rules.ip_type = IPC_IP_TYPE_IPV6;
+        icmpv6_reply_rules.icmpv6_type = IPC_HDR_ICMPV6_TYPE_ECHO_REPLY;
+        icmpv6_reply_rules.cust_cbk_func = pfm_icmp_ping_filter_cust_cbk;
+
+        g_icmpv6_echo_reply_filter_id = ipc_reg_filter(DL_DIRECT, &icmpv6_reply_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_ICMPV6_PING_REPLY_FILTER_IPC_FILTER_ID, __FUNCTION__, g_icmpv6_echo_reply_filter_id);
+        if (0 > g_icmpv6_echo_reply_filter_id) {
+            hif_trace_error(PFM_TR_ICMP_PING_FILTER_REGISTER_FAILED, __FUNCTION__, __LINE__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_ICMP_PING_FILTER_NO_ACTION, __FUNCTION__,  __LINE__, g_icmpv6_echo_reply_filter_id);
+    }
+
+    return;
+}
+
+void pfm_icmp_ping_filter_deregister_callback(void *buf,
+                                             kal_uint32 filter_cnt,
+                                             kal_bool uplink)
+{
+    ipc_deregister_dl_filter(g_icmpv4_echo_req_filter_id);
+    ipc_deregister_dl_filter(g_icmpv4_echo_reply_filter_id);
+    ipc_deregister_dl_filter(g_icmpv6_echo_req_filter_id);
+    ipc_deregister_dl_filter(g_icmpv6_echo_reply_filter_id);
+    g_icmpv4_echo_req_filter_id = PFM_INVALID_FILTER_ID;
+    g_icmpv4_echo_reply_filter_id = PFM_INVALID_FILTER_ID;
+    g_icmpv6_echo_req_filter_id = PFM_INVALID_FILTER_ID;
+    g_icmpv6_echo_reply_filter_id = PFM_INVALID_FILTER_ID;
+
+    hif_trace_info(PFM_TR_DEGISTER_ICMPV4_PING_FILTER, __FUNCTION__, g_icmpv4_echo_req_filter_id, g_icmpv4_echo_reply_filter_id);
+    hif_trace_info(PFM_TR_DEGISTER_ICMPV6_PING_FILTER, __FUNCTION__, g_icmpv6_echo_req_filter_id, g_icmpv6_echo_reply_filter_id);
+
+    return;
+}
+
+void pfm_ul_disable_all_packets_filter_cbk(ipc_filter_info_t *info_p,
+                             void *context,
+                             kal_int32 filter_id,
+                             qbm_gpd *head_gpd,
+                             qbm_gpd *tail_gpd,
+                             kal_uint32 length)
+{
+    hif_trace_info(PFM_TR_DISABLE_ALL_PACKETS_FILTER_DROP, __FUNCTION__, filter_id);
+    qbmt_dest_q(head_gpd, tail_gpd);
+
+    return;
+}
+
+void pfm_ul_disable_all_packets_filter_register_parser(void *buf,
+                                         kal_uint32 filter_cnt,
+                                         kal_bool uplink)
+{
+    ipc_filter_rules_t wc_rules = {0};
+
+    wc_rules.features = IPC_FILTER_FEATURE_WC;
+    wc_rules.priority = PFM_UL_ICMP_PING_WHITELIST_HIGH_PRIORITY;
+
+    if (PFM_INVALID_FILTER_ID == g_ul_disable_all_packets_filter_id) {
+        g_ul_disable_all_packets_filter_id = ipc_register_ul_filter_with_info_cbk(&wc_rules, pfm_ul_disable_all_packets_filter_cbk, NULL);
+        hif_trace_info(PFM_TR_DISABLE_ALL_PACKETS_FILTER_REGISTER_FILTER_ID, __FUNCTION__, g_ul_disable_all_packets_filter_id);
+        if (0 > g_ul_disable_all_packets_filter_id) {
+            hif_trace_error(PFM_TR_DISABLE_ALL_PACKETS_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_DISABLE_ALL_PACKETS_FILTER_NO_ACTION, __FUNCTION__, g_ul_disable_all_packets_filter_id);
+    }
+    return;
+}
+
+void pfm_ul_disable_all_packets_filter_deregister_callback(void *buf,
+                                             kal_uint32 filter_cnt,
+                                             kal_bool uplink)
+{
+    ipc_deregister_ul_filter(g_ul_disable_all_packets_filter_id);
+    g_ul_disable_all_packets_filter_id = PFM_INVALID_FILTER_ID;
+	
+    hif_trace_info(PFM_TR_DEREG_DISABLE_ALL_PACKETS_FILTER, __FUNCTION__, g_ul_disable_all_packets_filter_id);
+
+    return;
+}
+
+
+kal_bool pfm_ul_icmp_ping_whitelist_filter_cust_cbk(const kal_uint8 *p_pkt,
+                                         kal_int32 pkt_len,
+                                         kal_int32 filter_id,
+                                         void *p_args)
+{
+	/* Do nothing */
+    return KAL_FALSE;
+}
+
+void pfm_ul_icmp_ping_whitelist_filter_cbk(ipc_filter_info_t *info_p,
+                             void *context,
+                             kal_int32 filter_id,
+                             qbm_gpd *head_gpd,
+                             qbm_gpd *tail_gpd,
+                             kal_uint32 length)
+{
+    hif_trace_info(PFM_TR_ICMP_PING_WHITELIST_FILTER_DROP, __FUNCTION__, filter_id);
+    qbmt_dest_q(head_gpd, tail_gpd);
+
+    return;
+}
+
+void pfm_ul_icmp_ping_whitelist_filter_register_parser(void *buf,
+                                         kal_uint32 filter_cnt,
+                                         kal_bool uplink)
+{
+    ipc_filter_rules_t icmpv4_req_rules = {0};
+    ipc_filter_rules_t icmpv4_reply_rules = {0};
+    ipc_filter_rules_t icmpv6_req_rules = {0};
+    ipc_filter_rules_t icmpv6_reply_rules = {0};
+    ipc_filter_rules_t wc_rules = {0};
+    ipc_filter_ntfy_ctxt_t ntfy_context = {0};
+
+    ntfy_context.ntfy_type = IPC_FILTER_NTFY_CBK_FUNC_WITH_FILTER_INFO;
+    ntfy_context.ntfy_mod.with_info_cbk_func = pfm_ul_icmp_ping_whitelist_filter_cbk;
+
+    if (PFM_INVALID_FILTER_ID == g_ul_icmpv4_echo_req_whitelist_filter_id) {  
+        /* Register ICMPV4 Echo Request filter to IPCORE */
+        icmpv4_req_rules.features = IPC_FILTER_FEATURE_BWM;
+        icmpv4_req_rules.priority = PFM_UL_ICMP_PING_WHITELIST_HIGH_PRIORITY;
+        icmpv4_req_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_ICMPV4_TYPE;
+        icmpv4_req_rules.protocol = IPC_HDR_PROT_ICMP;
+        icmpv4_req_rules.ip_type = IPC_IP_TYPE_IPV4;
+        icmpv4_req_rules.icmpv4_type = IPC_HDR_ICMP_TYPE_ECHO_REQUEST;
+        icmpv4_req_rules.cust_cbk_func = pfm_ul_icmp_ping_whitelist_filter_cust_cbk;
+    
+        g_ul_icmpv4_echo_req_whitelist_filter_id = ipc_reg_filter(UL_DIRECT, &icmpv4_req_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_ICMPV4_PING_REQ_BYPASS_FILTER_IPC_FILTER_ID, __FUNCTION__, g_ul_icmpv4_echo_req_whitelist_filter_id);
+        if (0 > g_ul_icmpv4_echo_req_whitelist_filter_id) {
+            hif_trace_error(PFM_TR_ICMPV4_PING_REQ_BYPASS_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_ICMPV4_PING_REQ_BYPASS_FILTER_NO_ACTION, __FUNCTION__,  g_ul_icmpv4_echo_req_whitelist_filter_id);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_ul_icmpv4_echo_reply_whitelist_filter_id) {  
+        /* Register ICMPV4 Echo Reply filter to IPCORE */
+        icmpv4_reply_rules.features = IPC_FILTER_FEATURE_BWM;
+        icmpv4_reply_rules.priority = PFM_UL_ICMP_PING_WHITELIST_HIGH_PRIORITY;
+        icmpv4_reply_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_ICMPV4_TYPE;
+        icmpv4_reply_rules.protocol = IPC_HDR_PROT_ICMP;
+        icmpv4_reply_rules.ip_type = IPC_IP_TYPE_IPV4;
+        icmpv4_reply_rules.icmpv4_type = IPC_HDR_ICMP_TYPE_ECHO_REPLY;
+        icmpv4_reply_rules.cust_cbk_func = pfm_ul_icmp_ping_whitelist_filter_cust_cbk;
+
+        g_ul_icmpv4_echo_reply_whitelist_filter_id = ipc_reg_filter(UL_DIRECT, &icmpv4_reply_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_ICMPV4_PING_REPLY_BYPASS_FILTER_IPC_FILTER_ID, __FUNCTION__, g_ul_icmpv4_echo_reply_whitelist_filter_id);
+        if (0 > g_ul_icmpv4_echo_reply_whitelist_filter_id) {
+            hif_trace_error(PFM_TR_ICMPV4_PING_REPLY_BYPASS_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_ICMPV4_PING_REPLY_BYPASS_FILTER_NO_ACTION, __FUNCTION__,  g_ul_icmpv4_echo_reply_whitelist_filter_id);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_ul_icmpv6_echo_req_whitelist_filter_id) {  
+        /* Register ICMPV6 Echo Request filter to IPCORE */
+        icmpv6_req_rules.features = IPC_FILTER_FEATURE_BWM;
+        icmpv6_req_rules.priority = PFM_UL_ICMP_PING_WHITELIST_HIGH_PRIORITY;
+        icmpv6_req_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_ICMPV6_TYPE;
+        icmpv6_req_rules.protocol = IPC_HDR_PROT_ICMPV6;
+        icmpv6_req_rules.ip_type = IPC_IP_TYPE_IPV6;
+        icmpv6_req_rules.icmpv6_type = IPC_HDR_ICMPV6_TYPE_ECHO_REQUEST;
+        icmpv6_req_rules.cust_cbk_func = pfm_ul_icmp_ping_whitelist_filter_cust_cbk;
+    
+        g_ul_icmpv6_echo_req_whitelist_filter_id = ipc_reg_filter(UL_DIRECT, &icmpv6_req_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_ICMPV6_PING_REQ_BYPASS_FILTER_IPC_FILTER_ID, __FUNCTION__, g_ul_icmpv6_echo_req_whitelist_filter_id);
+        if (0 > g_ul_icmpv6_echo_req_whitelist_filter_id) {
+            hif_trace_error(PFM_TR_ICMPV6_PING_REQ_BYPASS_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_ICMPV6_PING_REQ_BYPASS_FILTER_NO_ACTION, __FUNCTION__,  g_ul_icmpv6_echo_req_whitelist_filter_id);
+    }
+
+    if (PFM_INVALID_FILTER_ID ==g_ul_icmpv6_echo_reply_whitelist_filter_id) {  
+        /* Register ICMPV6 Echo Reply filter to IPCORE */
+        icmpv6_reply_rules.features = IPC_FILTER_FEATURE_BWM;
+        icmpv6_reply_rules.priority = PFM_UL_ICMP_PING_WHITELIST_HIGH_PRIORITY;
+        icmpv6_reply_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_ICMPV6_TYPE;
+        icmpv6_reply_rules.protocol = IPC_HDR_PROT_ICMPV6;
+        icmpv6_reply_rules.ip_type = IPC_IP_TYPE_IPV6;
+        icmpv6_reply_rules.icmpv6_type = IPC_HDR_ICMPV6_TYPE_ECHO_REPLY;
+        icmpv6_reply_rules.cust_cbk_func = pfm_ul_icmp_ping_whitelist_filter_cust_cbk;
+
+        g_ul_icmpv6_echo_reply_whitelist_filter_id = ipc_reg_filter(UL_DIRECT, &icmpv6_reply_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_ICMPV6_PING_REPLY_BYPASS_FILTER_IPC_FILTER_ID, __FUNCTION__, g_ul_icmpv6_echo_reply_whitelist_filter_id);
+        if (0 > g_ul_icmpv6_echo_reply_whitelist_filter_id) {
+            hif_trace_error(PFM_TR_ICMPV6_PING_REPLY_BYPASS_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_ICMPV6_PING_REPLY_BYPASS_FILTER_NO_ACTION, __FUNCTION__,  g_ul_icmpv6_echo_reply_whitelist_filter_id);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_ul_icmpv6_rs_whitelist_filter_id) {  
+        /* Register ICMPV6 RS filter to IPCORE */
+        icmpv6_req_rules.features = IPC_FILTER_FEATURE_BWM;
+        icmpv6_req_rules.priority = PFM_UL_ICMP_PING_WHITELIST_HIGH_PRIORITY;
+        icmpv6_req_rules.valid_fields = IPC_FILTER_BY_PROTOCOL | IPC_FILTER_BY_ICMPV6_TYPE;
+        icmpv6_req_rules.protocol = IPC_HDR_PROT_ICMPV6;
+        icmpv6_req_rules.ip_type = IPC_IP_TYPE_IPV6;
+        icmpv6_req_rules.icmpv6_type = IPC_HDR_ICMPV6_TYPE_RS;
+        icmpv6_req_rules.cust_cbk_func = pfm_ul_icmp_ping_whitelist_filter_cust_cbk;
+    
+        g_ul_icmpv6_rs_whitelist_filter_id = ipc_reg_filter(UL_DIRECT, &icmpv6_req_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_ICMPV6_RS_BYPASS_FILTER_IPC_FILTER_ID, __FUNCTION__, g_ul_icmpv6_rs_whitelist_filter_id);
+        if (0 > g_ul_icmpv6_rs_whitelist_filter_id) {
+            hif_trace_error(PFM_TR_ICMPV6_RS_BYPASS_FILTER_REGISTER_FAILED, __FUNCTION__);
+            return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_ICMPV6_RS_BYPASS_FILTER_NO_ACTION, __FUNCTION__,  g_ul_icmpv6_rs_whitelist_filter_id);
+    }
+
+    if (PFM_INVALID_FILTER_ID == g_ul_non_ping_filter_id) {
+        /* Register wild card filter to IPCORE to filter out all packets left*/
+        wc_rules.features = IPC_FILTER_FEATURE_WC;
+        wc_rules.priority = PFM_UL_ICMP_PING_WHITELIST_LOW_PRIORITY;
+
+        g_ul_non_ping_filter_id = ipc_reg_filter(UL_DIRECT, &wc_rules, &ntfy_context);
+        hif_trace_info(PFM_TR_NON_PING_FILTER_REGISTER_FILTER_ID, __FUNCTION__, g_ul_non_ping_filter_id);
+	    if (0 > g_ul_non_ping_filter_id) {
+            hif_trace_error(PFM_TR_NON_PING_FILTER_REGISTER_FAILED, __FUNCTION__);
+	        return;
+        }
+    } else {
+        hif_trace_info(PFM_TR_NON_PING_FILTER_NO_ACTION, __FUNCTION__, g_ul_non_ping_filter_id);
+    }
+    return;
+}
+
+void pfm_ul_icmp_ping_whitelist_filter_deregister_callback(void *buf,
+                                             kal_uint32 filter_cnt,
+                                             kal_bool uplink)
+{
+    ipc_deregister_ul_filter(g_ul_icmpv4_echo_req_whitelist_filter_id);
+    ipc_deregister_ul_filter(g_ul_icmpv4_echo_reply_whitelist_filter_id);
+    ipc_deregister_ul_filter(g_ul_icmpv6_echo_req_whitelist_filter_id);
+    ipc_deregister_ul_filter(g_ul_icmpv6_echo_reply_whitelist_filter_id);
+    ipc_deregister_ul_filter(g_ul_icmpv6_rs_whitelist_filter_id);
+
+    ipc_deregister_ul_filter(g_ul_non_ping_filter_id);
+
+    g_ul_icmpv4_echo_req_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+    g_ul_icmpv4_echo_reply_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+    g_ul_icmpv6_echo_req_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+    g_ul_icmpv6_echo_reply_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+    g_ul_icmpv6_rs_whitelist_filter_id = PFM_INVALID_FILTER_ID;
+
+    g_ul_non_ping_filter_id = PFM_INVALID_FILTER_ID;
+	
+    hif_trace_info(PFM_TR_DEREG_ICMPV4_PING_REQ_BYPASS_FILTER, __FUNCTION__, g_ul_icmpv4_echo_req_whitelist_filter_id);
+    hif_trace_info(PFM_TR_DEREG_ICMPV4_PING_REPLY_BYPASS_FILTER, __FUNCTION__, g_ul_icmpv4_echo_reply_whitelist_filter_id);
+    hif_trace_info(PFM_TR_DEREG_ICMPV6_PING_REQ_BYPASS_FILTER, __FUNCTION__, g_ul_icmpv6_echo_req_whitelist_filter_id);
+    hif_trace_info(PFM_TR_DEREG_ICMPV6_PING_REPLY_BYPASS_FILTER, __FUNCTION__, g_ul_icmpv6_echo_reply_whitelist_filter_id);	
+    hif_trace_info(PFM_TR_DEREG_ICMPV6_RS_BYPASS_FILTER, __FUNCTION__, g_ul_icmpv6_echo_req_whitelist_filter_id);
+    hif_trace_info(PFM_TR_DEREG_NON_PING_FILTER, __FUNCTION__, g_ul_non_ping_filter_id);	
+
+    return;
+}
+
+
diff --git a/mcu/middleware/hif/ipcore/src/pfm_if.c b/mcu/middleware/hif/ipcore/src/pfm_if.c
new file mode 100644
index 0000000..9cffd05
--- /dev/null
+++ b/mcu/middleware/hif/ipcore/src/pfm_if.c
@@ -0,0 +1,847 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2014
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   pfm_if.c
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   Packet Filter Manager public interface implementation.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_api.h"
+#include "ipc_api.h"
+#include "ipc_filter.h"
+#include "intrCtrl.h"
+#include "ccci_ipc_msgid.h"
+
+#include "mw_sap.h"
+#include "ipc_debug.h"
+
+#include "pfm_struct.h"
+#include "pfm_defs.h"
+#include "pfm_enums.h"
+#include "pfm_object.h"
+
+#if defined(__HIF_PCIE_SUPPORT__)
+#include "hif_dpmaifdev.h"
+#endif 
+
+/*------------------------------------------------------------------------------
+ * Global variables.
+ *----------------------------------------------------------------------------*/
+kal_spinlockid pfm_spinlock_g = NULL;
+/*------------------------------------------------------------------------------
+ * Helper macro.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Private data structure.
+ *----------------------------------------------------------------------------*/
+typedef void (*pfm_register_parser_func_t)(void *, kal_uint32, kal_bool);
+typedef void (*pfm_deregister_callback_func_t)(void *, kal_uint32, kal_bool);
+
+/*------------------------------------------------------------------------------
+ * Private variables.
+ *----------------------------------------------------------------------------*/
+const static pfm_register_parser_func_t pfm_register_parser_func_list_s[] = {
+    #undef PFM_FILTER_SET_FEATURE_NAME
+    #undef PFM_FILTER_SET_PREFIX
+    #define PFM_FILTER_SET_FEATURE_NAME(_name)
+    #define PFM_FILTER_SET_PREFIX(_prefix) pfm_ ## _prefix ## _register_parser,
+    #include "pfm_config.h"
+
+};
+
+const static pfm_deregister_callback_func_t pfm_deregister_callback_func_list_s[] = {
+    #undef PFM_FILTER_SET_FEATURE_NAME
+    #undef PFM_FILTER_SET_PREFIX
+    #define PFM_FILTER_SET_FEATURE_NAME(_name)
+    #define PFM_FILTER_SET_PREFIX(_prefix) pfm_ ## _prefix ## _deregister_callback,
+    #include "pfm_config.h"
+
+};
+
+static pfm_internal_filter_set_t pfm_ul_filter_set_list_s[NUM_OF_PFM_FILTER_SET_ID];
+static pfm_internal_filter_set_t pfm_dl_filter_set_list_s[NUM_OF_PFM_FILTER_SET_ID];
+pfm_internal_filter_set_t *pfm_fsl_set_s[] = {pfm_dl_filter_set_list_s, pfm_ul_filter_set_list_s};
+
+/*------------------------------------------------------------------------------
+ * Private fucntions.
+ *----------------------------------------------------------------------------*/
+pfm_internal_filter_set_t *
+pfm_get_filter_set_by_id(
+    pfm_internal_filter_set_t  *filter_set_list,
+    kal_uint32                  list_size,
+    kal_uint32                  filter_set_id)
+{
+    pfm_internal_filter_set_t    *filter_set;
+
+    if ( (NULL == filter_set_list) ||
+         (filter_set_id >= list_size) ) {
+        hif_trace_error(PFM_TR_GET_FILTER_SET_INVALID_PARAMS, filter_set_list, list_size, filter_set_id);
+        return NULL;
+    }
+
+    filter_set = &filter_set_list[filter_set_id];
+
+    if (!PFM_IS_VALID_OBJECT(filter_set)) {
+        hif_trace_info(PFM_TR_GET_FILTER_SET_NEW_FILTER_SET, filter_set_list, filter_set_id, filter_set);
+        PFM_INIT_OBJECT_BEGIN(filter_set, pfm_spinlock_g);
+
+        filter_set->filter_set_id = filter_set_id;
+        filter_set->filter_cnt = 0;
+        kal_mem_set(filter_set->filters, -1, sizeof(filter_set->filters));
+
+        PFM_INIT_OBJECT_END(filter_set, pfm_spinlock_g);
+        return filter_set;
+    }
+    return filter_set;
+}
+
+void pfm_delete_filter_set(
+    pfm_internal_filter_set_t   *filter_set)
+{
+    hif_trace_info(PFM_TR_DEL_FILTER_SET_BEGIN, filter_set);
+    PFM_DEINIT_OBJECT_BEGIN(filter_set, pfm_spinlock_g);
+    if (filter_set) {
+        PFM_DEINIT_OBJECT_END(filter_set, pfm_spinlock_g);
+    } else {
+        PFM_ASSERT(KAL_FALSE);
+    }
+}
+
+void pfm_dispatch_cmd(ilm_struct *ilm, kal_bool is_register)
+{
+    pfm_filter_set_t    *fs;
+    kal_uint8           *filters_buf;
+    kal_bool            uplink;
+    local_para_struct   *local_para_ptr = ilm->local_para_ptr; /* local_para pointer */
+    peer_buff_struct    *peer_buff_ptr = ilm->peer_buff_ptr;  /* peer_buff pointer */
+    kal_uint16          peer_buf_len;
+
+    if (!local_para_ptr) {
+        if(is_register){
+            hif_trace_error(PFM_TR_DISPATCH_REGISTER_CMD_NULL_PARAMS);
+        }else{
+            hif_trace_error(PFM_TR_DEREG_FILTERS_NULL_PARAMS);
+        }
+        return;
+    }
+
+    fs = (pfm_filter_set_t *)local_para_ptr;
+
+    /* Register parameter check */
+    if(is_register) {
+        if ( (fs->filter_set_id >= NUM_OF_PFM_FILTER_SET_ID) ||
+             (fs->filter_cnt == 0) ||
+             ((fs->filter_cnt > 0) && (NULL == peer_buff_ptr))) {
+            hif_trace_error(PFM_TR_DISPATCH_REGISTER_CMD_INVALID_PARAMS, peer_buff_ptr, fs->filter_set_id, fs->filter_cnt);
+            return;
+        }
+    } else {
+        /* De-register parameter check */
+        if ( (fs->filter_set_id >= NUM_OF_PFM_FILTER_SET_ID) ||
+             (fs->filter_cnt == 0) ||
+             ((fs->filter_cnt > 0) && (NULL == peer_buff_ptr))) {
+            hif_trace_error(PFM_TR_DEREG_FILTERS_INVALID_PARAMS, peer_buff_ptr, fs->filter_set_id, fs->filter_cnt);
+            PFM_ASSERT(KAL_FALSE);
+            return;
+        }
+    }
+
+    if (NULL != peer_buff_ptr) {
+        filters_buf = (kal_uint8 *)get_peer_buff_pdu(peer_buff_ptr, &peer_buf_len);
+    } else {
+        filters_buf = NULL;
+    }
+    uplink = (fs->uplink == 1)? KAL_TRUE:KAL_FALSE;
+
+    if(is_register) {
+        hif_trace_info(PFM_TR_DISPATCH_REGISTER_CMD_BEGIN, fs->filter_set_id, fs->filter_cnt);
+        /* Dispatch to pfm_xxx_register_parser() */
+        pfm_register_parser_func_list_s[fs->filter_set_id](filters_buf, fs->filter_cnt, uplink);
+    } else {
+        hif_trace_info(PFM_TR_DEREG_FILTERS_INFO, fs->uplink, fs->filter_set_id, fs->filter_cnt);
+        /* De-register command dispatch */
+        pfm_deregister_callback_func_list_s[fs->filter_set_id](filters_buf, fs->filter_cnt, uplink);
+    }
+}
+
+void pfm_deregister_filter(
+    kal_bool                        uplink,
+    pfm_internal_filter_set_t      *filter_set,
+    kal_int32                       filter_id)
+{
+    kal_int32           ipc_filter_id;
+
+    if ( !filter_set || (filter_id < 0) || (filter_id >= PFM_FILTER_SET_MAX_SIZE)|| (filter_set->filter_cnt == 0) ) {
+        hif_trace_error(PFM_TR_DEREG_FILTER_WITH_INVALID_PARAMS, uplink, filter_set, filter_id);
+        PFM_ASSERT(KAL_FALSE);
+        return;
+    }
+
+    ipc_filter_id = filter_set->filters[filter_id];
+    hif_trace_info(PFM_TR_DEREG_FILTER_BEGIN, uplink, filter_set, filter_id, ipc_filter_id);
+    if (-1 != ipc_filter_id) {
+        if (uplink) {
+            ipc_deregister_ul_filter(ipc_filter_id);
+        } else {
+            ipc_deregister_dl_filter(ipc_filter_id);
+        }
+        filter_set->filters[filter_id] = -1;
+        filter_set->filter_cnt--;
+    } else {
+        PFM_ASSERT(KAL_FALSE);
+    }
+}
+
+void pfm_deregister_filters(local_para_struct *local_para_ptr)
+{
+    pfm_filter_set_t   *fs;
+    kal_int32          *filters_buf;
+
+    pfm_internal_filter_set_t  *filter_set;
+    kal_int32                   idx;
+
+    if (!local_para_ptr) {
+        hif_trace_error(PFM_TR_DEREG_FILTERS_NULL_PARAMS);
+        return;
+    }
+
+    fs = (pfm_filter_set_t *)local_para_ptr;
+    filters_buf = (kal_int32 *)(fs + 1);
+
+    if ( (fs->filter_set_id >= NUM_OF_PFM_FILTER_SET_ID) ||
+         (fs->filter_cnt == 0) ) {
+        hif_trace_error(PFM_TR_DEREG_FILTERS_INVALID_PARAMS, local_para_ptr, fs->filter_set_id, fs->filter_cnt);
+        PFM_ASSERT(KAL_FALSE);
+        return;
+    }
+    
+    filter_set = pfm_get_filter_set_by_id(pfm_fsl_set_s[fs->uplink], NUM_OF_PFM_FILTER_SET_ID, fs->filter_set_id);
+    if (filter_set) {
+        hif_trace_info(PFM_TR_DEREG_FILTERS_INFO, fs->uplink, fs->filter_set_id, fs->filter_cnt);
+        if (-1 == fs->filter_cnt) {
+            /* Deregister all filters. */
+            for (idx = 0; idx < PFM_FILTER_SET_MAX_SIZE; idx++) {
+                if (-1 != filter_set->filters[idx]) {
+                    pfm_deregister_filter((fs->uplink == 1)?KAL_TRUE:KAL_FALSE, filter_set, idx);
+                    pfm_deregister_callback_func_list_s[fs->filter_set_id](filters_buf, fs->filter_cnt, fs->uplink);
+                    if (0 == filter_set->filter_cnt) {
+                        pfm_delete_filter_set(filter_set);
+                        break;
+                    }
+                }
+            }
+        } else {
+            /* Deregister the specified filters. */
+            if (fs->filter_cnt <= filter_set->filter_cnt) {
+                for (idx = 0; idx < fs->filter_cnt; idx++) {
+                    pfm_deregister_filter((fs->uplink == 1)?KAL_TRUE:KAL_FALSE, filter_set, filters_buf[idx]);
+                    pfm_deregister_callback_func_list_s[fs->filter_set_id](filters_buf, fs->filter_cnt, fs->uplink);
+                    if (0 == filter_set->filter_cnt) {
+                        PFM_ASSERT(idx == (fs->filter_cnt - 1));
+                        pfm_delete_filter_set(filter_set);
+                    }
+                }
+            } else {
+                PFM_ASSERT(KAL_FALSE);
+            }
+        }
+    } else {
+        hif_trace_error(PFM_TR_DEREG_FILTERS_FILTER_SET_NOT_FOUND, fs->uplink, fs->filter_set_id);
+    }
+}
+
+kal_bool pfm_register_filter(kal_uint32 filter_set_id,
+                             kal_int32 filter_id,
+                             kal_bool uplink,
+                             kal_bool callback,
+                             kal_bool with_info,
+                             ipc_filter_rules_t *rules,
+                             void *callback_func,
+                             void *callback_context,
+                             module_type callback_module)
+{
+    pfm_internal_filter_set_t  *filter_set = NULL;
+    kal_int32                   ret = 0;
+    kal_uint8                   idx = (KAL_TRUE == uplink) ? 1 : 0;
+
+    if ( (filter_set_id < 0) || (filter_set_id >= NUM_OF_PFM_FILTER_SET_ID) ||
+         (filter_id < 0) || (filter_id >= PFM_FILTER_SET_MAX_SIZE) ||
+         (!rules) ) {
+        hif_trace_error(PFM_TR_REG_FILTER_INVALID_PARAMS, filter_set_id, filter_id, rules);
+        PFM_ASSERT(KAL_FALSE);
+        return KAL_FALSE;
+    }
+
+    filter_set = pfm_get_filter_set_by_id(pfm_fsl_set_s[idx], NUM_OF_PFM_FILTER_SET_ID, filter_set_id);
+    if (filter_set) {
+        /* Deregister the filter if the filter_id has been used. */
+        if (-1 != filter_set->filters[filter_id]) {
+            pfm_deregister_filter(uplink, filter_set, filter_id);
+        }
+
+        if (KAL_FALSE == uplink) {
+            rules->features |= IPC_FILTER_FEATURE_PFM_DL;
+        }
+
+        /* Call corresponding register API */
+        if (uplink) {
+            if (callback) {
+                if (with_info) {
+                    ret = ipc_register_ul_filter_with_info_cbk(rules, callback_func, callback_context);
+                } else {
+                    ret = ipc_register_ul_filter_cbk(rules, callback_func, callback_context);
+                }
+            } else {
+                if (with_info) {
+                    ret = ipc_register_ul_filter_with_info_msg(rules, callback_module, callback_context);
+                } else {
+                    ret = ipc_register_ul_filter_msg(rules, callback_module, callback_context);
+                }
+            }
+        } else {
+            if (callback) {
+                if (with_info) {
+                    ret = ipc_register_dl_filter_with_info_cbk(rules, callback_func, callback_context);
+                } else {
+                    ret = ipc_register_dl_filter_cbk(rules, callback_func, callback_context);
+                }
+            } else {
+                if (with_info) {
+                    ret = ipc_register_dl_filter_with_info_msg(rules, callback_module, callback_context);
+                } else {
+                    ret = ipc_register_dl_filter_msg(rules, callback_module, callback_context);
+                }
+            }
+        }
+
+        /* Check if registering is succeeded or not. */
+        if (PFM_IPC_REGISTER_FILTER_FAIL != ret) {
+            filter_set->filters[filter_id] = ret;
+            filter_set->filter_cnt++;
+        } else {
+            hif_trace_error(PFM_TR_REG_FILTER_FAILED);
+            return KAL_FALSE;
+        }
+    } else {
+        hif_trace_error(PFM_TR_REG_FILTER_FILTER_SET_NOT_FOUND, uplink, filter_set_id);
+        return KAL_FALSE;
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool pfm_register_filter_cbk(
+    kal_uint32              filter_set_id,
+    kal_int32               filter_id,
+    kal_bool                uplink,
+    ipc_filter_rules_t     *rules,
+    ipc_filter_callback_t   callback_func,
+    void                   *callback_context)
+{
+    hif_trace_info(PFM_TR_REG_FILTER_CBK_BEGIN, filter_set_id, filter_id, uplink, rules, callback_func, callback_context);
+    return pfm_register_filter(filter_set_id, filter_id, uplink, KAL_TRUE, KAL_FALSE, rules, callback_func, callback_context, MOD_NIL);
+}
+
+kal_bool pfm_register_filter_msg(
+    kal_uint32              filter_set_id,
+    kal_int32               filter_id,
+    kal_bool                uplink,
+    ipc_filter_rules_t     *rules,
+    module_type             callback_module,
+    void                   *callback_context)
+{
+    hif_trace_info(PFM_TR_REG_FILTER_MSG_BEGIN, filter_set_id, filter_id, uplink, rules, callback_module, callback_context);
+    return pfm_register_filter(filter_set_id, filter_id, uplink, KAL_FALSE, KAL_FALSE, rules, NULL, callback_context, callback_module);
+}
+
+kal_bool pfm_register_filter_with_info_cbk(
+    kal_uint32                        filter_set_id,
+    kal_int32                         filter_id,
+    kal_bool                          uplink,
+    ipc_filter_rules_t               *rules,
+    ipc_filter_with_info_callback_t   callback_func,
+    void                             *callback_context)
+{
+    hif_trace_info(PFM_TR_REG_FILTER_WITH_INFO_CBK_BEGIN, filter_set_id, filter_id, uplink, rules, callback_func, callback_context);
+    return pfm_register_filter(filter_set_id, filter_id, uplink, KAL_TRUE, KAL_TRUE, rules, callback_func, callback_context, MOD_NIL);
+}
+
+kal_bool pfm_register_filter_with_info_msg(
+    kal_uint32              filter_set_id,
+    kal_int32               filter_id,
+    kal_bool                uplink,
+    ipc_filter_rules_t     *rules,
+    module_type             callback_module,
+    void                   *callback_context)
+{
+    hif_trace_info(PFM_TR_REG_FILTER_WITH_INFO_MSG_BEGIN, filter_set_id, filter_id, uplink, rules, callback_module, callback_context);
+    return pfm_register_filter(filter_set_id, filter_id, uplink, KAL_FALSE, KAL_TRUE, rules, NULL, callback_context, callback_module);
+}
+
+void pfm_matched_packet_trace(kal_int16 ebi, kal_uint8 *p_data, kal_uint32 bytes){
+    kal_uint32   i = 0;
+    kal_uint32  *p_dump = (kal_uint32 *)((int)p_data & (~0x3)); //4-bytes alignment
+
+    hif_data_trace(MD_TRC_PFM_GE_MATCHED_PACKET_INFO, ebi, (p_data[4]<<8|p_data[5]), (p_data[10]<<8|p_data[11]));
+    for (i = 0; i*4 < bytes; i = i+4 ){
+        hif_data_trace(MD_TRC_PFM_GE_MATCHED_PACKET_DUMP, i*4, p_dump[i], p_dump[i+1], p_dump[i+2], p_dump[i+3]);
+    }
+}
+
+void pfm_spinlock_init()
+{
+    PFM_ASSERT(!pfm_spinlock_g);
+    pfm_spinlock_g = kal_create_spinlock(PFM_LOCK_NAME);
+}
+
+static kal_bool pfm_ap_fin_ack_reduction_handler(void)
+{
+    pfm_filter_set_t *p_filter_set = NULL;
+
+    p_filter_set = (pfm_filter_set_t *)construct_local_para(sizeof(pfm_filter_set_t), TD_RESET);
+    if (NULL == p_filter_set) {
+        hif_trace_error(PFM_TR_FIN_ACK_FILTER_ALLOCATE_FAILED);
+        return KAL_FALSE;
+    }
+
+    p_filter_set->filter_set_id = PFM_FIN_ACK_FILTER_SET_ID;
+    p_filter_set->filter_cnt = -1;   // No filter info in peer buf
+    p_filter_set->uplink = KAL_FALSE;
+
+    if (KAL_FALSE == msg_send6(kal_get_active_module_id(), MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_REGISTER_FILTER_REQ, (local_para_struct *)p_filter_set, NULL)) {
+        hif_trace_error(PFM_TR_FIN_ACK_FILTER_SEND_ILM_FAILED);\
+        return KAL_FALSE;
+    }
+
+    hif_trace_info(PFM_TR_FIN_ACK_FILTER_FIN_ACK_FILTER_REQ, p_filter_set->filter_set_id);
+    return KAL_TRUE;
+}
+
+static void pfm_ap_suspend_handler(kal_uint32 bm_cmd)
+{
+    hif_trace_info(PFM_TR_FIN_ACK_FILTER_RECEIVED_AP_SUSPEND_CMD, bm_cmd);
+
+    if (bm_cmd == PFM_AP_CMD_NONE) {
+        /* no additional action */
+        return;
+    }
+
+    if (bm_cmd & PFM_AP_CMD_FIN_ACK_REDUCTION) {
+        if (KAL_FALSE == pfm_ap_fin_ack_reduction_handler()) {
+            /* pfm_ap_fin_ack_reduction_handler failed */
+            return;
+        }
+    }
+
+    return;
+}
+
+static void pfm_ap_wakeup_handler()
+{
+    pfm_deregister_callback_func_list_s[PFM_FIN_ACK_FILTER_SET_ID](NULL, 0, 0);
+    return;
+}
+
+static void pfm_ap_status_parser(local_para_struct *p_local_param)
+{
+    pfmApStatusInd *p_ap_status = (pfmApStatusInd *)p_local_param;
+
+    ASSERT(NULL != p_ap_status);
+
+    hif_trace_info(PFM_TR_FIN_ACK_FILTER_RECEIVED_AP_STATUS,
+                   (p_ap_status->em_ap_status == PFM_AP_STATUS_SUSPEND) ? "suspend":"resume");
+    switch(p_ap_status->em_ap_status) {
+        case PFM_AP_STATUS_SUSPEND :
+            pfm_ap_suspend_handler(p_ap_status->bm_cmd);
+            break;
+        case PFM_AP_STATUS_WAKE_UP :
+            pfm_ap_wakeup_handler();
+            break;
+        default :
+            /* unsupported status */
+            hif_trace_error(PFM_TR_FIN_ACK_FILTER_RECEIVED_AP_INVALID_STATUS);
+            break;
+    }
+
+    return;
+}
+
+static void pfm_udp_igmp_reg_filter_handler(local_para_struct *p_local_param)
+{
+    pfm_filter_set_t *p_filter_set = NULL;
+
+    p_filter_set = (pfm_filter_set_t *)construct_local_para(sizeof(pfm_filter_set_t), TD_RESET);
+    if (NULL == p_filter_set) {
+        hif_trace_error(PFM_TR_FIN_ACK_FILTER_ALLOCATE_FAILED);
+        return;
+    }
+
+    p_filter_set->filter_set_id = PFM_UDP_IGMP_FILTER_SET_ID;
+    p_filter_set->filter_cnt = -1; // No filter info in peer buf
+    p_filter_set->uplink = KAL_TRUE;
+
+    if (KAL_FALSE == msg_send6(kal_get_active_module_id(), MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_REGISTER_FILTER_REQ, (local_para_struct *)p_filter_set, NULL)) {
+        hif_trace_error(PFM_TR_FIN_ACK_FILTER_SEND_ILM_FAILED);
+        return;
+    }
+
+    return;
+}
+
+static void pfm_udp_igmp_dereg_filter_handler(local_para_struct *p_local_param)
+{
+    pfm_deregister_callback_func_list_s[PFM_UDP_IGMP_FILTER_SET_ID](NULL, 0, 0);
+    return;
+}
+
+static void pfm_icmp_ping_reg_filter_handler(local_para_struct *p_local_param)
+{
+    pfm_filter_set_t *p_filter_set = NULL;
+
+    p_filter_set = (pfm_filter_set_t *)construct_local_para(sizeof(pfm_filter_set_t), TD_RESET);
+    if (NULL == p_filter_set) {
+        hif_trace_error(PFM_TR_ICMP_PING_FILTER_ALLOCATE_FAILED, __FUNCTION__);
+        return;
+    }
+
+    p_filter_set->filter_set_id = PFM_ICMP_PING_FILTER_SET_ID;
+    p_filter_set->filter_cnt = -1; // No filter info in peer buf
+    p_filter_set->uplink = KAL_FALSE;
+
+    if (KAL_FALSE == msg_send6(kal_get_active_module_id(), MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_REGISTER_FILTER_REQ, (local_para_struct *)p_filter_set, NULL)) {
+        hif_trace_error(PFM_TR_ICMP_PING_FILTER_SEND_ILM_FAILED, __FUNCTION__);
+        return;
+    }
+
+    return;
+}
+
+static void pfm_icmp_ping_dereg_filter_handler(local_para_struct *p_local_param)
+{
+    pfm_deregister_callback_func_list_s[PFM_ICMP_PING_FILTER_SET_ID](NULL, 0, 0);
+    return;
+}
+
+static void pfm_ul_disable_all_packets_reg_filter_handler(local_para_struct *p_local_param)
+{
+    pfm_filter_set_t *p_filter_set = NULL;
+
+    p_filter_set = (pfm_filter_set_t *)construct_local_para(sizeof(pfm_filter_set_t), TD_RESET);
+    if (NULL == p_filter_set) {
+        hif_trace_error(PFM_TR_UL_DISABLE_ALL_PACKETS_FILTER_ALLOCATE_FAILED, __FUNCTION__);
+        return;
+    }
+
+    p_filter_set->filter_set_id = PFM_UL_DISABLE_ALL_PACKETS_FILTER_SET_ID;
+    p_filter_set->filter_cnt = -1; // No filter info in peer buf
+    p_filter_set->uplink = KAL_TRUE;
+
+    if (KAL_FALSE == msg_send6(kal_get_active_module_id(), MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_REGISTER_FILTER_REQ, (local_para_struct *)p_filter_set, NULL)) {
+        hif_trace_error(PFM_UL_DISABLE_ALL_PACKETS_FILTER_SEND_ILM_FAILED, __FUNCTION__);
+        return;
+    }
+
+    return;
+}
+
+static void pfm_ul_disable_all_packets_dereg_filter_handler(local_para_struct *p_local_param)
+{
+    pfm_deregister_callback_func_list_s[PFM_UL_DISABLE_ALL_PACKETS_FILTER_SET_ID](NULL, 0, 0);
+    return;
+}
+
+static void pfm_ul_icmp_ping_whitelist_reg_filter_handler(local_para_struct *p_local_param)
+{
+    pfm_filter_set_t *p_filter_set = NULL;
+
+    p_filter_set = (pfm_filter_set_t *)construct_local_para(sizeof(pfm_filter_set_t), TD_RESET);
+    if (NULL == p_filter_set) {
+        hif_trace_error(PFM_TR_UL_ICMP_PING_WHITELIST_FILTER_ALLOCATE_FAILED, __FUNCTION__);
+        return;
+    }
+
+    p_filter_set->filter_set_id = PFM_UL_ICMP_PING_WHITELIST_FILTER_SET_ID;
+    p_filter_set->filter_cnt = -1; // No filter info in peer buf
+    p_filter_set->uplink = KAL_TRUE;
+
+    if (KAL_FALSE == msg_send6(kal_get_active_module_id(), MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_REGISTER_FILTER_REQ, (local_para_struct *)p_filter_set, NULL)) {
+        hif_trace_error(PFM_UL_ICMP_PING_WHITELIST_FILTER_SEND_ILM_FAILED, __FUNCTION__);
+        return;
+    }
+
+    return;
+}
+
+static void pfm_ul_icmp_ping_whitelist_dereg_filter_handler(local_para_struct *p_local_param)
+{
+    pfm_deregister_callback_func_list_s[PFM_UL_ICMP_PING_WHITELIST_FILTER_SET_ID](NULL, 0, 0);
+    return;
+}
+
+
+#if defined(__HIF_DPMAIF_PCIE_SUPPORT__)
+int pfm_pcie_hifdpmaif_callback(void *param, void *user_param)
+{
+    pfm_pcie_state_change_ind_struct *ind_p;
+    ind_p = (pfm_pcie_state_change_ind_struct *)construct_local_para(sizeof(pfm_pcie_state_change_ind_struct), TD_RESET);
+    ind_p->is_suspend = (kal_uint32)user_param;
+    msg_send5(kal_get_active_module_id(), MOD_IPCORE, IPCORE_SAP, MSG_ID_PFM_PCIE_STATE_CHANGE_IND, (local_para_struct*) ind_p);
+    
+    return 0;
+}
+
+static void pfm_pcie_state_change_hdlr(local_para_struct *p_local_param)
+{
+    pfm_pcie_state_change_ind_struct *p_suspend_ind;
+    p_suspend_ind = (pfm_pcie_state_change_ind_struct *)p_local_param;
+
+    if (p_suspend_ind->is_suspend == PFM_STATE_SUSPEND) {
+        ipc_filter_switch_dl_mode(IPC_SW_DL_MODE_PCI);
+        hifdpmaif_suspend_user_ack(DPMAIF_PCIE_NPU_IPCORE);
+    } else {
+        ipc_filter_switch_dl_mode(IPC_HW_DL_MODE_PCI);
+        hifdpmaif_resume_user_ack(DPMAIF_PCIE_NPU_IPCORE);
+    }
+}
+
+#endif 
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+void pfm_on_ilm(ilm_struct *ilm)
+{
+    ASSERT(NULL != ilm);
+
+    switch (ilm->msg_id) {
+        case MSG_ID_PFM_REGISTER_FILTER_REQ:
+            pfm_dispatch_cmd(ilm, KAL_TRUE);
+            break;
+        case MSG_ID_PFM_DEREGISTER_FILTER_REQ:
+            pfm_dispatch_cmd(ilm, KAL_FALSE);
+            break;
+        case MSG_ID_AP_STATUS_IND:
+            pfm_ap_status_parser(ilm->local_para_ptr);
+            break;
+        case MSG_ID_IPCORE_UDP_IGMP_REG_FILTER_REQ:
+            pfm_udp_igmp_reg_filter_handler(ilm->local_para_ptr);
+            break;
+        case MSG_ID_IPCORE_UDP_IGMP_DEREG_FILTER_REQ:
+            pfm_udp_igmp_dereg_filter_handler(ilm->local_para_ptr);
+            break;
+        case MSG_ID_PFM_ICMP_PING_REG_FILTER_REQ:
+            pfm_icmp_ping_reg_filter_handler(ilm->local_para_ptr);
+            break;
+        case MSG_ID_PFM_ICMP_PING_DEREG_FILTER_REQ:
+            pfm_icmp_ping_dereg_filter_handler(ilm->local_para_ptr);
+            break;
+        case MSG_ID_PFM_UL_DISABLE_ALL_PACKETS_REG_FILTER_REQ:
+            pfm_ul_disable_all_packets_reg_filter_handler(ilm->local_para_ptr);
+            break;
+        case MSG_ID_PFM_UL_DISABLE_ALL_PACKETS_DEREG_FILTER_REQ:
+            pfm_ul_disable_all_packets_dereg_filter_handler(ilm->local_para_ptr);
+            break;
+        case MSG_ID_PFM_UL_ICMP_PING_WHITELIST_REG_FILTER_REQ:
+            pfm_ul_icmp_ping_whitelist_reg_filter_handler(ilm->local_para_ptr);
+            break;
+        case MSG_ID_PFM_UL_ICMP_PING_WHITELIST_DEREG_FILTER_REQ:
+            pfm_ul_icmp_ping_whitelist_dereg_filter_handler(ilm->local_para_ptr);
+            break;
+    #if defined(__HIF_DPMAIF_PCIE_SUPPORT__)
+        case MSG_ID_PFM_PCIE_STATE_CHANGE_IND:
+            pfm_pcie_state_change_hdlr(ilm->local_para_ptr);
+            break;
+    #endif 
+        default:
+            break;
+    }
+}
+
+kal_bool pfm_init(void)
+{
+    kal_uint32 i = 0;
+
+    /* Init the static structure */
+    kal_mem_set(pfm_ul_filter_set_list_s, 0, sizeof(pfm_ul_filter_set_list_s));
+    kal_mem_set(pfm_dl_filter_set_list_s, 0, sizeof(pfm_dl_filter_set_list_s));
+
+    for (i = 0; i < NUM_OF_PFM_FILTER_SET_ID; i++) {
+        kal_mem_set(pfm_ul_filter_set_list_s[i].filters, -1, sizeof(kal_int32) * PFM_FILTER_SET_MAX_SIZE);
+        kal_mem_set(pfm_dl_filter_set_list_s[i].filters, -1, sizeof(kal_int32) * PFM_FILTER_SET_MAX_SIZE);
+    }
+
+    pfm_spinlock_init();
+#if defined(__HIF_DPMAIF_PCIE_SUPPORT__)
+    hifdpmaif_register_suspend_non_post_callback(
+        DPMAIF_PCIE_NPU_IPCORE,
+        pfm_pcie_hifdpmaif_callback,
+        (void*)PFM_STATE_SUSPEND);
+    hifdpmaif_register_resume_non_post_callback(
+        DPMAIF_PCIE_NPU_IPCORE,
+        pfm_pcie_hifdpmaif_callback,
+        (void*)PFM_STATE_RESUME);
+#endif 
+
+    return KAL_TRUE;
+}
+
+kal_bool pfm_reset(void)
+{
+    kal_uint32 i = 0;
+
+    /* Init the static structure */
+    kal_mem_set(pfm_ul_filter_set_list_s, 0, sizeof(pfm_ul_filter_set_list_s));
+    kal_mem_set(pfm_dl_filter_set_list_s, 0, sizeof(pfm_dl_filter_set_list_s));
+
+    for (i = 0; i < NUM_OF_PFM_FILTER_SET_ID; i++) {
+        kal_mem_set(pfm_ul_filter_set_list_s[i].filters, -1, sizeof(kal_int32) * PFM_FILTER_SET_MAX_SIZE);
+        kal_mem_set(pfm_dl_filter_set_list_s[i].filters, -1, sizeof(kal_int32) * PFM_FILTER_SET_MAX_SIZE);
+    }
+
+    return KAL_TRUE;
+}
+
+pfm_internal_filter_set_t* pfm_get_filter_set_list(kal_bool is_uplink)
+{
+    return (is_uplink)?pfm_fsl_set_s[1]:pfm_fsl_set_s[0];
+}
diff --git a/mcu/middleware/hif/uartcore/src/uartcore_task.c b/mcu/middleware/hif/uartcore/src/uartcore_task.c
new file mode 100644
index 0000000..92e4335
--- /dev/null
+++ b/mcu/middleware/hif/uartcore/src/uartcore_task.c
@@ -0,0 +1,171 @@
+/*!
+ *  @file uartcore_task.c
+ *  @author Ansel Liao <ansel.liao@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main functions of uartcore
+ */
+
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "hmu.h"
+#include "hmu_conf_data.h"
+
+typedef enum{
+	UART_EN_Q = 0,
+	UART_DE_Q = 1,
+	UART_EN_Q_LIGHT = 2,
+	UART_DE_Q_ALL = 3,
+} drv_uart_en_q_or_de_q;
+
+extern void *uart_tgpd_head[3];
+extern void *uart_rgpd_head[3];
+extern void *uart_tgpd_tail[3];
+extern void *uart_rgpd_tail[3];
+extern kal_uint32 uart_open_event;
+extern void uart_en_q_de_q_with_mutex(UART_PORT port, kal_bool tx_or_rx, kal_bool en_q_or_de_q, void *p_ior_head, void *p_ior_tail);
+extern void dbg_print(kal_char *fmt, ...);
+
+static void uart_core_task_main(task_entry_struct* task_entry_ptr)
+{
+	ilm_struct current_ilm;
+	kal_uint32 rt_event, uart_event=0;
+	kal_uint32 count = 0;
+
+	kal_set_active_module_id(MOD_UARTCORE);
+	kal_mem_set(&current_ilm, 0, sizeof(ilm_struct));
+
+	while(1)
+	{
+		//dbg_print("=========>uartcore_task_main\r\n");
+
+		// msg_receive_extq will block, therefore we poll if any message exist first
+		while(msg_get_extq_messages() > 0)
+		{
+			if(msg_receive_extq(&current_ilm) != KAL_TRUE)
+			{
+				break;
+			}
+
+			switch (current_ilm.msg_id)
+			{
+				default:
+					break;
+			}
+
+			destroy_ilm(&current_ilm);
+		}
+			// wait some open uart port first time;
+		if(uart_open_event <= 0){
+			uart_event = hmu_hifeg_wait(HIF_DRV_EG_UART_IND_EVENT);
+		}
+		if((HIF_DRV_EG_UART_IND_EVENT & uart_event) || uart_open_event>0){
+		// Wait someone notify HMU to wake up HIF.
+		rt_event = hmu_hifeg_wait(HIF_DRV_EG_HIF_TICK_EVENT_UART);
+		if((HIF_DRV_EG_HIF_TICK_EVENT_UART & rt_event))
+		{
+			count++;
+			if(0 == (count % 1) )
+			{
+				if(uart_tgpd_head[uart_port1] != uart_tgpd_tail[uart_port1])
+					uart_en_q_de_q_with_mutex(uart_port1, UART_TX, UART_DE_Q, NULL, NULL);
+			
+				if(uart_rgpd_head[uart_port1] != uart_rgpd_tail[uart_port1])
+					uart_en_q_de_q_with_mutex(uart_port1, UART_RX, UART_DE_Q, NULL, NULL);
+#if defined(__FLAVOR_MULTI_MODE_ROUTER__) || defined(__FLAVOR_SINGLE_MODE_ROUTER__)
+	//in Router product. SUART0 is AP  own, so it should not be init here.
+#else
+				if(uart_tgpd_head[uart_port2] != uart_tgpd_tail[uart_port2])
+					uart_en_q_de_q_with_mutex(uart_port2, UART_TX, UART_DE_Q, NULL, NULL);
+			
+				if(uart_rgpd_head[uart_port2] != uart_rgpd_tail[uart_port2])
+					uart_en_q_de_q_with_mutex(uart_port2, UART_RX, UART_DE_Q, NULL, NULL);
+#endif
+			}
+		}
+	}
+}
+}
+
+
+static kal_bool uart_core_task_init(void)
+{
+	dbg_print("=========>uartcore_task_init\r\n");
+
+	return KAL_TRUE;
+}
+
+
+static kal_bool uart_core_task_reset(void)
+{
+	dbg_print("=========>uartcore_task_reset\r\n");
+
+	// Do task's reset here.
+	// Notice that: shouldn't execute modules reset handler since
+	// stack_task_reset() will do.
+	return KAL_TRUE;
+}
+
+
+static kal_bool uart_core_task_end(void)
+{
+	dbg_print("=========>uartcore_task_end\r\n");
+
+	// Do task's termination here.
+	// Notice that: shouldn't execute modules reset handler since
+	// stack_task_end() will do.
+	return KAL_TRUE;
+}
+
+
+kal_bool uart_core_create(comptask_handler_struct **handle)
+{
+	static const comptask_handler_struct uart_core_handler_info =
+	{
+		uart_core_task_main,		/* task entry function */
+		uart_core_task_init,		/* task initialization function */
+//		NULL,				/* task configuration function */
+		uart_core_task_reset,		/* task reset handler */
+//		uart_core_task_end		/* task termination handler */
+	};
+	
+    uart_open_event = 0;
+	dbg_print("=========>uartcore_create\r\n");
+
+	*handle = (comptask_handler_struct *) &uart_core_handler_info;
+
+	return KAL_TRUE;
+}
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_bm.h b/mcu/middleware/hif/usbclass/msd/include/ms_bm.h
new file mode 100644
index 0000000..d05c711
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_bm.h
@@ -0,0 +1,148 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ms_bm.h
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   MS buffer management header file.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_MS_BM_H
+#define __INC_MS_BM_H
+
+/*------------------------------------------------------------------------------
+ * Configuration.
+ *----------------------------------------------------------------------------*/
+#define QBM_NUM_MSD                     300 /* Number of MSD GPD */
+
+/*------------------------------------------------------------------------------
+ * Constant definition.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Global variables. 
+ *----------------------------------------------------------------------------*/
+extern kal_int32 free_gpd_cnt;
+extern kal_bool bm_need_init;
+
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+
+kal_uint32 ms_bm_get_gpd_list_cnt(qbm_gpd *head, qbm_gpd *tail);
+
+
+/* 
+ * ===  FUNCTION  =====================================================
+*     Name:  		ms_bm_init
+*     Description:  	Before use ms bm to allocate/free gpd queue, should init it first.
+*     Return:   		Success: KAL_TRUE.
+*				Failed: 	KAL_FALSE
+* =================================================================
+*/
+kal_bool ms_bm_init(void);
+
+/* 
+ * ===  FUNCTION  =====================================================
+*     Name:  		ms_bm_de_init
+*     Description:  	Dummy function just check gpds is all free or not, when bm_de_init require all gpds free  
+*     Return:   		Success: KAL_TRUE
+*				Failed: 	KAL_FALSE
+* =================================================================
+*/
+kal_bool ms_bm_de_init(void);
+
+/*! 
+* ===  FUNCTION  =====================================================
+*     Name:  		 ms_bm_alloc_gpd
+*	Description:     allcate the gpd queue 
+*	@param cnt:   [IN] the request of allocate gpd number, if the cnt more than free gpds just allocate all free count
+*     @param head: [IN] Pointer to the gpd list head which you allocated      
+*     @param tail:    [IN] Pointer to the gpd list tail which you allocated
+*     Return:   		 Success: The allocate GPD number
+*				 Failed:	0 
+* =================================================================
+*/
+kal_int32 ms_bm_alloc(kal_int32 cnt , qbm_gpd **head,  qbm_gpd **tail);
+
+/*! 
+* ===  FUNCTION  =====================================================
+*     Name:  		 ms_bm_free_gpd
+*	Description:     free the whole queue from head to tail.
+*     @param head: [IN] Pointer to the gpd list head which you want to free         
+*     @param tail:    [IN] Pointer to the gpd list tail which you want to free
+*     Return:   		 Success: The freed GPD number
+*				 Failed:	0 
+* =================================================================
+*/
+kal_int32 ms_bm_free(qbm_gpd *head,  qbm_gpd *tail);
+
+
+#endif
+
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_core.h b/mcu/middleware/hif/usbclass/msd/include/ms_core.h
new file mode 100644
index 0000000..5739fc1
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_core.h
@@ -0,0 +1,235 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ms_core.h
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   MSD core header file.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __INC_MS_CORE_H
+#define __INC_MS_CORE_H
+
+/*------------------------------------------------------------------------------
+ * Configuration.
+ *----------------------------------------------------------------------------*/
+#define MS_UL_RELOAD_MIN_THRESH	128
+#define MS_UL_RELOAD_GPD_CNT	132
+
+#define MS_CACHE_GPD_NUM	128
+#define MS_MAX_GPD_FOR_READ	32
+
+#define MS_FAST_WRITE_FEATURE 1
+
+/*------------------------------------------------------------------------------
+ * Constant definition.
+ *----------------------------------------------------------------------------*/
+#define USBMS_VENDOR_CMD				0xF0
+#define USBMS_VENDOR_CMD_SUB_SET		0x01
+#define USBMS_VENDOR_CMD_SUB_GET		0x02
+#define USBMS_VENDOR_CMD_SUB_META		0x03
+#define USBMS_VENDOR_CMD_SUB_SET_WIN	0x01
+#define USBMS_VENDOR_CMD_SUB_SET_MAC	0x02
+#define USBMS_VENDOR_CMD_SUB_SET_LINUX	0x03
+
+#define USBMS_VENDOR_CMD_OS_XP			0x01
+#define USBMS_VENDOR_CMD_OS_VISTA		0x02
+#define USBMS_VENDOR_CMD_OS_WIN7		0x03
+#define USBMS_VENDOR_CMD_OS_WIN8		0x04
+
+#define USB11_MAX_PACKET_SIZE	64
+#define USB20_MAX_PACKET_SIZE	512
+#define USB30_MAX_PACKET_SIZE	1024
+
+
+
+	
+	
+#define USB_BULK_CB_WRAP_LEN	31
+#define USB_BULK_CB_SIG		0x43425355	/*little endian: Spells out USBC */
+#define USB_BULK_IN_FLAG	0x80
+	
+#define USB_BULK_CS_WRAP_LEN	13
+#define USB_BULK_CS_SIG		0x53425355	/*little endian: Spells out 'USBS' */
+#define USB_STATUS_PASS		0
+#define USB_STATUS_FAIL		1
+#define USB_STATUS_PHASE_ERROR	2
+	
+/* Bulk-only class specific requests */
+#define USB_BULK_RESET_REQUEST		0xff
+#define USB_BULK_GET_MAX_LUN_REQUEST	0xfe
+	
+
+/* Length of a SCSI Command Data Block */
+#define SS_MAX_COMMAND_SIZE	16
+
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Global variables. 
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+#define MS_CORE_LOCK(_stack_var) _stack_var = SaveAndSetIRQMask()
+#define MS_CORE_UNLOCK(_stack_var) RestoreIRQMask(_stack_var)
+
+#define MS_INC_CTRL_DROPS(_dev, _packets) \
+    { \
+        kal_uint32 _tmp_stack_var; \
+        MS_CORE_LOCK(_tmp_stack_var); \
+        (_dev)->statistics.ctrl_drops += (_packets); \
+        MS_CORE_UNLOCK(_tmp_stack_var); \
+    }
+
+#define MS_INC_CTRL_ERRORS(_dev, _packets) \
+    { \
+        kal_uint32 _tmp_stack_var; \
+        MS_CORE_LOCK(_tmp_stack_var); \
+        (_dev)->statistics.ctrl_errors += (_packets); \
+        MS_CORE_UNLOCK(_tmp_stack_var); \
+    }
+
+
+#define MS_INC_CTRL_PACKETS(_dev, _packets) \
+    { \
+        kal_uint32 _tmp_stack_var; \
+        MS_CORE_LOCK(_tmp_stack_var); \
+        (_dev)->statistics.ctrl_packets += (_packets); \
+        MS_CORE_UNLOCK(_tmp_stack_var); \
+    }
+
+#define MS_INC_RX_DROPS(_dev, _packets) \
+    { \
+        kal_uint32 _tmp_stack_var; \
+        MS_CORE_LOCK(_tmp_stack_var); \
+        (_dev)->statistics.rx_drops += (_packets); \
+        MS_CORE_UNLOCK(_tmp_stack_var); \
+    }
+
+#define MS_INC_RX_ERRORS(_dev, _packets) \
+    { \
+        kal_uint32 _tmp_stack_var; \
+        MS_CORE_LOCK(_tmp_stack_var); \
+        (_dev)->statistics.rx_errors += (_packets); \
+        MS_CORE_UNLOCK(_tmp_stack_var); \
+    }
+
+
+#define MS_INC_RX_PACKETS(_dev, _packets) \
+    { \
+        kal_uint32 _tmp_stack_var; \
+        MS_CORE_LOCK(_tmp_stack_var); \
+        (_dev)->statistics.rx_packets += (_packets); \
+        MS_CORE_UNLOCK(_tmp_stack_var); \
+    }
+
+#define MS_INC_TX_DROPS(_dev, _packets) \
+    { \
+        kal_uint32 _tmp_stack_var; \
+        MS_CORE_LOCK(_tmp_stack_var); \
+        (_dev)->statistics.tx_drops += (_packets); \
+        MS_CORE_UNLOCK(_tmp_stack_var); \
+    }
+
+#define MS_INC_TX_ERRORS(_dev, _packets) \
+    { \
+        kal_uint32 _tmp_stack_var; \
+        MS_CORE_LOCK(_tmp_stack_var); \
+        (_dev)->statistics.tx_errors += (_packets); \
+        MS_CORE_UNLOCK(_tmp_stack_var); \
+    }
+
+
+#define MS_INC_TX_PACKETS(_dev, _packets) \
+    { \
+        kal_uint32 _tmp_stack_var; \
+        MS_CORE_LOCK(_tmp_stack_var); \
+        (_dev)->statistics.tx_packets += (_packets); \
+        MS_CORE_UNLOCK(_tmp_stack_var); \
+    }
+
+
+void ms_core_handle_ilm(ilm_struct *ilm);
+kal_int32 ms_core_ul_reload(void);
+kal_int32 ms_core_init();
+kal_int32 ms_core_deinit(void);
+kal_int32 ms_core_send_tx_gpd_list(qbm_gpd *head, qbm_gpd *tail, kal_uint32 gpd_cnt);
+kal_uint32 ms_core_get_ior_gpd_cnt(usbc_io_request_t *ior);
+kal_int32 ms_core_init_luns(ms_dev_t *dev);
+kal_int32 ms_core_usb_speed(kal_uint32 speed);
+kal_int32 ms_usbc_init(kal_uint8 class_device_id, usb_mode_e mode, kal_uint32 config_num, void *context,kal_uint32 flag);
+kal_int32 ms_usbc_set_config(kal_uint8 class_device_id, kal_uint32 config_num, void *context);
+void ms_usbc_reinit(kal_bool need_check_in);
+kal_uint16 ms_usbc_query_func_wk_capability(void);
+#endif
+
+
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_ctrl.h b/mcu/middleware/hif/usbclass/msd/include/ms_ctrl.h
new file mode 100644
index 0000000..e2bd032
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_ctrl.h
@@ -0,0 +1,117 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ms_ctrl.h
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   MSD control header file.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __INC_MS_CTRL_H
+#define __INC_MS_CTRL_H
+
+/*------------------------------------------------------------------------------
+ * Configuration.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Constant definition.
+ *----------------------------------------------------------------------------*/
+#define MS_MSG_LEN sizeof(kal_int32)
+
+#define MS_MSG_TYPE_KAL_INT32	0
+#define MS_MSG_TYPE_USB_STATE	1
+#define MS_MSG_TYPE_USB_SPEED	2
+#define MS_MSG_TYPE_USB_SETUP_PKT	3
+#define MS_MSG_TYPE_USB_IO_REQUEST	4
+#define MS_MSG_TYPE_USB_EP_STALL	5
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+typedef struct
+{
+	LOCAL_PARA_HDR
+	kal_uint32 msg_type;
+	kal_uint32 msg_length;
+	void *msg_value;
+}ms_ilm_param_t;
+
+
+/*------------------------------------------------------------------------------
+ * Global variables. 
+ *----------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+void ms_ctrl_on_usb_state(kal_uint8 class_device_id, usbc_usb_state_e state);
+void ms_ctrl_on_usb_speed(kal_uint8 class_device_id, usbc_usb_speed_e speed);
+void ms_ctrl_on_setup_packet(kal_uint8 class_device_id, usbc_setup_packet_t *packet);
+void ms_ctrl_on_control_complete(kal_uint8 class_device_id);
+void ms_ctrl_on_bulk_in_complete(kal_uint8 class_device_id, usbc_io_request_t *io_request);
+void ms_ctrl_on_bulk_out_complete(kal_uint8 class_device_id, usbc_io_request_t *io_request);
+void ms_ctrl_on_bulk_in_stall(kal_uint8 class_device_id, kal_bool stall);
+void ms_ctrl_on_bulk_out_stall(kal_uint8 class_device_id, kal_bool stall);
+
+#define MS_CONSTRUCT_LOCAL_PARA(local_para_ptr, local_para_struct) \
+        local_para_ptr = (local_para_struct *) \
+           construct_local_para((kal_uint16)sizeof(local_para_struct),0);
+
+
+#endif
+
+
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_custom.h b/mcu/middleware/hif/usbclass/msd/include/ms_custom.h
new file mode 100644
index 0000000..c365ced
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_custom.h
@@ -0,0 +1,90 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ms_custom.h
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   MSD customization parameter head file.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __INC_MS_CUSTOM_H
+#define __INC_MS_CUSTOM_H
+
+
+/*------------------------------------------------------------------------------
+ * Configuration.
+ *----------------------------------------------------------------------------*/
+#define MS_INTERFACE_STRING_MAX_SIZE 64
+/*------------------------------------------------------------------------------
+ * Constant definition.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Global variables. 
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+extern kal_bool ms_custom_init(usb_mode_e mode,kal_uint32 config_num);
+extern kal_bool ms_custom_deinit(void);
+
+#endif
+
+
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_debug.h b/mcu/middleware/hif/usbclass/msd/include/ms_debug.h
new file mode 100644
index 0000000..c199e2e
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_debug.h
@@ -0,0 +1,14 @@
+#ifndef __INC_MS_DEBUG_H
+#define __INC_MS_DEBUG_H
+
+#if defined(__MTK_TARGET__)
+    #define HIF_CONSOLE_TRACE_ENABLED   0 /* TODO: set it to 0 once DHL log is done on target. */
+#else
+    #define HIF_CONSOLE_TRACE_ENABLED   0
+#endif
+
+#include "hif_trace.h"
+#include "ms_trace.h"
+
+#endif /* __INC_UCD_DEBUG_H */
+
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_defs.h b/mcu/middleware/hif/usbclass/msd/include/ms_defs.h
new file mode 100644
index 0000000..6fda398
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_defs.h
@@ -0,0 +1,298 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ms_defs.h
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   MS device related defines and configurations.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __INC_MS_DEFS_H
+#define __INC_MS_DEFS_H
+
+#include "usbcore_class_device.h"
+#include "hif_ior.h"
+
+
+/*------------------------------------------------------------------------------
+ * Configuration.
+ *----------------------------------------------------------------------------*/
+#define MS_HWO_BM_RECYCLE_TICKS     KAL_TICKS_10_MSEC /* KAL ticks of start bm recycle timer. */
+#define MS_UL_RELOAD_TICKS			KAL_TICKS_10_MSEC /* KAL ticks of start ul reload timer*/
+#define MS_INF_STRING_MAX_SIZE		32
+
+
+/*------------------------------------------------------------------------------
+ * Constant definition.
+ *----------------------------------------------------------------------------*/
+
+#define MSD_BULK_IN_MAX_SIZE 512
+#define MSD_BULK_OUT_MAX_SIZE 512
+
+#define MS_ES_INDEX_HWO_BM_RECYCLE	1
+#define MS_ES_INDEX_UL_GPD_RELOAD	2
+
+#define MS_PIPE_TYPE_BULK_IN	0
+#define MS_PIPE_TYPE_BULK_OUT	1
+#define MS_TOTAL_PIPE_NUM		2
+
+#define USB_DIR_OUT 0
+#define USB_DIR_IN 0x80
+
+#define USB_TYPE_CLASS (0x01 << 5)
+#define USB_RECIP_INTERFACE 0x01
+
+#define MS_FUNC_WAKEUP_CAPABLE	1
+
+
+/*
+ *  DEVICE TYPES
+ */
+#define TYPE_DISK           0x00
+#define TYPE_ROM            0x05
+
+#define MS_SUCCESS 						 1
+#define MS_ERROR_BM_RECYCLING			-1
+#define MS_ERROR_REGISTER_USBC_DEV_FAIL -2
+#define MS_ERROR_SETUP_REQ_ERRORINFO	-3
+#define MS_ERROR_SETUP_UNSUPPORTED		-4
+#define MS_ERROR_NOT_CBW_CMD_GPD		-5
+#define MS_ERROR_CBW_CMD_ERROR			-6
+#define MS_ERROR_ALLOC_GPD_FAILED		-7
+#define MS_ERROR_DO_SCSI_FAILED			-8
+#define MS_ERROR_NOT_ENOUGH_BM			-9
+#define MS_ERROR_MORE_DATA_REQ			-10
+#define MS_ERROR_QUEUE_NO_FULL			-11
+
+#define MS_INFO_SEND_CSW				-500
+#define MS_INFO_CBW_DATA_COMPLETED		-550
+#define MS_INFO_FAST_WRITE_STATUS_GOOD	-600
+
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+typedef enum {
+	MS_STATE_INVALID,	/*Invalid device. */	
+	MS_STATE_INIT,
+	MS_STATE_DEINIT,	/*ms device is deinit*/
+	MS_STATE_IDLE,		/*idle state. */
+	MS_STATE_CBW,		/*CBW state, Transition state from MS idle state. */
+	MS_STATE_DATA_TRANSING,	/*Data translating state,Transition state from CBW state. */
+	MS_STATE_DATA_COMPLETED,/*Data translation completed state,Transition state from translating state.*/
+	MS_STATE_CSW,		/*CBW state,Transition state from data completed state or no data required of CBW state. */
+    
+    MS_STATE_DUMMY = 0x7fffffff /* Make it a 4-byte enum */
+} ms_dev_state_e;
+
+typedef enum {
+	MS_BULK_START,	/*bulk start, data is handled in MS*/
+	MS_BULK_STOP,	/*bulk stop, no data is handled in MS*/	
+	
+	MS_BULK_DUMMY = 0x7fffffff /* Make it a 4-byte enum */
+}ms_bulk_state_e;
+
+typedef enum {
+	MS_DATA_TRANS_NONE, /*data trans default state*/
+	MS_DATA_TRANS_LOOP_CNT,	/*loop cnt more than threshold*/
+	MS_DATA_TRANS_NO_DATA,		/*no data transfer*/
+	MS_DATA_TRANS_NO_BM,		/*no enought bm to allocate*/
+	MS_DATA_TRANS_BULK_STALL,	/*bulk stall*/
+	MS_DATA_TRANS_MAX_STATE = 0xffff,
+
+	MS_DATA_TRANS_DUMMY = 0x7fffffff /* Make it a 4-byte enum */
+}ms_data_trans_state_e;
+
+typedef enum {
+	MS_CSW_STATUS_GOOD = 0,			/*command good*/
+	MS_CSW_STATUS_FAILED = 1,		/*command failed*/
+	MS_CSW_STATUS_PHASE_ERROR = 2	/*phase error*/
+}ms_csw_status_e;
+
+/* Command Block Wrapper */
+typedef struct 
+{
+	kal_uint32	Signature;		/* Contains 'USBC' */
+	kal_uint32 	Tag;			/* Unique per command id */
+	kal_uint32	DataTransferLength; /* Size of the data */
+	kal_uint8	Flags;			/* Direction in bit 7 */
+	kal_uint8	Lun;			/* LUN (normally 0) */
+	kal_uint8	Length; 		/* Of the CDB, <= MAX_COMMAND_SIZE */
+	kal_uint8	CDB[16];		/* Command Data Block */
+}ms_bulk_cb_wrap_t;
+
+/* Command Status Wrapper */
+typedef struct  
+{
+	kal_uint32	Signature;		/* Should = 'USBS' */
+	kal_uint32	Tag;			/* Same as original command */
+	kal_uint32	Residue;		/* Amount not transferred */
+	kal_uint8	Status; 		/* success/fail/phase error */
+	kal_uint8	padding[3];		/* 4 byte alignment*/
+}ms_bulk_cs_wrap_t;
+
+typedef struct
+{
+	ms_data_trans_state_e state_code;
+	kal_int32 (*state_code_callback)(void *);
+}ms_data_trans_err_handle_t;
+
+typedef struct
+{	
+	kal_uint32 num_sectors;
+	kal_uint32 sector_len;
+	
+	kal_uint32 cdrom:1;
+	kal_uint32 readonly:1;
+	kal_uint32 removable:1;
+	kal_uint32 prevent_medium_removal:1;
+	kal_uint32 stop_by_host:1;
+	kal_uint32 info_invalid:1;
+	kal_uint32 last_write_error:1;
+	
+	kal_uint32 sense_data;
+	kal_uint32 sense_info;
+	kal_uint16 max_driver_bd_num;
+}ms_lun_t;
+
+/* maintain read/write status */
+typedef struct
+{
+	kal_uint32	LBA;       /*Logical block address*/
+	kal_uint32	blkcnt;    /*transfer logical blocks count*/
+	kal_uint8	rw_case;	/*read /write case*/
+} ms_rw_cmd;
+
+typedef struct 
+{
+	/*
+	* States.
+	*/
+	ms_dev_state_e dev_state; /**< MS device global state. */
+	ms_bulk_state_e bulkin_state; /**< MS bulk in state.*/
+	ms_bulk_state_e bulkout_state; /**< MS bulk out state.*/
+
+	/*
+	* Handles.
+	*/
+	usbc_class_device_instance_t   *usbc_inst;  /**< Instance acquired in usbc_class_device_register(), which keeps valid until usbc_class_device_deregister(). */
+
+	kal_uint8 lun_num;	/**< total lun num(disk num -1): lun 0 mean the first disk,...*/
+	kal_uint8 cur_mode; /*recorde last mode which from SCSI vendor command*/
+	kal_uint16	rx_allow_data_len; /**< max usb allow data length*/
+	
+	kal_int32	bulk_out_hwo_cnt;  /**< Number of GPD owned by USB for bulk OUT EP. */
+	kal_int32	bulk_in_hwo_cnt;  /**< Number of GPD owned by USB for bulk IN EP. */
+	eventid		hwo_bm_recycle_eventid;  /**< Event id for recycling hwo GPD. */
+	eventid		ul_reload_eventid;  /**< Event id for ul reload. */
+
+	const usb_class_ms_param_t *cus_param;	/**< parameter customization*/
+	ms_lun_t luns[8];    /**< ms lun struct.*/
+	kal_uint32	csw_data_residue;		/**< Amount not transferred */
+	kal_uint8	csw_error_status; 		/**< success/fail/phase error */
+	ms_data_trans_err_handle_t data_trans_err_handle; /**<data trans handle error*/
+	ms_rw_cmd rw_cmd; /**< maintain read/write status */
+	ms_bulk_cb_wrap_t cur_cbw; /**< cbw */
+	kal_bool ior_is_handle;
+	kal_bool need_check_in;
+	kal_bool usbc_reinit;
+	kal_bool usbc_reinit_done;
+} ms_dev_t;
+
+/*------------------------------------------------------------------------------
+ * Global variables. 
+ *----------------------------------------------------------------------------*/
+
+extern ms_dev_t	ms_dev_g; /* ms device context, please use ms_get_dev() to access it outside this file. */
+extern event_scheduler *ms_es_recycle_hwo_gpd_g; /* Timer to retry recycling hwo gpd. */
+extern event_scheduler *ms_es_ul_reload_gpd_g; /* Timer to retry ul reload gpd*/
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+ 
+/*Only one instance */ 
+#define ms_get_dev() &ms_dev_g
+
+#ifdef ATEST_SYS_MSD
+	#define MS_ASSERT(x) if(!(x)) \
+		{	\
+			printf("MSD ASSERT ERROR! %s(%d)\n",__FUNCTION__,__LINE__); \
+		}
+#else
+	#define MS_ASSERT ASSERT 
+#endif
+
+#endif
+
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_scsi.h b/mcu/middleware/hif/usbclass/msd/include/ms_scsi.h
new file mode 100644
index 0000000..b427fc5
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_scsi.h
@@ -0,0 +1,159 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ms_scsi.h
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   MSD core header file.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __INC_MS_SCSI_H
+#define __INC_MS_SCSI_H
+
+/*------------------------------------------------------------------------------
+ * Configuration.
+ *----------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ * Constant definition.
+ *----------------------------------------------------------------------------*/
+
+
+/* SCSI commands that we recognize */
+#define SC_TEST_UNIT_READY       0x00
+#define SC_REQUEST_SENSE         0x03
+#define SC_READ_6                0x08
+#define SC_WRITE_6               0x0a
+#define SC_INQUIRY               0x12
+#define SC_MODE_SELECT           0x15
+#define SC_MODE_SENSE            0x1a
+#define SC_START_STOP            0x1b
+#define SC_ALLOW_MEDIUM_REMOVAL  0x1e
+#define SC_READ_FORMAT_CAPACITIES 0x23
+#define SC_READ_CAPACITY         0x25
+#define SC_READ_10               0x28
+#define SC_WRITE_10              0x2a
+#define SC_VERIFY                0x2f
+#define SC_SYNCHRONIZE_CACHE     0x35
+#define SC_WRITE_BUFFER          0x3b
+#define SC_READ_TOC              0x43
+#define SC_READ_HEADER           0x44
+#define SC_GET_CONFIGURATION	  0x46
+#define SC_GET_EVENT_STATUS_NOTIFICATION 0x4a
+#define SC_READ_DISKINFO		0x51
+#define SC_READ_TRACKINFO		0x52
+#define SC_MODE_SELECT_10     0x55
+#define SC_MODE_SENSE_10         0x5a
+#define SC_READ_12               0xa8
+#define SC_WRITE_12              0xaa
+#define SC_ERASE_12			  0xac
+#define SC_SET_CD_SPEED		  0xbb
+#define SC_READ_CD				  0xbe
+
+/*Vendor command*/
+#define SC_VENDOR_CMD			  0xF0
+#define SC_UNKONW_CMD			  0xFF
+
+	
+/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
+#define SS_NO_SENSE				0
+#define SS_COMMUNICATION_FAILURE		0x040800
+#define SS_INVALID_COMMAND			0x052000
+#define SS_INVALID_FIELD_IN_CDB			0x052400
+#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE	0x052100
+#define SS_LOGICAL_UNIT_NOT_SUPPORTED		0x052500
+#define SS_MEDIUM_NOT_PRESENT			0x023a00
+#define SS_MEDIUM_REMOVAL_PREVENTED		0x055302
+#define SS_NOT_READY_TO_READY_TRANSITION	0x062800
+#define SS_RESET_OCCURRED			0x062900
+#define SS_SAVING_PARAMETERS_NOT_SUPPORTED	0x053900
+#define SS_UNRECOVERED_READ_ERROR		0x031100
+#define SS_WRITE_ERROR				0x030c02
+#define SS_WRITE_PROTECTED			0x072700
+	
+#define SK(x)		((kal_uint8)((x) >> 16))	/* Sense Key byte, etc. */
+#define ASC(x)		((kal_uint8)((x) >> 8))
+#define ASCQ(x)		((kal_uint8)(x))
+
+/*------------------------------------------------------------------------------
+ * Data structure defintion.
+ *----------------------------------------------------------------------------*/
+
+
+/*------------------------------------------------------------------------------
+ * Global variables. 
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+#define MS_SCSI_LOCK(_stack_var) _stack_var = SaveAndSetIRQMask()
+#define MS_SCSI_UNLOCK(_stack_var) RestoreIRQMask(_stack_var)
+
+kal_int32 ms_scsi_do_scsi_cmd(qbm_gpd *gpd_cbw,usbc_io_request_t *ior);
+kal_int32 ms_scsi_handle_received_data(usbc_io_request_t *ior);
+kal_int32 ms_scsi_tx_csw(void *dev_t);
+kal_int32 ms_scsi_handle_read(void *dev_t);
+#endif
+
+
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_trace.h b/mcu/middleware/hif/usbclass/msd/include/ms_trace.h
new file mode 100644
index 0000000..51f1685
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_trace.h
@@ -0,0 +1,17 @@
+#ifndef __INC_MS_TRACE_H
+#define __INC_MS_TRACE_H
+#if HIF_CONSOLE_TRACE_ENABLED != 1
+#ifndef GEN_FOR_PC
+ #include "kal_public_defs.h"
+#endif /* GEN_FOR_PC */
+#include "dhl_trace.h"
+#include "dhl_def.h"
+#if !defined(GEN_FOR_PC)
+#if defined(__DHL_MODULE__) || defined(__CUSTOM_RELEASE__)
+#endif /* TST Trace Defintion */
+#endif
+#endif /* HIF_CONSOLE_TRACE_ENABLED != 1 */
+#if !defined(GEN_FOR_PC)
+#include"ms_trace_mod_usbmsd_utmd.h"
+#endif
+#endif /* __INC_UCD_TRACE_H */
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_trace_mod_usbmsd_utmd.json b/mcu/middleware/hif/usbclass/msd/include/ms_trace_mod_usbmsd_utmd.json
new file mode 100644
index 0000000..4284198
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_trace_mod_usbmsd_utmd.json
@@ -0,0 +1,1370 @@
+{
+  "legacyParameters": {}, 
+  "module": "MOD_USBMSD", 
+  "startGen": "Legacy",
+  "endGen": "Legacy",
+  "traceClassDefs": [
+    {
+      "TRACE_INFO": {
+        "debugLevel": "Medium", 
+        "tag": [
+          "Baseline", 
+          "TRACE_INFO"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_WARNING": {
+        "debugLevel": "High", 
+        "tag": [
+          "Baseline", 
+          "TRACE_WARNING"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_ERROR": {
+        "debugLevel": "High", 
+        "tag": [
+          "Baseline", 
+          "TRACE_ERROR"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_FUNC": {
+        "debugLevel": "Medium", 
+        "tag": [
+          "Baseline", 
+          "TRACE_FUNC"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_STATE": {
+        "debugLevel": "Medium", 
+        "tag": [
+          "Baseline", 
+          "TRACE_STATE"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_1": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_2": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_3": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_4": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_5": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_6": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_7": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_8": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_9": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }, 
+    {
+      "TRACE_GROUP_10": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "Public"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_INIT_BEGIN": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init start...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_INIT_FINISHED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init finished!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_INIT_FAILED": {
+        "apiType": "index", 
+        "format": "[MSD] MS adapter custom init failed!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_DEINIT_BEGIN": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom DeInit begin...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_DEINIT_FINISHED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom deinit finished!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_DEINIT_CDROM_HANDLE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter: cdrom driver handler(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_DEINIT_CDROM_FS_LOCK": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter: FS lock(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_DEINIT_CDROM_FREE_FS_LOCK": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter: after free lock,fs_lock(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_NO_CUS_PARAM": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init fail, no custom parameter!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_NO_DISK_CONFIG": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init fail, no disk configured!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_DISK_CONFIG_TOO_MANY": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init fail, configured too many disk!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_NO_SD_MMC_SUPPORT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init fail, No SD MMC support, please check the feature option __MSDC_SD_MMC__ !!!!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_NO_SD_MMC_DUAL_CARD_SUPPORT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init fail, No SD MMC dual card support, please check the feature option __MSDC_SD_MMC__ and __MSDC_DUAL_CARD_SWITCH__ !!!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_NO_NAND_SUPPORT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init fail, No NAND support, please check feature option NAND_SUPPORT", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_NO_RAMDISK_SUPPORT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init fail, No RAMDISK support, please check the feature option __USB_RAMDISK__", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_CDROM_REGISTERED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init,CDROM driver registered!!!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_RAMDISK_REGISTERED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init,RAMDISK driver registered!!!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_NO_DISK_REGISTERED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init,No disk is registered,please check disk config!!!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_CUSTOM_REGISTERED_DISK": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter custom init,Registered %d disks!!!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter usbms_read_write_failed sub_head:(0x%x),sub_tail:(0x%x),lba:(%d),lba_num:(%d),data_len(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_OUT_OF_RANGE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter rw LBA out of range,lastLBA:(%d),rw LBA:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_RESIDUE_GPD": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter rw residue gpd,write seq(%d),write gpd(%d),residue gpd:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_LBA_LEN_ERR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter rw lba len error,lba_len:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_LBA_NUM_MISS_MATCH": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter rw lba len/num miss match,wrote:(%d),want to wrote:(%d),addr:(0x%x),data len:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_DATA_PTR_ERR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter rw data ptr is NULL", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_DIR_WRITE_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter direct write failed,data_ptr:(0x%x),lba:(%d),lba_sec_num:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_DIR_READ_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter direct read failed,data_ptr:(0x%x),lba:(%d),lba_sec_num:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_DATA_LEN_INVALID": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter invalid write data len:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_RW_CACHE_OUT_OF_RANGE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter rw cache out of range:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_INIT_NORMAL_MODE_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter init normal mode failed,result:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_FS_GET_DEVSTATUS_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter get dev status failed,result:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_ADAPTER_INIT_CDROM_ISO_NOT_FOUND": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS adapter init cdrom iso not found,result:(%d),DeRegister driver!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_FREE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm free(%d)gpds,all free gpds(%d)!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_FREE_IN_ERR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm free Input Error!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_DE_INIT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm deinit finished!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_DE_INIT_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm deinit failed - not all gpd free!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_ALLOC": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm alloc(%d)gpds,all free gpds(%d)!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_ALLOC_MORE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm allocate need cnt(%d)is more than now free gpd(%d)!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_ALLOC_NO_FREE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm allocate failed - No free GPD!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_ALLOC_REQUIRE_ERR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm allocate failed - Require cnt error(%d)!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_INIT_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm init failed - Qbm_init_queue Error code:(%d)!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_BM_REINIT_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS bm reinit failed - not all gpd free!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_ON_USB_STATE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] USB state notify, usbc device id:%d,state:%d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_ON_USB_SPEED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] USB speed changed,usbc device id:%d,speed:%d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_ON_USB_SETUP_PKT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] USB setup pkt recevied", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_ON_USB_CTRL_COMPLETED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] USB send ctrl pkt completed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_ON_USB_BULKIN_COMPLETED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] USB bulk in completed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_ON_USB_BULKOUT_COMPLETED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] USB bulk out completed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_ON_USB_BULKIN_STALL": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] USB bulk in stall state(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_ON_USB_BULKOUT_STALL": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] USB bulk out stall state(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_SETUP_PKT_INFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] received setup pkt, reqType=0x%x, req=0x%x, wVal=%d, wIdx=%d, wLen=%d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_SETUP_PKT_ERROR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] setup pkt info error,reqType=0x%x, req=0x%x, wVal=%d, wIdx=%d, wLen=%d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CTRL_SETUP_PKT_REQUEST_UNSUPPORTED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] setup pkt unsupported!,reqType=0x%x, req=0x%x, wVal=%d, wIdx=%d, wLen=%d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_START_BM_RECYCLE_TIMER": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] start recycle HWO GPD timer,timer(%d)...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_SET_BM_RECYCLE_TIMER_ERROR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] start recycle HWO GPD timer error!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_BM_RECYCLE_TIME_OUT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] recycle HWO GPD time out!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_BM_RECYCLE_RESTART": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] recycle HWO GPD time out and recycle is needed, restart...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_BM_RECYCLE_START": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] try to start BM recycling now...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_BM_RECYCLE_FINISHED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] BM recycling completed, send reinit ILM to MSD", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_INIT_BEGIN": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS core init begin...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_INIT_FINISHED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS core init completed...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_DEINIT_NEED_BM_RECYCLE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] MS core deinit, bm recycle is needed...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_MALLOC_BM": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] malloc bm buffer, to_alloc(%d),num_alloc(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_UL_GPD_ALLOW_LEN": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] UL submitted GPD, update allow length(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_UL_GPD_SUBMITTED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] UL submitted GPD, total number(%d) in HIF", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_UL_RELOAD_TIMER": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] start UL reload timer, timer(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_UL_RELOAD_TIMEOUT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] UL reload time out!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_UL_RELOAD_RESTART_ILM": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] send ILM to MSD for restart UL reload!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_SEND_SUBMIT_GPD_LIST": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] TX GPD count(%d) to usb core", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_SEND_BACK_GPD_LIST": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] TX GPD count back(%d) from usb core", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_DATA_TRANS_STATE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Data translate state(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_DATA_START_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Data start failed for dev->usbc_inst is NULL", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_BULK_IN_STATE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]BULK IN STALL?(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_BULK_OUT_HWO_CNT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]BULK OUT HWO cnt(%d),RX GPD cnt(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_BULK_IN_HWO_CNT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] BULK IN HWO cnt(%d),TX GPD cnt(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_BULK_IN_HWO_CNT_IN_FALSE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]BULK IN HWO in failed cnt(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_HANDLE_USB_MODE_SWITCH": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]=============USB MODE SWITCH,switch to mode(%d)===============", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_HANDLE_USB_RESET_DEVICE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]******RESET DEVICE REQUEST...******", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_IF_USBC_INIT_INFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]MS IF USBC INIT INFO:if_id(%d),bulkin_ep(%d),bulkou_ep(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_IF_USBC_SET_CONF_INFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]MS IF set config...mode(%d),conf_num(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_IF_USBC_SET_CONF": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]MS IF set config retval(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_IF_USBC_REINIT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]MS IF USBC REINIT,need_check_in(%d)...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_IF_USBC_WAIT_REINIT_DONE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]MS IF USBC REINIT,wait reinit done(%d)...", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_IF_USBC_REINIT_DONE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]MS IF USBC REINIT DONE,reinit done, total wait time(%d)(ms)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_IF_USBC_SET_FUNC_WK_ABILITY": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD]MS IF USBC set func wake ability(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_INQUIRY": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - INQUIRY, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_REQUEST_SENSE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - REQUEST_SENSE, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_TEST_UNIT_READY": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - TEST_UNIT_READY, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_READ": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - READ, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_READ_6": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - READ_6", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_READ_10": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - READ_10", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_READ_12": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - READ_12", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_WRITE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - WRITE, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_WRITE_6": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - WRITE_6", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_WRITE_10": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - WRITE_10", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_WRITE_12": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - WRITE_12", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_MODE_SELECT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - MODE_SELECT, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_MODE_SELECT_10": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - MODE_SELECT_10, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_MODE_SENSE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - MODE_SENSE, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_START_STOP": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - START_STOP, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_ALLOW_MEDIUM_REMOVAL": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - ALLOW_MEDIUM_REMOVAL, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_READ_FORMAT_CAPACITIES": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - READ_FORMAT_CAPACITIES, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_READ_CAPACITY": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - READ_CAPACITY, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_VERIFY": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - VERIFY, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_MODE_SENSE_10": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - MODE_SENSE_10, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_READ_TOC": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - READ_TOC, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_GET_CONFIGURATION": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - GET_CONFIGURATION, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_READ_DISKINFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - READ_DISKINFO, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_UNKNOWN_CMD": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI command - UNKNOWN_CMD, LUN(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_TX_GPG_LIST_ERROR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Tx gpd list to usb core ERROR!!", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_ATTEMPT_STOP_PREVENT": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] attempt stop prevent lun(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_VENDOR_CMD": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] handle vendor cmd(0x%x),CDB1=0x%x,CDB2=0x%x,CDB3=0x%x", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_TX_CSW": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] <=== Do SCSI TX CSW", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_TX_CSW_SUCCESS": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI tx csw success", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_TX_CSW_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI tx csw failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_ALLOC_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI alloc gpd failed cnt:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_GEN_SENSEKEY": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI gen sensekey sd:(%d),sdinfo:(%d),valid:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_GEN_INQUIRY_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI gen inquiry failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_GEN_INQUIRY_INFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI gen inquiry info -- vendor:(%s),product:(%s),revision:(%s)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_STATUS_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI hand write status:(%d),csw status:(%d) failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_FAST_WRITE_TX_CSW_STATUS": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write,FAST WRITE TX CSW status(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_FAST_WRITE_TX_CSW_AGAIN_STATUS": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write,WRITE TX CSW again for no BM, status(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_LAST_WRITE_ERROR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write,LUN(%d),last write error(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_MORE_GPD": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI gpd list more than data tansfer", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_LBA_NUM": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write: cur(%d) of total(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_TX_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write tx failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_MORE_TO_WRITE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write more data to write residue:(%d),blk cnt:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write failed LBA:(%d),residue:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_NO_IOR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write No ior to write", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_SEC_LEN_ERR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write lba len is 0", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_WRITE_RESIDUE_LEN_ERR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle write residue len err,blk cnt(%d),lba len:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_DUMMY_TX_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI do dummy tx failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_DUMMY_ERROR_DIR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI do dummy unknow direction", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_INFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read info -- residue:(%d),need_gpd:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_STATE_ERROR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read status error:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_ALLOC_GPD": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read alloc gpd:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_LBA_NUM": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read lba index:(%d),lba num:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_FAILED_FREE_BUF": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read failed -- free buffer", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_ALLOC_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read alloc failed gpd cnt:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_FINISH": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read finish", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_FINISH_5": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read case 5 finish", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_FINISH_7": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read case 7 finish", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_STATUS_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI hand read status:(%d),csw status:(%d),lba_len(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_RESIDUE_LEN_ERR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI hand read residue len err,blk cnt(%d),lba len:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_SEND_SHORT_PACKET_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI send short packet failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_TX_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read tx failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_HANDLE_READ_MORE_LOOP": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI handle read loop cnt(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_IQ_TX_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI do inquire tx failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_CAP_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read capacity failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_CAP_STATUS_ERROR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read capacity status error:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_CAP_ALLOC_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read capacity alloc failed cnt:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_CAP_INFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read capacity info -- LBA:(%d),len(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_CAP_TX_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read capacity tx failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_FMT_CAP_INFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read fmt capacity info -- blk no:(%x),blk len(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_FMT_TX_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read fmt capacity tx failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_FMT_ALLOC_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read fmt alloc failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_LBA_INFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read lba info -- lba len:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_CASE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read case:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_CSW_STATUS_ERROR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read csw status error,status:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_MEDIA_ERR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read media error,sense_data:(%d),lba_len:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_WRITE_INFO": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI write info -- lba len:(%d),blk cnt(%d),data(%d) byte", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_WRITE_CASE": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI write case:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_WRITE_MEDIA_ERR_DROP_DATA": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI write media err drop data sense_data:(%d),ior addr:(%d),lba_len:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_WRITE_MEDIA_ERR": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI write media error,sense_data(%d),lba_len:(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_REQ_SENSE_TX_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI req sense tx failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_REQ_SENSE_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI req sense failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_GET_CONFIG_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI get configuration failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_DO_READ_DISKINFO_FAILED": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI read diskinfo failed", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_LOG_DATA_ADDR_LEN": {
+        "_comment": "Trace reference not found", 
+        "format": "[MSD] Do SCSI log data addr:(%x),len(%d),print(%d)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_LOG_DATA": {
+        "_comment": "Trace reference not found", 
+        "format": "%02x ", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_SCSI_LOG_DROP_DATA": {
+        "_comment": "Trace reference not found", 
+        "format": "****************DROP DATA***************", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_LOG_IOR": {
+        "_comment": "Trace reference not found", 
+        "format": "****IOR(0x%x)****", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_LOG_EQUAL": {
+        "_comment": "Trace reference not found", 
+        "format": "=================", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "MSD_TR_MS_CORE_LOG_GPD_ADDRESS": {
+        "_comment": "Trace reference not found", 
+        "format": "gpd(0x%x)", 
+        "traceClass": "TRACE_INFO"
+      }
+    }
+  ], 
+  "traceFamily": "PS",
+  "userModule": "MOD_USBMSD"
+}
\ No newline at end of file
diff --git a/mcu/middleware/hif/usbclass/msd/include/ms_ut.h b/mcu/middleware/hif/usbclass/msd/include/ms_ut.h
new file mode 100644
index 0000000..46d8ef4
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/ms_ut.h
@@ -0,0 +1,134 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ms_ut.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   MSD unit test defines.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __INC_MS_UT_H
+#define __INC_MS_UT_H
+
+/*------------------------------------------------------------------------------
+ * Configurations.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Data structure.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * Helper macros for UT and normal modes.
+ *----------------------------------------------------------------------------*/
+#define _msd_ut_printf printf
+	
+#define msd_ut_printf(_fmts, ...) \
+			_msd_ut_printf("%s(): " _fmts, __FUNCTION__, ##__VA_ARGS__)
+	
+#define msd_ut_format_err_str(_fmts, ...) \
+			kal_sprintf(p_ret_err_str, "%s:%d: " _fmts, __FILE__, __LINE__, ##__VA_ARGS__); \
+			msd_ut_printf("[FAILED] " _fmts, ##__VA_ARGS__)
+			
+
+#ifdef ATEST_SYS_MSD
+
+	#define msd_hif_register msd_ut_hif_register
+
+	#define msd_hif_deregister msd_ut_hif_deregister
+
+	#define msd_hif_submit_control_request msd_ut_hif_submit_control_request
+
+	#define msd_hif_submit_io_request msd_ut_hif_submit_io_request
+
+	#define msd_hif_flush_io_request msd_ut_hif_flush_io_request
+#else
+
+	#define msd_hif_register usbc_class_device_register
+
+	#define msd_hif_deregister usbc_class_device_deregister
+
+	#define msd_hif_submit_control_request usbc_class_device_submit_control_request
+
+	#define msd_hif_submit_io_request usbc_class_device_submit_io_request
+
+	#define msd_hif_flush_io_request usbc_class_device_flush_io_request
+#endif
+
+#ifdef ATEST_SYS_MSD
+/*------------------------------------------------------------------------------
+ * UT specific helper macros.
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+ * UT specific public fucntions.
+ *----------------------------------------------------------------------------*/
+usbc_class_device_instance_t *msd_ut_hif_register(kal_uint8 class_device_id,usbc_class_device_info_t *device_info);
+
+kal_bool msd_ut_hif_deregister(kal_uint8 class_device_id);
+
+kal_bool msd_ut_hif_submit_control_request(kal_uint8 class_device_id, kal_uint8 *buffer, kal_uint32 length, usbc_control_request_type_e type);
+
+kal_bool msd_ut_hif_submit_io_request(kal_uint8 class_device_id, kal_uint8 queue_no, usbc_io_request_t *io_request);
+kal_bool msd_ut_hif_flush_io_request(kal_uint8 class_device_id, kal_uint8 queue_no);
+
+#endif /* ATEST_SYS_MSD */
+#endif /* __INC_MBIM_UT_H */
+
diff --git a/mcu/middleware/hif/usbclass/msd/include/mse_common.h b/mcu/middleware/hif/usbclass/msd/include/mse_common.h
new file mode 100644
index 0000000..2291649
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/mse_common.h
@@ -0,0 +1,81 @@
+/*!
+ *  @file adb_common.h
+ *  @author TJ Chang <tj.chang@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  
+ */
+
+#ifndef _MSE_COMMON_H
+#define _MSE_COMMON_H
+
+#include "kal_general_types.h"
+
+/* USB_CORE */
+#include "usbcore_class_device.h"
+
+
+// ==========================================================
+// Macro Definition
+// ==========================================================
+
+
+// ==========================================================
+// Data Structure Definition
+// ==========================================================
+typedef enum _MSE_PIPE_TYPE_E {
+    MSE_PIPE_TYPE_DATA_IN = 0,
+    MSE_PIPE_TYPE_DATA_OUT = 1,
+    MSE_PIPE_MAX_NUM,
+} MSE_PIPE_TYPE_E;
+
+typedef struct _mse_device_instance_t
+{
+    /* COMMON */
+    kal_bool                        is_used;    /**< KAL_TRUE if this cdcacm instance is used, KAL_FALSE otherwise. */
+
+    /* USB_CORE */
+    kal_bool                        usb_ready;  /**< USB read state. */
+    kal_bool                        usb_pipe_ready[MSE_PIPE_MAX_NUM];    /**< USB pipe state. */
+    usbc_class_device_instance_t    *usb_handler;   /**< USB handler is acquired when registering usb_core, and used to communicate with usb_core. */
+    usbc_usb_state_e                usb_state;  /**< USB state. */
+    usbc_usb_speed_e                usb_speed;  /**< USB speed. */
+    kal_uint8                       usb_class_id;  /**< USB class id. */
+    usb_class_type_e                if_type;  /**< USB MSE interface type.which is defined in usbc_custom.h. */
+    kal_uint8                       func_wakeup_enabled;  /**< 1 if function remote wakeup is enabled. */
+    kal_uint8                       is_usb_state_suspend; /**< 1 if in usb suspend state */
+} mse_device_instance_t;
+
+#endif  /* _MSE_COMMON_H */
diff --git a/mcu/middleware/hif/usbclass/msd/include/mse_core.h b/mcu/middleware/hif/usbclass/msd/include/mse_core.h
new file mode 100644
index 0000000..858d2d5
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/mse_core.h
@@ -0,0 +1,67 @@
+/*!
+ *  @file mse_core.h
+ *  @author TJ Chang <tj.chang@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  
+ */
+
+#ifndef _MSE_CORE_H
+#define _MSE_CORE_H
+
+#include "mse_common.h"
+#include "usbcore_debug.h"
+
+#define mse_trace_info usbc_trace_info
+// ==========================================================
+// Macro Definition
+// ==========================================================
+#define MSE_FUNC_WAKEUP_CAPABLE              1 /* 1 to enable USB function remote wakeup capable; 0 to disable. */
+#define MSE_MAX_REMOTE_WAKEUP_SLEEP_TICKS    KAL_TICKS_10_MSEC /* Interval to check if remote wakeup is completed. */
+#define MSE_MAX_REMOTE_WAKEUP_WAIT_TICKS     KAL_TICKS_1_SEC /* Maximal time to wait for the completion of remote wakeup. */
+
+/* MSE-related USB Protocol Definition */
+#define MSE_EP_BULK_MAXP                 0x0200
+#define MSE_DATA_CLASS                   0x08
+#define MSE_DATA_SUBCLASS                0x06
+#define MSE_DATA_PROTOCOL                0x50
+
+mse_device_instance_t* mse_core_get_instance();
+kal_int32 mse_core_set_config(kal_uint8 class_device_id, kal_uint32 config_num);
+void mse_core_deinit(mse_device_instance_t *p_dev_inst);
+void mse_core_reinit(kal_bool need_checkin);
+kal_bool mse_task_init(void);
+
+#endif  /* _MSE_CORE_H */
diff --git a/mcu/middleware/hif/usbclass/msd/include/mse_usbhdr.h b/mcu/middleware/hif/usbclass/msd/include/mse_usbhdr.h
new file mode 100644
index 0000000..5bf205f
--- /dev/null
+++ b/mcu/middleware/hif/usbclass/msd/include/mse_usbhdr.h
@@ -0,0 +1,110 @@
+/*!
+ *  @file mse_usbhdr.h
+ *  @author TJ Chang <tj.chang@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  
+ */
+
+#ifndef _MSE_USBHDR_H
+#define _MSE_USBHDR_H
+
+#include "kal_general_types.h"
+#include "usbcore_class_device.h"
+#include "mse_common.h"
+
+
+// ==========================================================
+// Data Structure Definition
+// ==========================================================
+
+
+// ==========================================================
+// USBHDR Public Function
+// ==========================================================
+/**
+ * mse_usbhdr_checkin 
+ *
+ * CDCACM USB Handler - Checkin CDCACM callback function into USB stack.
+ *
+ * @return      KAL_TRUE if success, otherwise KAL_FALSE if fail.
+ */
+kal_bool mse_usbhdr_checkin();
+
+/**
+ * mse_usbhdr_reg_usbcore 
+ *
+ * CDCACM USB Handler - Register to USB_CORE
+ *
+ * @param       [IN] p_dev_inst             mse device instance
+ *
+ * @return      KAL_TRUE if success, otherwise KAL_FALSE if fail.
+ */
+kal_bool mse_usbhdr_reg_usbcore(mse_device_instance_t *p_dev_inst);
+
+/**
+ * mse_usbhdr_expt_reg_usbcore
+ *
+ * CDCACM USB Handler - Register exception handling to USB_CORE
+ *
+ * @param       [IN] p_dev_inst             mse exception device instance
+ *
+ * @return      KAL_TRUE if success, otherwise KAL_FALSE if fail.
+ */
+kal_bool mse_usbhdr_expt_reg_usbcore(mse_device_instance_t *p_dev_inst);
+
+/*!
+ * usbcore reports USB remote wakeup ability
+ *
+ * @param class_device_id [IN] Identifier of the RNDIS device.
+ * @param ability         [IN] KAL_TRUE if remote wakeup ability is enabled, otherwise is KAL_FALSE.
+ */
+void mse_usbhdr_set_func_wk_ability(kal_uint8 class_device_id, kal_bool ability);
+
+/*!
+ * usbcore queries USB remote status.
+ *
+ * @param class_device_id [IN] Identifier of the RNDIS device.
+ */
+kal_uint16 mse_usbhdr_query_func_wk_status(kal_uint8 class_device_id);
+
+kal_int32 mse_usbhdr_init(kal_uint8 class_device_id, usb_mode_e mode, kal_uint32 config_num, void *context, kal_uint8 flag);
+kal_int32 mse_usbhdr_set_config(kal_uint8 class_device_id, kal_uint32 config_num, void *context);
+void mse_usbhdr_reinit(kal_bool need_checkin);
+kal_uint16 mse_usbhdr_query_func_wk_capability();
+
+
+#endif  /* _MSE_USBHDR_H */
+
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_cosim.h b/mcu/middleware/hif/usbcore/include/usbcore_cosim.h
new file mode 100644
index 0000000..be4da46
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_cosim.h
@@ -0,0 +1,27 @@
+#ifndef _USBCORE_COSIM_H
+#define _USBCORE_COSIM_H
+
+#include "hif_usb.h"
+#include "usbcore_main.h"
+#include "usbcore_hif.h"
+#include "dhl_trace.h"
+
+#define USBC_ESL_DEBUG  0
+
+#if USBC_ESL_DEBUG
+    #define usbc_esl_printf(...) hsl_printf(__VA_ARGS__)
+#else
+    #define usbc_esl_printf(...) 
+#endif
+
+/*!
+ *  @brief usbcore initial for ESL COSIM
+ */
+kal_bool usbc_cosim_core_task_init(void);
+
+/*!
+ * @brief usbcore main function for ESL COSIM
+ */
+void usbc_cosim_core_task_main(task_entry_struct*);
+
+#endif  // _USBCORE_HIF_H
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_data_path_trace_utmd.json b/mcu/middleware/hif/usbcore/include/usbcore_data_path_trace_utmd.json
new file mode 100644
index 0000000..837f7a8
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_data_path_trace_utmd.json
@@ -0,0 +1,250 @@
+{
+  "legacyParameters": {
+    "codeSection": "TCMFORCE", 
+    "l2BufferSetting": "L2_BUFFER_HIF", 
+    "l2MaxArg": 7, 
+    "modemType": "Generic"
+  }, 
+  "module": "USBCORE_L2", 
+  "stringTranslationDefs": [], 
+  "startGen": "Legacy",
+  "endGen": "-",
+  "traceClassDefs": [
+    {
+      "USBCORE_POLL_QUEUE_UL": {
+        "debugLevel": "Ultra-Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "CoreDesign"
+      }
+    },
+    {
+      "USBCORE_POLL_QUEUE_M": {
+        "debugLevel": "Medium", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "USBCORE_POLL_QUEUE_L": {
+        "debugLevel": "Low", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "CoreDesign"
+      }
+    },
+    {
+      "USBCORE_CLASS_REQUEST_UH": {
+        "debugLevel": "Ultra-High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "USBCORE_CLASS_REQUEST_H": {
+        "debugLevel": "High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "USBCORE_CLASS_REQUEST_M": {
+        "debugLevel": "Medium", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "USBCORE_POLL_QUEUE_H": {
+        "debugLevel": "High", 
+        "filterDefaultValue": "ON", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "USBCORE_POLL_QUEUE_E": {
+        "format": "[USBCORE] checked E_txq[%xd], E_rxq[%xl]",
+        "traceClass": "USBCORE_POLL_QUEUE_H"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_TX": {
+        "format": "[USBCORE] polling Tx_q[%d], returns %l GPD(s), first gpd %xl, last gpd %xl", 
+        "traceClass": "USBCORE_POLL_QUEUE_M"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_TX_ONE": {
+        "format": "[USBCORE] polling Tx_q[%d], returns gpd %xl", 
+        "traceClass": "USBCORE_POLL_QUEUE_M"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_TX_NOTIFY_END": {
+        "format": "[USBCORE] finishing notifing poll Tx queue complete:  class id = %d", 
+        "traceClass": "USBCORE_POLL_QUEUE_L"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_RX": {
+        "format": "[USBCORE] polling Rx_q[%d], returns %l GPD(s), first gpd %xl, last gpd %xl", 
+        "traceClass": "USBCORE_POLL_QUEUE_M"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_RX_ONE": {
+        "format": "[USBCORE] polling Rx_q[%d], returns gpd %xl",
+        "traceClass": "USBCORE_POLL_QUEUE_M"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_RX_NOTIFY_END": {
+        "format": "[USBCORE] finishing notifing poll Rx queue complete:  class id = %d", 
+        "traceClass": "USBCORE_POLL_QUEUE_L"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_LEN_TX": {
+        "format": "[USBCORE] polling Tx_q[%d], GPD length = %xl, BD_length = %xl, SPD length = %xl", 
+        "traceClass": "USBCORE_POLL_QUEUE_L"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_LEN_RX": {
+        "format": "[USBCORE] polling Rx_q[%d], GPD length = %xl, BD_length = %xl, SPD length = %xl", 
+        "traceClass": "USBCORE_POLL_QUEUE_L"
+      }
+    }, 
+    {
+      "USBCORE_CLASS_SUBMIT_IO_REQUEST_HWQ": {
+        "format": "[USBCORE] submit hw_q type/q_no = %xd, first gpd %xl, last gpd %xl", 
+        "traceClass": "USBCORE_CLASS_REQUEST_M"
+      }
+    }, 
+    {
+      "USBCORE_CLASS_SUBMIT_IO_REQUEST_HWQ_ONE": {
+        "format": "[USBCORE] submit hw_q type/q_no = %xd, gpd %xl",
+        "traceClass": "USBCORE_CLASS_REQUEST_M"
+      }
+    }, 
+    {
+      "USBCORE_CLASS_SUBMIT_IO_REQUEST_SWQ": {
+        "format": "[USBCORE] submit sw_q type/q_no = %xd, first gpd %xl, last gpd %xl", 
+        "traceClass": "USBCORE_CLASS_REQUEST_M"
+      }
+    }, 
+    {
+      "USBCORE_CLASS_SUBMIT_IO_REQUEST_SWQ_ONE": {
+        "format": "[USBCORE] submit sw_q type/q_no = %xd, gpd %xl",
+        "traceClass": "USBCORE_CLASS_REQUEST_M"
+      }
+    }, 
+    {
+      "USBCORE_CLASS_FLUSH_HW_QUEUE": {
+        "format": "[USBCORE] flush HW_q[%xd], returns %l GPD(s), first gpd %xl, last gpd %xl", 
+        "traceClass": "USBCORE_CLASS_REQUEST_H"
+      }
+    }, 
+    {
+      "USBCORE_CLASS_FLUSH_SW_QUEUE": {
+        "format": "[USBCORE] flush SW_q[%xd], returns %l GPD(s), first gpd %xl, last gpd %xl", 
+        "traceClass": "USBCORE_CLASS_REQUEST_H"
+      }
+    }, 
+    {
+      "USBCORE_RESTORE_RX_GPD_SWQ2HWQ": {
+        "format": "[USBCORE] restore Rx GPDs from sw_q to hw_q: type/q_no = %xd", 
+        "traceClass": "USBCORE_CLASS_REQUEST_H"
+      }
+    }, 
+    {
+      "USBCORE_RESTORE_TX_GPD_SWQ2HWQ": {
+        "format": "[USBCORE] restore Tx GPDs from sw_q to hw_q: type/q_no = %xd", 
+        "traceClass": "USBCORE_CLASS_REQUEST_H"
+      }
+    }, 
+    {
+      "USBCORE_DIRECT_POLL_QUEUE": {
+        "format": "[USBCORE] direct polling dir = %d, md_q = %l, ap_q = %l", 
+        "traceClass": "USBCORE_POLL_QUEUE_M"
+      }
+    }, 
+    {
+      "USBCORE_DIRECT_SUBMIT_IO_REQUEST": {
+        "format": "[USBCORE] direct submitIO dir = %d, md_q = %l, ap_q = %l", 
+        "traceClass": "USBCORE_CLASS_REQUEST_M"
+      }
+    }, 
+    {
+      "USBCORE_DIRECT_FLUSH_HW_QUEUE": {
+        "format": "[USBCORE] direct flush_hw_q dir = %d, md_q = %l, ap_q = %l", 
+        "traceClass": "USBCORE_CLASS_REQUEST_H"
+      }
+    }, 
+    {
+      "USBCORE_DIRECT_FLUSH_SW_QUEUE": {
+        "format": "[USBCORE] direct flush_sw_q dir = %d, md_q = %l, ap_q = %l", 
+        "traceClass": "USBCORE_CLASS_REQUEST_H"
+      }
+    }, 
+    {
+      "USBCORE_DIRECT_CHK_QUEUE_EMPTY": {
+        "format": "[USBCORE] direct check queue empty isTx = %d, md_q = %l, ap_q = %l, isEmpty = %l", 
+        "traceClass": "USBCORE_CLASS_REQUEST_UH"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_DRB": {
+        "format": "[USBCORE] polling drb_q[%d], returns %l field(s), startIdx %l, endIdx %l", 
+        "traceClass": "USBCORE_POLL_QUEUE_M"
+      }
+    }, 
+    {
+      "USBCORE_POLL_QUEUE_XIT": {
+        "format": "[USBCORE] polling xit_q[%d], returns %l field(s), startIdx %l, endIdx %l", 
+        "traceClass": "USBCORE_POLL_QUEUE_M"
+      }
+    }, 
+    {
+      "USBCORE_CHK_UL_META": {
+        "format": "[USBCORE] CHK UL META: type = %d, startIdx %l, endIdx %l", 
+        "traceClass": "USBCORE_POLL_QUEUE_UL"
+      }
+    }, 
+    {
+      "USBCORE_DEBUG_XIT_ENQ1": {
+        "format": "[USBCORE] DBG XIT: index = %d, len = %l, data_addr = %l", 
+        "traceClass": "USBCORE_POLL_QUEUE_UL"
+      }
+    }, 
+    {
+      "USBCORE_DEBUG_XIT_ENQ2": {
+        "format": "[USBCORE] DBG_XIT: dump: %d, %l, %l, %l", 
+        "traceClass": "USBCORE_POLL_QUEUE_UL"
+      }
+    }
+  ], 
+  "traceFamily": "L2",
+  "userModule": "MOD_USBCORE"
+}
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_debug.h b/mcu/middleware/hif/usbcore/include/usbcore_debug.h
new file mode 100644
index 0000000..09e1f08
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_debug.h
@@ -0,0 +1,129 @@
+#ifndef _USBCORE_DEBUG_H
+#define _USBCORE_DEBUG_H
+
+#define HIF_DATA_TRACE_ENABLED          1
+#define USBCORE_CONSOLE_TRACE_ENABLED   0
+
+#include "hif_trace.h"
+#include "TrcMod.h"
+#include <ex_public.h>
+
+extern void dbg_print(char *fmt,...);
+
+
+#if USBCORE_CONSOLE_TRACE_ENABLED
+    /*
+     * Print indexed trace to console.
+     */
+    #if defined(__MTK_TARGET__)
+        #define usbc_console_print  dbg_print
+    #else
+        #define usbc_console_print
+    #endif
+
+    #define usbc_trace_error(...)   usbc_console_print(__VA_ARGS__)
+    #define usbc_trace_warn(...)    usbc_console_print(__VA_ARGS__)
+    #define usbc_trace_info(...)    usbc_console_print(__VA_ARGS__)
+    #define usbc_data_trace    hif_data_trace
+#else    
+
+    /*
+     * Use DHL logging.
+     */
+    #define usbc_trace_error(trc_name, ...)                               \
+        do{                                                               \
+            if(INT_QueryExceptionStatus() == KAL_FALSE)                   \
+            {                                                             \
+                MD_TRC_##trc_name(__VA_ARGS__);                           \
+            }                                                             \
+        }while(0)
+
+    #define usbc_trace_warn(trc_name, ...)                                \
+        do{                                                                \
+            if(INT_QueryExceptionStatus() == KAL_FALSE)                    \
+            {                                                              \
+                MD_TRC_##trc_name(__VA_ARGS__);                            \
+            }                                                              \
+        }while(0)
+
+    #define usbc_trace_info(trc_name, ...)                                \
+        do{                                                               \
+            if(INT_QueryExceptionStatus() == KAL_FALSE)                   \
+            {                                                             \
+                MD_TRC_##trc_name(__VA_ARGS__);                           \
+            }                                                             \
+        }while(0)
+
+    #define usbc_trace_func(trc_name, ...)                                           \
+        do{                                                               \
+            if(INT_QueryExceptionStatus() == KAL_FALSE)                   \
+            {                                                             \
+                MD_TRC_##trc_name(__VA_ARGS__);                           \
+            }                                                             \
+        }while(0)
+
+    #define usbc_data_trace    hif_data_trace
+#endif /* USBCORE_CONSOLE_TRACE_ENABLED */
+
+
+#include "usbcore_trace.h"
+#include "dhl_trace.h"
+
+typedef enum
+{
+    USBCORE_UNIQUE_CODE_CLASS_START = 0,
+    USBCORE_UNIQUE_CODE_CLASS_RNDIS,
+    USBCORE_UNIQUE_CODE_CLASS_CDCACM,
+    USBCORE_UNIQUE_CODE_CLASS_ADB,
+    USBCORE_UNIQUE_CODE_CLASS_MSE,
+    USBCORE_UNIQUE_CODE_CLASS_ECM,
+    USBCORE_UNIQUE_CODE_CLASS_MBIM,
+    USBCORE_UNIQUE_CODE_CLASS_NUM
+}usbcore_unique_code_class_module;
+
+#define USBCORE_LOC_ASSERT_UNIQUE_CODE_BASE 0xA5200000
+typedef enum
+{
+    USBCORE_LOC_UNQIUE_CODE_START = USBCORE_LOC_ASSERT_UNIQUE_CODE_BASE,
+    USBCORE_LOC_SEND_OVER_CCCI_FAIL,
+    USBCORE_LOC_SEND_OVER_CCCI_TIMEOUT,
+    USBCORE_LOC_READ_OVER_CCCI_FAIL,
+    USBCORE_LOC_AP_RESPONSE_TIMEOUT,
+    USBCORE_LOC_AP_SET_STALL_INVALID_EP,
+    USBCORE_LOC_DUAL_OWNER_TIMER_INIT_FAIL,
+    USBCORE_LOC_INIT_CCCI_CHANNEL_FAIL_1,
+    USBCORE_LOC_INIT_CCCI_CHANNEL_FAIL_2,
+    USBCORE_LOC_INIT_CCCI_CHANNEL_FAIL_3,
+    USBCORE_LOC_DUALIPC_INVALID_PARAMETER,   
+    USBCORE_LOC_CCCI_NO_SUPPORT_RUNTIME_FEATURE,
+    USBCORE_LOC_DRV_NOTIFY_INVALID_EVENT,
+    USBCORE_LOC_POLLED_RX_NULL_GPD,
+    USBCORE_LOC_QUERY_QUE_DEVICE_NOT_REGISTER,    
+    USBCORE_LOC_QUERY_QUE_OVERSIZE_QUE_NUMBER,    
+    USBCORE_LOC_QUERY_QUE_CLASS_ID_NOT_MATCH,  //0xA5200010   
+    USBCORE_LOC_REGISTER_CLASS_NOT_INITIALIZE,
+    USBCORE_LOC_DEREGISTER_CLASS_NOT_REGISTERED,    
+    USBCORE_LOC_SUBMIT_CTRL_REQ_CLASS_NOT_REGISTERED,
+    USBCORE_LOC_NO_ABILITY_TO_REMOTE_WK,     
+    USBCORE_LOC_DEVICE_SET_CONFIG_FUNC_NULL,    
+    USBCORE_LOC_DEVICE_RX_COMPLETE_FUNC_NULL,    
+    USBCORE_LOC_TASK_INVALID_ITEM,
+    USBCORE_LOC_TASK_QUE_FULL,
+    USBCORE_LOC_GET_MODE_LID_INFO_FOR_ENUM_FAIL,
+    USBCORE_LOC_GET_MODE_LID_INFO_FOR_SET_FAIL,
+    USBCORE_LOC_GET_MODE_LID_INFO_FOR_AT_GET_FAIL,
+    USBCORE_LOC_GET_MODE_LID_VALUE_FAIL,
+    USBCORE_LOC_GET_EMEI_LID_INFO_FAIL,
+    USBCORE_LOC_GET_EMEI_LID_VALUE_FAIL,   
+    USBCORE_LOC_GET_SN_LID_INFO_FOR_ENUM_FAIL,
+    USBCORE_LOC_GET_SN_LID_INFO_FOR_SET_FAIL, //0xA5200020
+    USBCORE_LOC_GET_SN_LID_INFO_FOR_AT_GET_FAIL,
+    USBCORE_LOC_GET_STATUS_EP_STATUS_INVALID,
+    USBCORE_LOC_GET_STATUS_INVALID_RECIP,
+    USBCORE_LOC_MODIFY_CONFIG_DESC_OVERSIZE_FOR_U3_EP_COMP,
+    USBCORE_LOC_MODIFY_CONFIG_DESC_OVERSIZE,
+    USBCORE_LOC_ITEMS_NUM
+}usbcore_assert_loc_e;
+
+#endif  /* _USBCORE_DEBUG_H */
+
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_dual_owner.h b/mcu/middleware/hif/usbcore/include/usbcore_dual_owner.h
new file mode 100644
index 0000000..f84b29d
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_dual_owner.h
@@ -0,0 +1,152 @@
+/*!
+ *  @file usbcore_dual_owner.h
+ *  @author Yuhao Ye <yuhao.ye@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE TYPE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main definitions of usbcore
+ */
+
+#ifndef _DUAL_USB_OWNER_H
+#define _DUAL_USB_OWNER_H
+
+#include "kal_public_api.h"
+#include "usbc_custom.h"
+#include "usbcore_common.h"
+#include "nccci_if.h"
+
+#define USB_CLASS_MAX_IF_NUM 4
+#define USB_IF_MAX_EP_NUM 4
+#define USB_DEVICE_MAX_IF_NUM 16
+#define USB_MAX_AP_CLASS_DEVICE 8
+#define MSG_ID_USB_DUAL_OWNER_MSG_RECEIVE 1
+#define USB_DUAL_OWNER_WRITE_DONE_MAX_TICK  2000
+
+typedef enum{
+    APUBS_SETUP_RSP_IDLE = 0,
+    APUBS_SETUP_RSP_INIT,
+    APUSB_SETUP_RSP_SUCCESS,
+    APUSB_SETUP_RSP_FAIL,
+    APUSB_SETUP_RSP_DATA,
+    APUSB_SETUP_RSP_STALL,
+    APUSB_SETUP_RSP_TIMEOUT,
+    APUSB_SETUP_RSP_NUM,
+}apusb_setup_rsp_e;
+
+typedef enum{
+    APUSB_MSG_ID_UNKNOWN = 0,
+    APUSB_RSP_STATUS_SUCCESS,
+    APUSB_RSP_STATUS_STALL,
+    APUSB_RSP_SEND_DATA,
+    APUSB_NOTIFY_EVT_REMOTE_WAKEUP,
+    APUSB_NOTIFY_EVT_EP_HALT,    
+    APUSB_NOTIFY_EVT_RESET_DONE,
+    APUSB_NOTIFY_EVT_SUSPEND_DONE,
+    APUSB_NOTIFY_EVT_ATTACHED_DONE,
+    APUSB_MSG_ID_NUM
+}apusb_msg_id_e;
+
+typedef enum  {
+    NOTIFY_MSG_ID_UNKNOWN = 0,
+    NOTIFY_EVT_ATTACHED,
+    NOTIFY_EVT_DETACHED,
+    NOTIFY_EVT_SUSPEND,
+    NOTIFY_EVT_RESUME,
+    NOTIFY_EVT_RESET,
+    NOTIFY_EVT_CLASS_CTRL_REQ,
+    NOTIFY_EVT_FEATURE_SC,
+    NOTIFY_EVT_CTRL_DATA,
+    NOTIFY_EVT_FUNCTION_RESUME,    
+    NOTIFY_EVT_SUSPENDED,
+    NOTIFY_EVT_IP_PWRDOWN,
+    NOTIFY_MSG_ID_NUM
+} mdusb_msg_id_e;
+
+typedef enum{
+    USB_CLASS_TYPE_UNKNOWN = 0,
+    USB_CLASS_TYPE_CDC_ACM1,
+    USB_CLASS_TYPE_CDC_ACM2,
+    USB_CLASS_TYPE_CDC_ACM3,    
+    USB_CLASS_TYPE_ADB,
+    USB_CLASS_TYPE_MS,
+    USB_CLASS_TYPE_NUM
+}dual_usb_owner_class_type_e;
+
+typedef struct
+{
+    kal_uint8 endpoint_num;
+    kal_uint8 endpoint_direct;
+}apusb_ep_info_s;
+
+/*msg struct send to AP over CCCI*/
+typedef struct{
+    mdusb_msg_id_e msg_type;
+    kal_uint32 msg_length;
+}dual_usb_owner_msg_hdr_s;
+
+typedef struct{
+    dual_usb_owner_msg_hdr_s msg_hdr;
+    char  msg_data[CCCI_PAYLOAD_SIZE];
+}dual_usb_owner_msg_s;
+
+typedef struct{    
+    kal_uint32 class_device_id;
+    kal_uint32 endpoint_address;
+    hifusb_usb_xfer_type_e ep_type;
+    kal_uint32 maxpacketsize;
+}endpoint_info_s;
+
+typedef struct{
+    kal_uint32 interface_id;
+    usbc_interface_type_e interface_type;
+}interface_info_s;
+
+typedef struct{
+    kal_uint32 class_device_id;
+    dual_usb_owner_class_type_e class_device_type;
+    kal_uint32 total_interface_num;
+    interface_info_s if_info[USB_CLASS_MAX_IF_NUM];
+    endpoint_info_s ep_info[USB_IF_MAX_EP_NUM];
+}class_device_info_s;
+
+typedef struct{
+    kal_uint32 total_class_device;
+    class_device_info_s class_device_info[USB_MAX_AP_CLASS_DEVICE];
+}usb_deivce_info_s;
+
+void dual_owner_funciton_register();
+void dual_usb_owner_set_ap_rsp_timer();
+kal_bool dual_usb_owner_send_device_state(kal_uint32 type, kal_uint8 ext);
+#endif  // _DUAL_USB_OWNER_H
+
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_hif.h b/mcu/middleware/hif/usbcore/include/usbcore_hif.h
new file mode 100644
index 0000000..4c5d5e2
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_hif.h
@@ -0,0 +1,442 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   usbcore_hif.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   USB Core HIF interface shared between normal and exception modes.
+ *   One can tell the type of HIF interface from function name prefix:
+ *      (1) usbc_normal_hif_xxx(): implementation for normal mode HIF.
+ *      (2) usbc_core_xxx(): shared between normal mode and exception mode HIF.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#ifndef _USBCORE_HIF_H
+#define _USBCORE_HIF_H
+
+#include "hif_usb.h"
+#include "usbcore_main.h"
+#include "usbcore_debug.h"
+
+typedef kal_bool (*USBC_INDICATE_CONTROL_SETUP_PACKET)(kal_uint8 intf_idx, usbc_setup_packet_t *packet);
+typedef void (*USBC_INDICATE_CONTROL_COMPLETE)(kal_uint8 intf_idx);
+typedef void (*USBC_INDICATE_ALTERNATE_SETTING)(kal_uint8 intf_idx, kal_uint8 alternate_setting);
+typedef void (*USBC_INDICATE_STALL)(kal_bool is_tx, kal_uint8 queue_idx, kal_bool stall);
+typedef kal_bool (*USBC_SET_CONTROL_REQUEST)(kal_uint8* buffer, kal_uint32 length, usbc_control_request_type_e type);
+typedef kal_bool (*USBC_SET_PROPERTY)(hifusb_property_t *p_property);
+typedef kal_bool (*USBC_SET_USB_ADDRESS)(kal_uint8 address);
+typedef kal_bool (*USBC_SET_USB_CONFIGURATION)(kal_uint8 configuration);
+typedef void (*USBC_SET_STALL)(kal_bool is_tx, kal_uint8 nEnd);
+typedef void (*USBC_RST_EP)(kal_bool is_tx, kal_uint8 nEnd);
+typedef void (*USBC_CLEAR_STALL)(kal_bool is_tx, kal_uint8 nEnd);
+typedef kal_bool (*USBC_SET_USB_TESTMODE)(hifusb_test_mode_e testmode);
+typedef void (*USBC_SET_SS_DEV_INIT_U1_EN)(kal_bool);
+typedef void (*USBC_SET_SS_DEV_INIT_U2_EN)(kal_bool);
+typedef void (*USBC_SET_USBHIF_ADDRESS)(kal_uint8);
+typedef void (*USBC_SET_UFBHIF_CONFIGURATION)(kal_uint8);
+typedef kal_bool (*USBC_SET_USBHIF_CONNECT)(void);
+typedef kal_bool (*USBC_SET_USBHIF_DISCONNECT)(void);
+typedef kal_bool (*USBC_SET_USBHIFQ_GPD)(hif_queue_type_e, kal_uint8, qbm_gpd*, qbm_gpd*);
+typedef kal_uint32 (*USBC_POLL_USBHIFQ_GPD)(hif_deq_info_t deq_info, void **first_gpd, void **last_gpd);
+typedef kal_bool (*USBC_CHECK_USBHIFQ_EMPTY)(hif_queue_type_e core_queue_hif_type, kal_uint8 q_num);
+typedef kal_uint32 (*USBC_FLUSH_USBHIFQ_GPD)(hif_queue_type_e, kal_uint8, hif_flush_type_e, void**, void**);
+typedef kal_uint32 (*USBC_FLUSH_SW_USBHIFQ_GPD)(hif_queue_type_e, kal_uint8, hif_flush_type_e, void**, void**);
+typedef kal_bool (*USBC_CHK_NEWPKT)(kal_bool, kal_uint8);
+typedef void (*USBC_START_DATAQ)(kal_bool, kal_uint8);
+typedef void (*USBC_POWER_DOWN)(void);
+typedef void (*USBC_SET_CLOCK_CG)(kal_bool);
+typedef void (*USBC_MASK_WAKEUP_EVENT)(kal_bool);
+typedef void (*USBC_MASK_INTR)(kal_bool);
+
+typedef void (*USBC_DUAL_OWNER_OPERATION)(void);
+typedef kal_bool (*USBC_DUAL_OWNER_NOTIFY_EVENT)(kal_uint32 type, kal_uint8 ext);
+
+/*------------------------------------------------------------------------------
+ * USB Core HIF interface shared between normal mode and exception mode.
+ *----------------------------------------------------------------------------*/
+/*!
+ *  @brief indicate the setup packet up to specified USB CLASS interface.
+ */
+extern USBC_INDICATE_CONTROL_SETUP_PACKET usbc_core_indicate_control_setup_packet;
+
+/*!
+ *  @brief indicate the complete complete to specified USB CLASS interface.
+ */
+extern USBC_INDICATE_CONTROL_COMPLETE usbc_core_indicate_control_complete;
+
+/*!
+ *  @brief indicate the alternate setting set by host to specified interface.
+ */
+extern USBC_INDICATE_ALTERNATE_SETTING usbc_core_indicate_alternate_setting;
+
+/*!
+ *  @brief indicate the alternate setting set by host to specified interface.
+ */
+extern USBC_INDICATE_STALL usbc_core_indicate_stall;
+
+/*!
+ *  @brief write or read control transfer data buffer and status to hif driver
+ */
+extern USBC_SET_CONTROL_REQUEST usbc_core_set_control_request;
+
+/*!
+ *  @brief set USB device and endpoint related settings to hif driver
+ */
+extern USBC_SET_PROPERTY usbc_core_set_property;
+
+/*!
+ *  @brief update USB address to hif driver
+ */
+extern USBC_SET_USB_ADDRESS usbc_core_set_usb_address;
+
+/*!
+ *  @brief set usb configuration to hif driver
+ */
+extern USBC_SET_USB_CONFIGURATION usbc_core_set_usb_configuration;
+
+/*!
+ *  @brief set endpoint stall to hif driver
+ */
+extern USBC_SET_STALL usbc_core_set_stall;
+
+/*!
+ *  @brief reset endpoint  to hif driver
+ */
+extern USBC_RST_EP usbc_core_rst_ep;
+/*!
+ *  @brief clear endpoint stall to hif driver
+ */
+extern USBC_CLEAR_STALL usbc_core_clear_stall;
+
+/*!
+ *  @brief set test mode to hif driver
+ */
+extern USBC_SET_USB_TESTMODE usbc_core_set_usb_testmode;
+
+/*!
+ *  @brief enable U1 to hif driver
+ */
+extern USBC_SET_SS_DEV_INIT_U1_EN usbc_core_set_ss_dev_init_u1_en;
+
+/*!
+ *  @brief enable U2 to hif driver
+ */
+extern USBC_SET_SS_DEV_INIT_U2_EN usbc_core_set_ss_dev_init_u2_en;
+
+/*!
+ * @brief HIF API for setting address
+ */
+extern USBC_SET_USBHIF_ADDRESS usbc_core_set_usbhif_address; 
+
+/*!
+ * @brief HIF API for setting configuration
+ */
+extern USBC_SET_UFBHIF_CONFIGURATION usbc_core_set_usbhif_configuration; 
+
+/*!
+ * @brief HIF API for attaching to USB IP driver
+ */
+extern USBC_SET_USBHIF_CONNECT usbc_core_set_usbhif_connect;
+
+/*!
+ * @brief HIF API for deattaching to USB IP driver
+ */
+extern USBC_SET_USBHIF_DISCONNECT usbc_core_set_usbhif_disconnect;
+ 
+
+/*!
+ * @brief HIF QBM API for submit GPDs to USB QMU
+ */
+extern USBC_SET_USBHIFQ_GPD usbc_core_set_usbhifq_gpd;
+
+/*!
+ * @breif HIF QMU API for polling GPDs
+ */
+extern USBC_POLL_USBHIFQ_GPD usbc_core_poll_hifusbq_qpd; 
+
+extern USBC_CHECK_USBHIFQ_EMPTY usbc_core_check_hifusbq_empty;
+
+extern USBC_FLUSH_USBHIFQ_GPD usbc_core_flush_hifusbq_gpd;
+
+extern USBC_FLUSH_SW_USBHIFQ_GPD usbc_core_flush_sw_hifusbq_gpd;
+
+extern USBC_CHK_NEWPKT usbc_core_check_new_packet;
+
+/*!
+ *  @brief Start ULQ/DLQ to hif driver
+ */
+extern USBC_START_DATAQ usbc_core_start_dataq;
+
+extern USBC_POWER_DOWN usbc_core_power_down;
+
+extern USBC_MASK_WAKEUP_EVENT usbc_core_mask_wakeup_event;
+
+extern USBC_SET_CLOCK_CG usbc_core_set_clock_cg;
+
+extern USBC_MASK_INTR usbc_core_mask_intr;
+
+/*!
+ *  @brief for USB dual owner function point
+ */
+extern USBC_DUAL_OWNER_OPERATION usbc_dual_owner_init;
+extern USBC_DUAL_OWNER_OPERATION usbc_dual_owner_ilm_handle;
+extern USBC_DUAL_OWNER_OPERATION usbc_dual_owner_class_ctrl_request;
+extern USBC_DUAL_OWNER_OPERATION usbc_dual_owner_class_ctrl_complete;
+extern USBC_DUAL_OWNER_OPERATION usbc_dual_owner_send_feature_request;
+extern USBC_DUAL_OWNER_NOTIFY_EVENT usbc_dual_owner_notify_event;
+
+#ifdef __USBCORE_DEBUG__
+/*!
+ *  @brief dump gpd content for debug purpose
+ */
+void usbc_core_dump_gpd_list(void* first_gpd, void* last_gpd);
+#endif
+
+/*!
+ *  @brief fill up HIF IP dependent settings to hif driver
+ */
+kal_bool usbc_core_set_hif_configuration(void);
+
+/*!
+ *  @brief USB Core internal implementation to dispatch setup packet
+ *  @param  pUsbCore USB Core context
+ *  @param  p_setup setup packet to parse
+ *  @return KAL_TRUE if it has been handled in this function;
+ *          KAL_FALSE if it will be handled in task context later.
+ */
+kal_bool usbc_core_dispatch_control_setup_packet(usbc_core_t *pUsbCore, hifusb_setup_packet_t *p_setup);
+
+/*!
+ *  @brief USB Core internal implementation for control transfer complete post-processing 
+ *  @param  pUsbCore USB Core context
+ */
+void usbc_core_notify_control_complete(usbc_core_t *pUsbCore);
+
+/*!
+ *  @brief Change USB speed and related descriptors.
+ *  @param  pUsbCore USB Core context
+ */
+void usbc_core_speed_change(usbc_core_t *pUsbCore, usbc_usb_speed_e speed);
+
+
+/*------------------------------------------------------------------------------
+ * USB Core internal implementation for HIF normal mode.
+ *----------------------------------------------------------------------------*/
+/*!
+ *  @brief ask hif driver to initiate
+ */
+kal_bool usbc_normal_hif_init(void);
+
+/*!
+ *  @brief ask hif driver to shutdown
+ */
+kal_bool usbc_normal_hif_shutdown(void);
+
+/*!
+ *  @brief ask hif driver to connect
+ */
+kal_bool usbc_normal_hif_connect(void);
+
+/*!
+ *  @brief ask hif driver to disconnect
+ */
+kal_bool usbc_normal_hif_disconnect(void);
+
+/*!
+ *  @brief ask hif driver to remote wakeup
+ */
+kal_bool usbc_normal_hif_remote_wakeup(void);
+/*!
+ *  @brief ask hif driver to send function wakeup notification
+  */
+kal_bool usbc_normal_hif_ss_wk_notify(kal_uint8 nInterface);
+
+/*!
+ *  @brief poll hif each queue to see if any data available
+ */
+void usbc_normal_hif_poll_queue(void);
+
+/*!
+ *  @brief Process indications queued in USBCORE task context
+ */
+void usbc_normal_hif_process_indications(void);
+
+/*!
+ *  @brief Fill up HIF function pointers with nomral mode HIF implementation
+ */
+void usbc_normal_hif_factory(void);
+
+/*!
+ *  @brief Fill up HIF function pointers with meta mode HIF implementation
+ */
+void usbc_meta_hif_factory(void);
+
+/*!
+ *  @breif Fill up HIF function pointers with USB suspended HIF implementation
+ */
+void usbc_suspended_hif_factory(void);
+
+#ifdef ATEST_SYS_USBCORE
+/*!
+ *  @brief Fill up HIF function pointers with dummy HIF implementation
+ */
+void usbc_fake_hif_factory(void);
+#endif
+
+void usbc_direct_hif_factory(void);
+
+/*!
+ *  @brief Emulate HIFUSB_NOTIFY_EVT_RESET, SetAddress, and SetConfiguration in META mode
+ */
+void usbc_normal_hif_meta_attach(void);
+
+/*!
+ *  @brief Check for reusing META COM
+ */
+kal_bool usbc_normal_hif_is_meta_reused(void);
+
+/*!
+ *  @brief Restore Buffered GPDs to hardware
+ */
+kal_bool usbc_normal_hif_restore_gpd_pwrsave(void);
+
+/*!
+ *  @brief set pwr flag
+ */
+void usbc_normal_hif_set_pwr_flag(kal_bool flag);
+
+/*!
+ *  @brief print GPD length info
+ */
+void usbc_core_trace_gpd_info(qbm_gpd* first_gpd, qbm_gpd* last_gpd, kal_uint8 q_no, kal_bool isTx, kal_bool flag);
+
+/*!
+ *  @brief clear enum request record
+ */
+void usbc_core_clear_enum_record();
+
+usbcore_unique_code_class_module usbcore_classid_to_module(kal_uint8 class_device_id);
+#endif  // _USBCORE_HIF_H
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_ind_q.h b/mcu/middleware/hif/usbcore/include/usbcore_ind_q.h
new file mode 100644
index 0000000..2b6aeab
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_ind_q.h
@@ -0,0 +1,142 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   usbcore_ind_q.h
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   USB Core indication queue operations.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#ifndef _USBCORE_IND_Q_H
+#define _USBCORE_IND_Q_H
+
+#define USBC_IND_CTRL_SETUP       0   /**< Control transfer setup packet indication. */
+#define USBC_IND_CTRL_CMPLT       1   /**< Control transfer data phase complete. */
+#define USBC_IND_DEV_EVENT        2   /**< USB device event indication. */
+#define USBC_IND_SPEED_CHANGE     3   /**< USB speed changed notification. */
+#define USBC_IND_ALT_SETTING      4   /**< USB interface alternate setting set by host. */
+#define USBC_IND_PIPE_STALL       5   /**< USB pipe HALT state is set or cleared by host. */
+#define USBC_IND_MODE_SWITCH      6   /**< USB mode switch indication */
+#define USBC_IND_FUNC_EVENT       7   /**< USB function event indication. */
+#define USBC_IND_SET_CONFIG       8   /**< USB Set configuration */
+#define USBC_IND_UFPM_POLL        9   /**< USB direct poll queue */
+#define USBC_IND_IP_PWRDOWN        10   /**< USB direct poll queue */
+
+
+/*!
+ *  @brief Information to indication up to USB Class.
+ */
+typedef struct _usbc_ind {
+    kal_uint8       ext:4; /**< Extended data specific to each type of indication. */
+    kal_uint8       type:4; /**< Type of indication, see USBC_IND_XXX for details. */
+    kal_uint8       data; /**< Data specific to each type of indication. */
+} usbc_ind_t;
+
+
+/*!
+ *  @brief Empty the USB queue of indication
+ */
+void usbc_empty_ind_queue(void);
+
+/*!
+ *  @brief Copy and enqueue an indication object.
+ *  @param indication  [IN] Pointer to the indication object to enqueue.
+ */
+void usbc_enqueue_ind(usbc_ind_t *indication);
+
+/*!
+ *  @brief Dequeue an indication object if available.
+ *  @param indication  [OUT] Caller allocated space for the indication object dequeued.
+ *  @return KAL_TURE if there's an indicaiton object dequeue; KAL_FALSE otherwise.
+ */
+kal_bool usbc_dequeue_ind(usbc_ind_t *indication);
+
+void usbc_empty_ind_queue();
+
+kal_bool usbc_ind_queue_spinlock_init();
+
+kal_bool usbc_queue_empty_check();
+#endif
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_main.h b/mcu/middleware/hif/usbcore/include/usbcore_main.h
new file mode 100644
index 0000000..98d0de4
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_main.h
@@ -0,0 +1,666 @@
+/*!
+ *  @file usbcore_main.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main definitions of usbcore
+ */
+
+#ifndef _USBCORE_MAIN_H
+#define _USBCORE_MAIN_H
+
+#include "usbcore_common.h"
+#include "hif_usb.h"
+#include "usbcore_usbstd.h"
+#include "usbcore_class_device.h"
+#include "hifusb_qmu.h"
+#include "ubm_export.h"
+
+//#define __USBCORE_DEBUG__
+
+#ifdef __USBCORE_DEBUG__
+#define usbc_core_printf        kal_printf
+#else
+#if defined(__MTK_TARGET__)
+#define usbc_core_printf(fmt, args...)
+#else
+#define usbc_core_printf(fmt, ...)
+#endif
+#endif
+
+#define __USBCORE_CHECK__
+#ifdef __USBCORE_CHECK__
+    #define USBC_IS_IN_EXCEPTION_MODE() \
+                ( USBC_OP_MODE_EXCEPTION == usbc_get_op_mode() )
+    
+    #define USBC_EXCEPTION_MODE_CHECK() \
+                ASSERT( USBC_IS_IN_EXCEPTION_MODE() )
+    
+    #define USBC_NON_EXCEPTION_MODE_CHECK() \
+                ASSERT( !USBC_IS_IN_EXCEPTION_MODE() )
+    
+    #define USBC_CORE_INSTANCE_CHECK(_inst) \
+                ASSERT( NULL != (_inst))
+#else
+    #define USBC_IS_IN_EXCEPTION_MODE() 
+    
+    #define USBC_EXCEPTION_MODE_CHECK() 
+    
+    #define USBC_NON_EXCEPTION_MODE_CHECK()
+    
+    #define USBC_CORE_INSTANCE_CHECK(_inst) 
+#endif
+
+#define USBC_CLASS_DEVICE_CONTEXT_CHECK() \
+            ASSERT(!kal_if_hisr())
+
+#define USBC_QUEUE_GPD_TAKE_MUTEX(_s)   \
+            kal_take_enh_mutex(_s)
+
+#define USBC_QUEUE_GPD_GIVE_MUTEX(_s)   \
+            kal_give_enh_mutex(_s)
+
+/*!
+ *  @brief MAX_USBCORE_DEVICE_NUM defines the maximum value of class
+ *         devices usbcore can handle
+ */
+#define MAX_USBCORE_DEVICE_NUM                      16
+
+/*!
+ *  @brief KAL interval for resending function remote wakeup notification
+ *         The min. interval is 2500ms to notify the host.
+ */
+#ifdef __HAPS_FPGA_CLK_ADJUST__
+#define USBC_WK_NOTIFY_CHECK_MS                 (25 * KAL_TICKS_100_MSEC_REAL)
+#else
+#define USBC_WK_NOTIFY_CHECK_MS                 (25 * KAL_TICKS_100_MSEC)
+#endif
+
+/*!
+ *  @brief KAL ticks duration for checking device resuming
+ */
+#define USBC_DEV_RESUME_DURATION_TICK               2
+
+/*!
+ *  @brief KAL ticks duration for checking AP response
+ */
+#define USBC_DEV_DURATION_AP_RSP_TICK               1
+
+/*!
+ *  @brief KAL ticks duration for checking CCCI DL done
+ */
+#define USBC_DEV_DURATION_CCCI_DL_DONE_TICK              1
+
+/*!
+ *  @brief KAL event scheduler for function wakreup notification tiemout
+ */
+#define USBC_WK_NOTIFY_INDEX                        1
+
+/*!
+ * @breif Warpper for KAL enhanced mutex
+ */
+#define USBC_CLASS_REMOTE_WK_LOCK(_s)   kal_take_enh_mutex(_s)
+#define USBC_CLASS_REMOTE_WK_UNLOCK(_s) kal_give_enh_mutex(_s)
+
+#define USBC_CLASS_COMMON_LOCK(_s)   kal_take_enh_mutex(_s)
+#define USBC_CLASS_COMMON_UNLOCK(_s) kal_give_enh_mutex(_s)
+
+#define USBC_CLASS_COMMON_SPIN_LOCK(_s)  kal_take_spinlock(_s, KAL_INFINITE_WAIT)
+#define USBC_CLASS_COMMON_SPIN_UNLOCK(_s)  kal_give_spinlock(_s)
+
+#define USBC_POLLED_CHECK_DURATION                  25
+#define USBC_POLLED_CHECK_SHOW_ONLY_NO_DATA         1
+
+#define USBC_POLLED_CHECK_DURATION_TIME_MAX   10000  //10ms
+/*!
+ *  @brief timeout time for AP rsp request.
+ */
+#define USBC_AP_RSP_CHECK_MS                 (50 * KAL_TICKS_100_MSEC_REAL)
+#define USBC_AP_SUSPEND_DISABLE_CG_TIMEOUT 5000000
+#define USBC_AP_EVT_DONE_TIMEOUT 1500000
+
+#define USBC_READ_FILE_PATH_MAX_LENGTH 128
+#define USBC_READ_FILE_DATA_MAX_LENGTH 128
+typedef enum{
+    MSD_DISABLE = 0,
+    MSD_ENABLE,
+    MSD_INVALID,
+}usbc_ms_enable_e;
+
+
+/*!
+ *  @brief USBCORE ATCMD handle function table sturture
+ */
+typedef kal_bool (*USBC_HANDLE_ATCMD_FUNC)(void *data_in, void *data_out);
+typedef struct
+{
+    char cmd_type[32];
+    USBC_HANDLE_ATCMD_FUNC handle_set_func;    
+    USBC_HANDLE_ATCMD_FUNC handle_get_func;
+}usbc_atcmd_hd_t;
+/*!
+ * @brief configruation read from HMU.
+ */
+typedef struct _usbc_hmu_info {
+    /*!
+     *  @brief USB enumeration tiemout in unit of ms.
+     */
+    kal_uint32                          enum_timeout; 
+    /*!
+     *  @brief Tx transfer tiemout in unit of ms.
+     */
+    kal_uint32                          tx_timeout; 
+} usbc_hmu_info_t;
+
+/*
+ *  @brief USB descriptors compiled.
+ */
+typedef struct _usbc_descriptors_t {
+    kal_uint8                   device[USBC_DEVICE_DESC_SIZE];
+    kal_uint8                   configuration[MAX_USBCORE_CONFIG_NUM][USBC_MAX_CONF_SIZE];
+} usbc_descriptors_t;
+
+
+/*!
+ *  @brief usbc_core_class_device_t describe class device information maintain
+ *         within usbcore
+ */
+typedef struct _usbc_core_class_device_t {
+    /*!
+     *  @brief class type of this device
+     */
+    usb_class_type_e                    class_type;
+    /*!
+     *  @brief current state of this device
+     */
+    usbc_core_class_device_state_e      state;
+    /*!
+     *  @brief current class device owner
+     */
+    usb_class_owner_e owner;
+    /*!
+     *  @brief total pipes of this device
+     */
+    kal_uint8                           total_pipes;
+    kal_uint8                           rsvd[1];
+    /*!
+     *  @brief returning device instance to class driver
+     */
+    usbc_class_device_instance_t        device_instance;
+    /*!
+     *  @brief callback function while usb state changed
+     */
+    void                                (*notify_usb_state)(kal_uint8 class_device_id, usbc_usb_state_e state);
+    /*!
+     *  @brief callback function while usb speed changed
+     */
+    void                                (*notify_usb_speed)(kal_uint8 class_device, usbc_usb_speed_e speed);
+    /*!
+     *  @brief the status of the class device
+     */
+    kal_bool                            is_func_suspend;
+    /*!
+     *  @brief callback function while set or clear function remote wakeup ability
+     */
+     void                               (*notify_func_wk_ability)(kal_uint8 class_device_id, kal_bool ability);
+    /*!
+     *  @brief callback function to known the class device status
+     */
+     kal_uint16                         (*query_func_wk_status)(kal_uint8 class_device_id);
+} usbc_core_class_device_t;
+
+typedef struct _usbc_core_xit_meta_t {
+    kal_bool xit2meta_retry;
+    kal_uint32 remain_num;
+    kal_uint32 startIdx;
+    kal_uint32 endIdx;
+} usbc_core_xit_meta_t;
+
+/*!
+ *  @brief usbc_core_t describe main structure of usbcore
+ */
+typedef struct _usbc_core {
+    /*!
+     * @brief HMU events indication that USBCORE task is going to wait
+     */
+    kal_uint32                          hmu_indication;
+
+    usb_mode_e                          mode;
+    kal_bool                            is_mode_switch;
+
+    /*!
+     *  @brief current usb speed
+     */
+    usbc_usb_speed_e                    speed;
+    /*!
+     *  @brief current usb state
+     */
+    usbc_usb_state_e                    state;
+    usbc_usb_state_e                    state_in_hisr;
+    /*!
+     *  @brief KAL_TRUE if the setup_packet will be handled by USBCLASS; KAL_FALSE if it has been handled by USBCORE.
+     */
+    kal_bool                            setup_indicated;
+    kal_uint8                           rsvd0[1];
+    /*!
+     *  @brief current setup packet
+     */
+    usbc_setup_packet_t                 setup_packet;
+    /*!
+     *  @brief the state machine of setup handle
+     */
+    usbc_setup_packet_sm_e     setup_status;
+    /*!
+     *  @brief the spinlock for setup pakcet protect
+     */
+    kal_spinlockid setup_packet_spinlock;
+    /*!
+     *  @brief control request buffer to send or receive
+     */
+    kal_uint8                           control_request_buffer[MAX_USBCORE_CONTROL_REQUEST_BUFFER_SIZE];
+
+    /*!
+     *  @brief current device qualifier descriptor
+     */
+    usbc_device_qualifier_descriptor_t  device_qualifier_descriptor;
+
+    /* device parameter got from usb custom */
+	usb_dev_param_t*                    dev_param;
+
+    /* get the ability of morhping from NVRAM */
+    kal_bool                            morphing_enable;
+
+    /* Resource */
+    kal_uint8                           resource_interface_number[MAX_USBCORE_CONFIG_NUM];
+    kal_uint8                           resource_string_number;
+    kal_uint8                           resource_iad_number[MAX_USBCORE_CONFIG_NUM];
+    kal_uint8                           resource_ep_tx_number[MAX_USBCORE_CONFIG_NUM];
+    kal_uint8                           resource_ep_rx_number[MAX_USBCORE_CONFIG_NUM];
+    usbc_interface_info_t               if_info[MAX_USBCORE_CONFIG_NUM][MAX_USBCORE_INTERFACE_NUM];
+    usbc_interface_association_descriptor_t   iad_descriptor[MAX_USBCORE_CONFIG_NUM][MAX_USBCORE_IAD_NUM];
+    usbc_endpoint_info_t                ep_tx_info[MAX_USBCORE_CONFIG_NUM][MAX_USBCORE_QUEUE_NUM];
+    usbc_endpoint_info_t                ep_rx_info[MAX_USBCORE_CONFIG_NUM][MAX_USBCORE_QUEUE_NUM];
+
+    /*!
+     *  @brief current string descriptor
+     */
+    usbc_string_descriptor_t*           string_descriptor[MAX_USBCORE_STRING_DESCRIPTOR_NUM];
+
+    /*!
+     *  @brief current usb address in Set Address Request
+     */
+    kal_uint8                           usb_address;
+    /*!
+     *  @brief current selected configuration in Set Configuration Request
+     */
+    kal_uint8                           usb_configuration;
+
+    /*!
+     *  @brief total configurated class devices
+     */
+    kal_uint8                           total_class_devices;
+    /*!
+     *  @brief total configurated class interfaces
+     */
+    kal_uint8                           total_class_interfaces;
+    /*!
+     *  @brief total configurated transmit queues
+     */
+    kal_uint8                           total_tx_queues;
+    /*!
+     *  @brief total configurated receive queues
+     */
+    kal_uint8                           total_rx_queues;
+
+    /*!
+     *  @brief class device information
+     */
+    usbc_core_class_device_t            class_device[MAX_USBCORE_DEVICE_NUM];
+
+    /*!
+     *  @brief class interface information
+     */
+    usbc_core_class_interface_t         class_interface[MAX_USBCORE_INTERFACE_NUM];
+    /*!
+     *  @brief transmit queue information
+     */
+    usbc_core_queue_t                   tx_queue[MAX_USBCORE_QUEUE_NUM];
+    /*!
+     *  @brief receive queue information
+     */
+    usbc_core_queue_t                   rx_queue[MAX_USBCORE_QUEUE_NUM];
+
+    /*!
+     *  @brief USB descriptors compiled.
+     */
+    usbc_descriptors_t                  descriptors;
+
+    kal_bool                            morph_active;
+
+    /*!
+     *  @brief current status of device
+     */
+    kal_bool                            is_device_u1_enable;
+    kal_bool                            is_device_u2_enable;
+    kal_bool                            is_device_ltm_enable;
+
+    /*!
+     *  @brief MUTEX for remote wakeup
+     */
+    kal_enhmutexid                      usbc_class_remote_wk_mutex;
+
+    /*!
+     * @brief keep the information for device suspend after function suspend
+     */
+    event_scheduler*                    usbc_es_wk_notify_g;
+    kal_bool                            func_notify_list[MAX_USBCORE_DEVICE_NUM];
+    eventid                             wk_eventid;
+    kal_enhmutexid                      usbc_class_renotify_mutex;
+    kal_bool                            is_func_be_accessed[MAX_USBCORE_DEVICE_NUM];
+    kal_enhmutexid                      usbc_class_func_access_mutex;
+
+    /*!
+     *  @brief MUTEX for resume
+     */
+    kal_enhmutexid                      usbc_class_resume_mutex;
+
+    /*!
+     * @brief Check for META mode
+     */
+    kal_bool                            is_mode_meta;
+    kal_bool                            is_mode_meta_reused;
+
+    /*!
+     * @brief bMaxPower for USB 3.0 configuratyion
+     */
+    kal_uint8                           u3ConfMaxPower;
+
+    /*!
+     * @brief USB XIT queue status for META translation
+     */
+     usbc_core_xit_meta_t               rx_xit_meta[MAX_USBCORE_QUEUE_NUM];
+
+     kal_uint16                         usbc_txq_polled_mask;
+     kal_uint16                         usbc_rxq_polled_mask;
+     kal_uint16                         usbc_q_polled_duration;
+     
+     /*!
+      * @brief setup buffer for OUT request in AP owner port, send to AP over CCCI
+      */
+     kal_uint8                       ap_setup_buf[MAX_USBCORE_CONTROL_REQUEST_BUFFER_SIZE];  
+     kal_uint32                     ap_setup_buf_rx_expected_len;
+     
+     kal_timerid                    usbc_es_ap_rsp_timerid;
+    /*!
+    * @brief flag for waiting AP echo
+    */  
+    kal_bool                    ap_response_reset_evt_done;
+    kal_uint32                ap_response_evt_time;
+    kal_bool                    waiting_ap_clk_disable_flag;   
+    /*!
+  * @brief rx flush operation and submit spinlock
+  */  
+     kal_enhmutexid rx_submit_enhmuexid[MAX_USBCORE_QUEUE_NUM];         
+
+        /*!
+    * @brief flag for enable USB lowpower feature
+    */ 
+    kal_bool config_has_ap_port;
+    kal_bool usb_low_power_enable;
+    kal_bool usbc_wait_wakeup_event;
+    kal_timerid  usbc_ap_rsp_suspend_done_timerid;
+    kal_timerid  usbc_ap_rsp_attached_done_timerid;    
+} usbc_core_t;
+
+
+/*!
+ *  @brief  switch USBCORE operation mode.
+ *  @return current USBCORE operation mode, see usbc_op_mode_e for more information.
+ */
+usbc_op_mode_e usbc_get_op_mode(void);
+
+
+/*!
+ *  @brief  set USBCORE operation mode.
+ *  @param op_mode USBCORE operation mode to set, see usbc_op_mode_e for more information.
+ */
+void usbc_set_op_mode(usbc_op_mode_e op_mode);
+
+
+/*!
+ *  @brief  get instance of USBCORE module
+ *  @return pointer to usbc_core_t* instance if success, NULL if fail
+ */
+usbc_core_t *usbc_core_get_instance(void);
+
+
+/*!
+ *  @brief  get settings read from HMU
+ *  @return pointer the usbc_hmu_info_t object for these setting.
+ */
+usbc_hmu_info_t *usbc_core_get_hmu_info(void);
+
+
+/*!
+ *  @brief force returning to non-register state
+ */
+void usbc_core_clear_register(void);
+
+
+/*!
+ *  @brief notify all existed class drivers that usb state is changed to
+ *         attaching
+ */
+void usbc_core_notify_state_attaching(void);
+
+
+/*!
+ *  @brief notify all existed class drivers that usb state is changed to
+ *         attached
+ */
+void usbc_core_notify_state_attached(void);
+
+
+/*!
+ *  @brief notify all existed class drivers that usb state is changed to
+ *         detaching
+ */
+void usbc_core_notify_state_detaching(void);
+
+
+/*!
+ *  @brief notify all existed class drivers that usb state is changed to
+ *         suspending
+ */
+void usbc_core_notify_state_suspending(void);
+
+
+/*!
+ *  @brief notify all existed class drivers that usb state is changed to
+ *         resume
+ */
+void usbc_core_notify_state_resume(void);
+
+
+/*!
+ *  @brief notify all existed class drivers that usb state is changed to
+ *         reset
+ */
+void usbc_core_notify_state_reset(void);
+
+
+/*!
+ *  @brief notify all existed class drivers that usb speed is changed
+ *  @param  speed new USB link speed
+ */
+void usbc_core_notify_speed_change(usbc_usb_speed_e speed);
+
+
+/*!
+ *  @brief notify the interface that its alternate setting is set by host
+ *  @param  intf_idx indext to the interface
+ *  @param  alternate_setting alternate setting set by host
+ */
+void usbc_core_notify_alternate_setting(kal_uint8 intf_idx, kal_uint8 alternate_setting);
+
+
+/*!
+ *  @brief notify the endpoint that its HALT state is changed by host
+ *  @param  is_tx KAL_TURE for OUT endpoint; KAL_FALSE for IN endpoint
+ *  @param  queue_idx internal queue index of the endpoint
+ *  @param  stall KAL_TRUE if it's been set STALL; KAL_FALSE if it's been cleared STALL
+ */
+void usbc_core_notify_stall(kal_bool is_tx, kal_uint8 queue_idx, kal_bool stall);
+
+
+/*!
+ *  @brief handle usb standard request
+ */
+kal_bool usbc_core_handle_standard_request(void);
+
+/*!
+ *  @brief handle usb vendor request
+ */
+void usbc_core_handle_vendor_request(void);
+
+
+/*!
+ *  @brief  Modify descriptors according to current USB speed.
+ *  @param  pUsbCore USB Core context
+ *  @param  speed Current USB speed
+ */
+void usbc_core_descriptors_speed_change(usbc_core_t *pUsbCore, usbc_usb_speed_e speed);
+
+
+/*!
+ *  @brief  Internal implementaion of usb class device registration
+ *  @param class_device_id  [IN] USB class device instance id
+ *  @param  pUsbCore USB Core context
+ *  @param  device_info class device information used to register
+ *  @return new instance of usb class device if success, NULL if fail
+ */
+usbc_class_device_instance_t *usbc_core_device_register(kal_uint8 class_device_id, usbc_core_t *pUsbCore, usbc_class_device_info_t *device_info);
+
+
+/*!
+ *  @brief  Query information about the queue of an USB calss device instance.
+ *  @param class_device_id  [IN] USB class device instance id
+ *  @param queue_no         [IN] Queue number to query
+ *  @param queue            [OUT] Caller allocated space for a pointer to the queue object. Its value is invalid if no matched queue found.
+ *  @param queue_type       [OUT] Type of the queue. Its value is invalid if no matched queue found.
+ *  @return KAL_TURE if matched queue found; KAL_FALSE otherwise.
+ */
+kal_bool usbc_core_get_queue_info(kal_uint8 class_device_id, kal_uint8 queue_no, usbc_core_queue_t **queue, hif_queue_type_e *queue_type);
+
+
+/*!
+ *  @brief clear device status and function status to default setting
+ */
+void usbc_core_clear_status(void);
+
+
+/*!
+ *  @brief check if the given interface is the first one of any functions
+ */
+kal_bool usbc_core_is_1st_interface(kal_uint8 idx);
+
+
+/*!
+ *  @brief get the first interface of the given function
+ */
+kal_uint8 usbc_class_device_get_1st_interface(kal_uint8 class_device_id);
+
+/*!
+ *  @brief Notify the USB state to specific USB classes
+ */
+void usbc_core_indicate_function_state(kal_uint8 class_device_id, usbc_usb_state_e state); 
+
+/*!
+ *  @brief Notify the requested class driver that usb state is changed to suspending
+ *  @param idx              [IN] USB class_device_id
+ */
+void usbc_core_notify_function_state_suspending(kal_uint8 class_device_id);
+
+
+/*!
+ *  @brief notify the requested class driver that usb state is changed to resume
+ *  @param idx              [IN] USB class_device_id
+ */
+void usbc_core_notify_function_state_resume(kal_uint8 class_device_id);
+
+
+/*!
+ *  @brief notify the requested class driver to enable or disable function remote wakeup
+ *  @param idx              [IN] USB class_device_id
+ *  @param ability          [IN] Enable or disable the function remote wakeup capability. KAL_TRUE for enable, and KAL_FALSE for disable.
+ */
+void usbc_core_notify_func_wk_ability(kal_uint8 class_device_id, kal_bool ability);
+
+
+/*!
+ *  @brief get the bitmap of functions that enable remote wakeup
+ *  @return the bit map of funtions that enable remote wakeup
+ */
+kal_uint16 usbc_core_get_function_remote_wk_list(void);
+
+/*!
+ *  @brief get the bitmap of functions that are suspended
+ *  @return the bit map of funtions that are suspended
+ */
+kal_uint16 usbc_core_get_function_suspend_list(void);
+
+/*!
+ *  @brief set IMEI as the serial number of USB device descriptor
+ */
+kal_bool usbc_core_set_serial_number(void);
+
+/*!
+ *  @brief set USB serial number from NVRAM
+ */
+kal_uint8 usbc_set_serial_number_for_internal();
+
+/*!
+ *  @brief USBCORE ATCMD handle fucntion
+ */
+kal_bool usbc_core_handle_set_serialnumber_atcmd(void *data_req, void *data_cnf);
+kal_bool usbc_core_handle_set_usb_mode_atcmd(void *data_req, void *data_cnf);
+kal_bool usbc_core_handle_get_serialnumber_atcmd(void *data_req, void *data_cnf);
+kal_bool usbc_core_handle_get_usb_mode_atcmd(void *data_req, void *data_cnf);
+kal_bool usbc_core_handle_powerdown_usb_atcmd(void *req, void *cnf);
+void usbc_core_check_low_power_enable();
+void usbc_core_check_mass_strorage_onoff();
+
+#endif  // _USBCORE_MAIN_H
+
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_mode.h b/mcu/middleware/hif/usbcore/include/usbcore_mode.h
new file mode 100644
index 0000000..5f8cef0
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_mode.h
@@ -0,0 +1,245 @@
+/*!
+ *  @file usbcore_mode.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides mode related definitions of usbcore
+ */
+
+#ifndef _USBCORE_MODE_H
+#define _USBCORE_MODE_H
+
+
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+
+/*!
+ *  @brief USBC_DEF_BCDDEV defines default bcd device
+ */
+#define USBC_DEF_BCDDEV                     0x0001
+
+
+/*!
+ *  @brief USBC_DEF_STR_IDX_LANGUAGE defines default language string index
+ */
+#define USBC_DEF_STR_IDX_LANGUAGE           0x00
+
+
+/*!
+ *  @brief USBC_DEF_IDX_MANUFACTURER defines default manufacturer string index
+ */
+#define USBC_DEF_STR_IDX_MANUFACTURER       0x01
+
+
+/*!
+ *  @brief USBC_DEF_IDX_PRODUCT defines default product string index
+ */
+#define USBC_DEF_STR_IDX_PRODUCT            0x02
+
+
+/*!
+ *  @brief USBC_DEF_IDX_SERIALNUM defines default serial number string index
+ */
+#define USBC_DEF_STR_IDX_SERIALNUM          0x03
+
+
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+
+/*!
+ *  @brief USBC_USB11_MAX_PACKET_SIZE define maximum packet size in USB SPEED 1.1
+ */
+#define USBC_USB11_MAX_PACKET_SIZE          64
+
+
+/*!
+ *  @brief USBC_USB20_MAX_PACKET_SIZE define maximum packet size in USB SPEED 2.0
+ */
+#define USBC_USB20_MAX_PACKET_SIZE          512
+
+
+/*!
+ *  @brief USBC_USB30_MAX_PACKET_SIZE define maximum packet size in USB SPEED 3.0
+ */
+#define USBC_USB30_MAX_PACKET_SIZE          1024
+
+
+/*!
+ *  @brief usbc_core_mode_e enumerate all possible modes of USBCORE module
+ *  @param USBC_CORE_MODE_MIN                       pseudo mode
+ *  @param USBC_CORE_MODE_ACM                       1 CDC-ACM COM
+ *  @param USBC_CORE_MODE_ECM                       1 CDC-ECM
+ *  @param USBC_CORE_MODE_RNDIS                     1 RNDIS
+ *  @param USBC_CORE_MODE_CDROM                     1 Mass Storage CDROM
+ *  @param USBC_CORE_MODE_DISK                      1 Mass Storage Disk
+ *  @param USBC_CORE_MODE_MBIM                      1 MBIM
+ *  @param USBC_CORE_MODE_1RNDIS_1ACM               1 RNDIS 1 CDC-ACM
+ *  @param USBC_CORE_MODE_1RNDIS_2ACM               1 RNDIS 2 CDC-ACM
+ *  @param USBC_CORE_MODE_1ECM_1ACM                 1 CDC-ECM 1 CDC-ACM
+ *  @param USBC_CORE_MODE_2ACM                      2 CDC-ACM
+ *  @param USBC_CORE_MODE_3ACM                      3 CDC-ACM
+ *  @param USBC_CORE_MODE_1RNDIS_1ACM_1CDROM        1 RNDIS 1 CDC-ACM 1 CDROM
+ *  @param USBC_CORE_MODE_1ECM_1ACM_1CDROM          1 CDC-ECM 1 CDC-ACM 1 CDROM
+ *  @param USBC_CORE_MODE_MAX                       pseudo mode
+ */
+typedef enum _usbc_core_mode {
+    USBC_CORE_MODE_MIN                          = 0,
+    USBC_CORE_MODE_ACM                          = 1,
+    USBC_CORE_MODE_ECM                          = 2,
+    USBC_CORE_MODE_RNDIS                        = 3,
+    USBC_CORE_MODE_CDROM                        = 4,
+    USBC_CORE_MODE_DISK                         = 5,
+    USBC_CORE_MODE_MBIM                         = 6,
+    USBC_CORE_MODE_1RNDIS_1ACM                  = 7,
+    USBC_CORE_MODE_1RNDIS_2ACM                  = 8,
+    USBC_CORE_MODE_1ECM_1ACM                    = 9,
+    USBC_CORE_MODE_2ACM                         = 10,
+    USBC_CORE_MODE_3ACM                         = 11,
+    USBC_CORE_MODE_1RNDIS_1ACM_1CDROM           = 12,
+    USBC_CORE_MODE_1ECM_1ACM_1CDROM             = 13,
+#ifdef __USB_MSD_SUPPORT__
+	USBC_CORE_MODE_MSD							=14,
+	USBC_CORE_MODE_1ACM_1MSD					=15,
+#endif
+    USBC_CORE_MODE_1MBIM_1ACM                   = 16,
+    USBC_CORE_MODE_MAX                          = 99,
+} usbc_core_mode_e;
+
+
+/*!
+ *  @brief set the mode usbcore will run at
+ */
+void usbc_core_set_mode(usbc_core_mode_e mode);
+
+
+/*!
+ *  @brief  SetUp all things for MODE CDC_ACM
+ */
+void usbc_core_set_mode_acm(void);
+
+
+/*!
+ *  @brief  SetUp all things for MODE RNDIS
+ */
+void usbc_core_set_mode_rndis(void);
+
+
+/*!
+ *  @brief  SetUp all things for MODE 1MBIM_1ACM
+ */
+void usbc_core_set_mode_1mbim_1acm(void);
+
+
+/*!
+ *  @brief  SetUp all things for MODE 1RNDIS_1ACM
+ */
+void usbc_core_set_mode_1rndis_1acm(void);
+
+
+/*!
+ *  @brief  SetUp all things for MODE 1RNDIS_2ACM
+ */
+void usbc_core_set_mode_1rndis_2acm(void);
+
+/*!
+ *  @brief  SetUp all things for MODE 1RNDIS_3ACM
+ */
+void usbc_core_set_mode_3acm(void);
+
+/*!
+ *  @brief  Set up an USB device with one MBIM function.
+ */
+void usbc_core_set_mode_mbim(void);
+/*!
+ *  @brief  Set up an USB device with one MSD function.
+ */
+void usbc_core_set_mode_msd(void);
+
+void usbc_core_set_mode_1acm_1msd();
+
+#endif  // _USBCORE_MODE_H
+
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_trace.h b/mcu/middleware/hif/usbcore/include/usbcore_trace.h
new file mode 100644
index 0000000..5eb4764
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_trace.h
@@ -0,0 +1,17 @@
+#ifndef _USBCORE_TRACE_H_
+#define _USBCORE_TRACE_H_
+#if HIF_CONSOLE_TRACE_ENABLED != 1
+#ifndef GEN_FOR_PC
+ #include "stack_config.h"
+#endif /* GEN_FOR_PC */
+#include "dhl_trace.h"
+#include "dhl_def.h"
+#if !defined(GEN_FOR_PC)
+#if defined(__DHL_MODULE__) || defined(__CUSTOM_RELEASE__)
+#endif /* TST Trace Defintion */
+#endif
+#endif /* HIF_CONSOLE_TRACE_ENABLED != 1 */
+#if !defined(GEN_FOR_PC)
+#include"usbcore_trace_mod_usbcore_utmd.h"
+#endif
+#endif /* _USBCORE_TRACE_H_ */
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_trace_mod_usbcore_utmd.json b/mcu/middleware/hif/usbcore/include/usbcore_trace_mod_usbcore_utmd.json
new file mode 100644
index 0000000..530d996
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_trace_mod_usbcore_utmd.json
@@ -0,0 +1,606 @@
+{
+  "legacyParameters": {}, 
+  "module": "MOD_USBCORE", 
+  "startGen": "Legacy",
+  "endGen": "-",
+  "traceClassDefs": [
+    {
+      "TRACE_ERROR": {
+        "debugLevel": "Ultra-High", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "TRACE_WARNING": {
+        "debugLevel": "High", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "TRACE_INFO": {
+        "debugLevel": "Medium", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "InternalDesign"
+      }
+    },
+    {
+      "TRACE_STATE": {
+        "debugLevel": "Low", 
+        "tag": [
+          "Baseline"
+        ], 
+        "traceType": "CoreDesign"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "USBCORE_TASK_INIT": {
+        "format": "[USBCORE] usbcore task initialization", 
+        "traceClass": "TRACE_STATE"
+      }
+    }, 
+    {
+      "USBCORE_TASK_RESET": {
+        "format": "[USBCORE] usbcore task reset", 
+        "traceClass": "TRACE_STATE"
+      }
+    }, 
+    {
+      "USBCORE_TASK_CREATE": {
+        "format": "[USBCORE] usbcore task create", 
+        "traceClass": "TRACE_STATE"
+      }
+    }, 
+    {
+      "USBCORE_TASK_MAIN": {
+        "format": "[USBCORE] usbcore task main", 
+        "traceClass": "TRACE_STATE"
+      }
+    }, 
+    {
+      "USBCORE_ALL_NODE_CHECKIN": {
+        "format": "[USBCORE] all nodes have been checked in", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_ALL_NODE_CHECKIN_INIT_CLASS_START": {
+        "format": "[USBCORE] start initialing classes after all nodes checked in: class type = %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_ALL_NODE_CHECKIN_INIT_CLASS_END": {
+        "format": "[USBCORE] finish initialing classes after all nodes checked in: class type = %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_ALL_NODE_CHECKIN_REINIT_CLASS_START": {
+        "format": "[USBCORE] start re-initialing classes after all nodes checked in: class index = %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_ALL_NODE_CHECKIN_REINIT_CLASS_END": {
+        "format": "[USBCORE] finish re-initialing classes after all nodes checked in: class index = %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_DISPATCH_REQUEST": {
+        "format": "[USBCORE] usbcore dispatches requests: bmRequestType = 0x%x", 
+        "traceClass": "TRACE_STATE"
+      }
+    }, 
+    {
+      "USBCORE_SET_ADDRESS": {
+        "format": "[USBCORE] usbcore handles set_address: addr = 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_GET_STATUS": {
+        "format": "[USBCORE] usbcore handles get_status: bRecip = 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_SET_FEATURE": {
+        "format": "[USBCORE] usbcore handles set_feature: bRecip = 0x%x, wIndex = 0x%x, wValue = 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_CLEAR_FEATURE": {
+        "format": "[USBCORE] usbcore handles clear_feature: bRecip = 0x%x, wIndex = 0x%x, wValue = 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_GET_DESCRIPTOR": {
+        "format": "[USBCORE] usbcore handles get_descriptor: bRecip = 0x%x, type = 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_SET_CONFIG": {
+        "format": "[USBCORE] usbcore handles set_configuration: wValue = 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_GET_CONFIG": {
+        "format": "[USBCORE] usbcore handles get_configuration: wValue = 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_SET_INFX": {
+        "format": "[USBCORE] usbcore handles set_interface: bInterface = 0x%x, wValue = 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_GET_INFX": {
+        "format": "[USBCORE] usbcore handles get_interface: bInterface = 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_HIF_EVENT_ATTACH": {
+        "format": "[USBCORE] usbcore receives ATTACH events from HIF driver", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_HIF_EVENT_DETACH": {
+        "format": "[USBCORE] usbcore receives DETACH events from HIF driver", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_HIF_EVENT_SUSPEND": {
+        "format": "[USBCORE] usbcore receives SUSPEND events from HIF driver", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_HIF_EVENT_RESUME": {
+        "format": "[USBCORE] usbcore receives RESUME events from HIF driver", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_HIF_EVENT_RESET": {
+        "format": "[USBCORE] usbcore receives RESET events from HIF driver", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_HIF_EVENT_SPEED_CHANGE": {
+        "format": "[USBCORE] usbcore changes speed in HIF driver reset: original speed 0x%x to new speed 0x%x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_HIF_EVENT_UNKNOWN": {
+        "format": "[USBCORE] usbcore receives unknown events from HIF driver", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "USBCORE_HIF_SET_CONFIG": {
+        "format": "[USBCORE] usbcore is setting config: %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_HIF_SET_CONFIG_UNCHANGED": {
+        "format": "[USBCORE] usbcore doesn't set config (config unchaged)", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_HIF_SET_CONFIG_REINIT_START": {
+        "format": "[USBCORE] usbcore starts usbclass reinit in HIF SET CONF", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_HIF_SET_CONFIG_REINIT_END": {
+        "format": "[USBCORE] usbcore finishes usbclass reinit in HIF SET CONF", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_HIF_SET_CONFIG_USBCLASS": {
+        "format": "[USBCORE] usbcore calls set config callback usbclass type %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_HIF_SET_CONFIG_HIF": {
+        "format": "[USBCORE] usbcore calls HIF driver to set config: %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_HIF_SET_CONFIG_ADDR_STATE": {
+        "format": "[USBCORE] usbcore goes to address state after setting config", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_HIF_SET_CONFIG_CONF_STATE": {
+        "format": "[USBCORE] usbcore goes to configuration state after setting config", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_CONF_INVALID": {
+        "format": "[USBCORE] usbcore receives an invalid configuration: %d", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "USBCORE_REMOTE_WK_START": {
+        "format": "[USBCORE] usb class id %d starts calling function remote wk", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_REMOTE_WK_INVALID": {
+        "format": "[USBCORE] the class id %d doesn't enable function remote wk: status 0x%x", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "USBCORE_REMOTE_WK_DEVICE": {
+        "format": "[USBCORE] the class id %d asks the USB device to remote wakeup", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_REMOTE_WK_DEVICE_WAIT": {
+        "format": "[USBCORE] the class id %d waits for device resuming", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_REMOTE_WK_FUNC": {
+        "format": "[USBCORE] the class id %d asks  USBCORE to wakeup its function", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_REMOTE_WK_SET_NOTIFY_TIMER": {
+        "format": "[USBCORE] usbcore sets remote wk notify timer for the class id %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_REMOTE_WK_HIF_NOTIFY": {
+        "format": "[USBCORE] usbcore asks HIF driver to send wk notification for interface %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_NOTIFY_CLASS_START": {
+        "format": "[USBCORE] usbcore calls usbclass's notify state: class type = %d, state = %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_NOTIFY_CLASS_END": {
+        "format": "[USBCORE] usbcore finishs usbclass's notify state: class type = %d, state = %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_NOTIFY_WK_ABILITY_START": {
+        "format": "[USBCORE] usbcore starts notifing wk ability to usbclass: class type = %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_NOTIFY_WK_ABILITY_END": {
+        "format": "[USBCORE] usbcore finishs notifing wk ability to usbclass: class type = %d", 
+        "traceClass": "TRACE_INFO"
+      }
+    }, 
+    {
+      "USBCORE_NOTIFY_WK_ABILITY_INVALID": {
+        "format": "[USBCORE] invalid notifing wk ability to usbclass: class type = %d", 
+        "traceClass": "TRACE_ERROR"
+      }
+    }, 
+    {
+      "USBCORE_DEV_SUSPEND_CLOCK": {
+        "format": "[USBCORE] usbcore sets clock gating = %d, notifies usbidle = %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_DEV_SUSPEND_L4": {
+        "format": "[USBCORE] usbcore sets l4 power saving = %d, notifies ILM = %d, suspend = %d, remote wk =%d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_SUSPEND_STOP_POLL": {
+        "format": "[USBCORE] usbcore stop polling GPDs", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_SUSPEND_START_POLL": {
+        "format": "[USBCORE] usbcore start polling GPDs", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_RESTORE_BFF_GPD": {
+        "format": "[USBCORE] usbcore restore buffered GPDs in queue %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_FLUSH_BFF_GPD": {
+        "format": "[USBCORE] usbcore flushes buffered GPDs in queue %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_UPDATE_API_BUFF_GPD": {
+        "format": "[USBCORE] usbcore updates API for buffering GPDs: %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+    {
+      "USBCORE_CLASS_OP_INACTIVATE_QUE": {
+        "format": "[USBCORE] the class id %d uses inactivated queue %d", 
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+	{
+      "USBCORE_MODE_NVRAM_SELECT": {
+        "format": "[USBCORE] usbcore mode NVRAM select vendor:%d, index%d, mode:%d ret:%d", 
+        "traceClass": "TRACE_INFO"
+      }
+    },
+	{
+      "USBCORE_MODE_DEFAULT_CFG_SELECT": {
+        "format": "[USBCORE] usbcore mode default select mode:%d", 
+        "traceClass": "TRACE_INFO"
+      }
+    },
+	{
+      "USBCORE_DEBUG_CONFIGURATION_PORT_INFO": {
+        "format": "[USBCORE] usbcore port_info class idx:%d, type:%s, owner:%d, uart_port%d", 
+        "traceClass": "TRACE_INFO"
+      }
+    },
+	{
+      "USBCORE_DEBUG_CONFIGURATION_PORT_EP_INFO": {
+        "format": "[USBCORE] usbcore port_info class idx:%d, tx_ep start:%d, num:%d, rx_ep start:%d, num:%d", 
+        "traceClass": "TRACE_INFO"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_NOTIFY_USB_STATE": {
+        "format": "[USBCORE] usbcore dual_owner notify USB state %d length: %d ret :%d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_NOTIFY_FEATURE_SC": {
+        "format": "[USBCORE] usbcore dual_owner feature set/clear, request:%d value:%d index:%d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_NOTIFY_SEND_CLASS_REQUEST": {
+        "format": "[USBCORE] usbcore dual_owner send class req, request:%d value:%d index:%d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },	
+	{
+      "USBCORE_DUAL_OWNER_SEND_CLASS_REQUEST_NO_RSP": {
+        "format": "[USBCORE] usbcore dual_owner send class request no rsp request:%d value:%d index:%d", 
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_RECEIVE_CCCI_DL_DONE_TIMEOUT": {
+        "format": "[USBCORE] usbcore dual_owner CCCI write done callback timeout.", 
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_SEND_CTRL_OUT_DATA": {
+        "format": "[USBCORE] usbcore dual_owner send EP0 out data length:%d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_CCCI_WRITE": {
+        "format": "[USBCORE] usbcore dual_owner write ccci fail ret:%d", 
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_CCCI_READ": {
+        "format": "[USBCORE] usbcore dual_owner read ccci fail ret:%d", 
+        "traceClass": "TRACE_ERROR"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_IN_DATA_LEN_ERROR": {
+        "format": "[USBCORE] usbcore dual_owner IN request data expect length:%d actual length:%d ", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_RECEIVE_ILM_MSG": {
+        "format": "[USBCORE] usbcore dual_owner receive ILM MSG msg_id %d, length %d.", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_RECEIVE_REMOTE_WAKEUP": {
+        "format": "[USBCORE] usbcore dual_owner send function resume after remote wakeup from device%d.", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_DUAL_OWNER_DEBUG_ATTACHED_INFO": {
+        "format": "[USBCORE] usbcore dual_owner attached info %s:%d, %s:%d.", 
+        "traceClass": "TRACE_INFO"
+      }
+    },
+	{
+      "USBCORE_RECEIVE_ATCMD_MSG": {
+        "format": "[USBCORE] usbcore receive ATCMD msg data:%s, handle result:%d.", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_DUALIPC_INFO": {
+        "format": "[USBCORE] usbcore dualipc dipcmode:%d, port_mode:%d, pcie_state:%d.", 
+        "traceClass": "TRACE_INFO"
+      }
+    },
+	{
+      "USBCORE_FACTORY_MODE_INFO": {
+        "format": "[USBCORE] usbcore get META mode from CCCI start_id:%d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },	
+	{
+      "USBCORE_POLL_TICK_TIMEOUT": {
+        "format": "[USBCORE] usbcore get polling tick timeout duration : %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_POLL_ALL_QUEUE_EMPTY": {
+        "format": "[USBCORE] polling all queue %d times empty, tx 0x%x, rx 0x%x", 
+        "traceClass": "TRACE_WARNING"
+	  }
+    },	
+    {
+      "USBCORE_CLASS_FLUSH_HW_QUEUE_PS": {
+        "format": "[USBCORE] flush HW_q[0x%x], returns %d GPD(s), first gpd %x, last gpd %x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+    {
+      "USBCORE_CLASS_FLUSH_SW_QUEUE_PS": {
+        "format": "[USBCORE] flush SW_q[0x%x], returns %d GPD(s), first gpd %x, last gpd %x", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+	{
+      "USBCORE_CLASS_CHECK_SUBMIT_TX_GPD_KPI": {
+        "format": "[USBCORE] submit tx_q %d gpd %x length %d, bd number %d bypass %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+	{
+      "USBCORE_CLASS_CHECK_POLL_TX_GPD_KPI": {
+        "format": "[USBCORE] polled tx_q %d gpd %x length %d, bd number %d bypass %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+	{
+      "USBCORE_CLASS_CHECK_SUBMIT_RX_GPD_KPI": {
+        "format": "[USBCORE] submit rx_q %d gpd %x length %d, bd number %d bypass %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }, 
+	{
+      "USBCORE_CLASS_CHECK_POLL_RX_GPD_KPI": {
+        "format": "[USBCORE] polled rx_q %d gpd %x length %d, bd number %d bypass %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_FLUSH_RX_HW_GPD_WITH_SUBMIT": {
+        "format": "[USBCORE] flush HW queue %d, returns gpd %x length %d, and submit", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },	
+	{
+      "USBCORE_FLUSH_RX_SW_GPD_WITH_SUBMIT": {
+        "format": "[USBCORE] flush SW queue %d, returns gpd %x length %d, and submit", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_RECEIVE_MULTI_SETUP_PACKET": {
+        "format": "[USBCORE] receive multi-setup , state machine: %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_MULTI_SETUP_PACKET_RETURN_STALL": {
+        "format": "[USBCORE] return STALL after multi-setup packet", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_GET_NETWORK_TYPE": {
+        "format": "[USBCORE] current network type is %d", 
+        "traceClass": "TRACE_WARNING"
+	  }
+    },
+	{
+      "USBCORE_SET_USB_WAKEUP_EVENT": {
+        "format": "[USBCORE] set usb wakeup event from eint", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_WAIT_AP_SUSPEND_DOWN_TIMEOUT": {
+        "format": "[USBCORE] ap suspend done timeout", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_WAIT_AP_RESET_DOWN_TIMEOUT": {
+        "format": "[USBCORE] ap reset done timeout", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_WAIT_AP_ATTACH_DOWN_TIMEOUT": {
+        "format": "[USBCORE] ap attach done timeout", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_SET_CG_ON": {
+        "format": "[USBCORE] USBCORE set USB cg on", 
+        "traceClass": "TRACE_WARNING"
+      }
+    },
+	{
+      "USBCORE_GET_LOW_POWER_ENABLE_VALUE": {
+        "format": "[USBCORE] USBCORE get low power value: %d", 
+        "traceClass": "TRACE_WARNING"
+      }
+    }
+  ], 
+  "traceFamily": "PS",
+  "userModule": "MOD_USBCORE"
+}
diff --git a/mcu/middleware/hif/usbcore/include/usbcore_ut.h b/mcu/middleware/hif/usbcore/include/usbcore_ut.h
new file mode 100644
index 0000000..a393f33
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/include/usbcore_ut.h
@@ -0,0 +1,34 @@
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "usbcore_usbstd.h"
+#include "hif_common.h"
+#include "hif_usb.h"
+#include "usbcore_main.h"
+#include "usbcore_class_device.h"
+
+#define USBC_UT_FAKE_CLASS_CALLBACK 0
+
+#define usbc_core_set_ss_dev_init_u1_en(...)
+#define usbc_core_set_ss_dev_init_u2_en(...)
+#define hifusb_ss_func_wk_notify usbc_ut_fake_notify_retry
+#define hifusb_remote_wakeup  usbc_ut_fake_hif_remote_wakeup
+
+#define USBC_UT_BLOCK_TICK_T    2
+
+typedef kal_uint16 usbc_ut_fake_infx_status;
+
+typedef struct usbc_ut_fake_class_func_info {
+    usbc_ut_fake_infx_status    infx_status;
+    kal_uint8                    nRetry;
+} usbc_ut_fake_class_func_info_t;
+
+kal_uint16 usbc_ut_fake_query_func_wk_status(kal_uint8 class_device_id);
+
+void usbc_ut_fake_notify_func_wk_ability(kal_uint8 class_device_id, kal_bool ability);
+
+kal_bool usbc_ut_fake_notify_retry(kal_uint8 nInterface);
+
+kal_bool usbc_ut_fake_hif_remote_wakeup();
+
+kal_bool usbc_ut_fake_set_control_request(kal_uint8 *buffer, kal_uint32 length, usbc_control_request_type_e type);
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_class_device.c b/mcu/middleware/hif/usbcore/src/usbcore_class_device.c
new file mode 100644
index 0000000..bc4a784
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_class_device.c
@@ -0,0 +1,1118 @@
+/*!
+ *  @file usbcore_class_device.c
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides functions of usbcore class device interface
+ */
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "usbcore_main.h"
+#include "usbcore_class_device.h"
+#include "usbcore_hif.h"
+#include "hifusb_qmu.h"
+#include "hif_ior.h"
+#include "usbcore_ind_q.h"
+#include "hmu.h"
+#include "usbcore_debug.h"
+#include "usbidle_if.h"
+#include "hif_swla.h"
+#include "usbidle_if.h"
+#include "hif_mw_msgid.h"
+#include "usbc_custom.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+
+#ifdef ATEST_SYS_USBCORE
+#include "usbcore_ut.h"
+#endif
+#include "us_timer.h"
+
+#define INVALID_CLASS_DEVICE_ID         0xff
+#define INVALID_PIPE_QUEUE_ID           0xff
+#define PIPE_QUEUE_RX_MASK              0x80
+
+usbcore_unique_code_class_module usbcore_classid_to_module(kal_uint8 class_device_id)
+{
+    usb_class_type_e type;
+    usbcore_unique_code_class_module module;
+    type = usbc_core_get_instance()->class_device[class_device_id].class_type;
+
+    switch(type)
+    {
+#ifdef __USB_ACM_SUPPORT__
+        case USB_CLASS_ACM1:
+        case USB_CLASS_ACM2:
+        case USB_CLASS_ACM3:
+            module = USBCORE_UNIQUE_CODE_CLASS_CDCACM;
+            break;
+#endif
+#ifdef __USB_RNDIS_SUPPORT__
+        case USB_CLASS_RNDIS:
+            module = USBCORE_UNIQUE_CODE_CLASS_RNDIS;
+            break;
+#endif
+#ifdef __USB_ADB_SUPPORT__
+        case USB_CLASS_ADB:
+            module = USBCORE_UNIQUE_CODE_CLASS_ADB;
+            break;
+#endif
+#ifdef __USB_MBIM_SUPPORT__
+        case USB_CLASS_MBIM:
+            module = USBCORE_UNIQUE_CODE_CLASS_MBIM;
+            break;        
+#endif
+#ifdef __USB_ECM_SUPPORT__
+        case USB_CLASS_ECM:
+            module = USBCORE_UNIQUE_CODE_CLASS_ECM;
+            break;
+#endif
+//#ifdef __USB_MSD_SUPPORT__
+        case USB_CLASS_MS:
+            module = USBCORE_UNIQUE_CODE_CLASS_MSE;
+            break;
+//#endif
+        default:
+            module = USBCORE_UNIQUE_CODE_CLASS_START;
+            break;
+    }
+    return module;
+}
+
+static void release_class_device(kal_uint8 class_device_id)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 i = 0;
+
+    pUsbCore->class_device[class_device_id].state = USBC_CORE_CLASS_DEVICE_STATE_INITIATED;
+
+    for ( i=0; i<pUsbCore->total_class_interfaces; i++ )
+    {
+        if (pUsbCore->class_interface[i].class_device_id == class_device_id)
+        {
+            pUsbCore->class_interface[i].state = USBC_CORE_CLASS_INTERFACE_STATE_INITIATED;
+        }
+    }
+}
+
+
+static kal_uint8 acquire_pipe_queue(kal_uint8 class_device_id, usbc_pipe_type_e type)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 pipe_queue = INVALID_PIPE_QUEUE_ID;
+    kal_uint8 i = 0;
+
+    for ( i=0; i< MAX_USBCORE_QUEUE_NUM; i++ )
+    {
+        if ( (pUsbCore->tx_queue[i].class_device_id == class_device_id) &&
+             (pUsbCore->tx_queue[i].pipe_type == type) &&
+             (pUsbCore->tx_queue[i].state == USBC_CORE_QUEUE_STATE_INITIATED))
+        {
+            pipe_queue = i;
+            break;
+        }
+    }
+
+    if ( pipe_queue != INVALID_PIPE_QUEUE_ID )
+    {
+        return pipe_queue;
+    }
+
+    for ( i=0; i< MAX_USBCORE_QUEUE_NUM; i++ )
+    {
+        if ( (pUsbCore->rx_queue[i].class_device_id == class_device_id) &&
+             (pUsbCore->rx_queue[i].pipe_type == type) &&
+             (pUsbCore->rx_queue[i].state == USBC_CORE_QUEUE_STATE_INITIATED))
+        {
+            pipe_queue = (i | PIPE_QUEUE_RX_MASK);
+            break;
+        }
+    }
+
+    return pipe_queue;
+}
+
+
+static void release_pipe_queue(kal_uint8 class_device_id)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 i = 0;
+
+    for ( i=0; i< MAX_USBCORE_QUEUE_NUM; i++ )
+    {
+        if (pUsbCore->tx_queue[i].class_device_id == class_device_id)
+        {
+            pUsbCore->tx_queue[i].state = USBC_CORE_QUEUE_STATE_INITIATED;
+        }
+        if (pUsbCore->rx_queue[i].class_device_id == class_device_id)
+        {
+            pUsbCore->rx_queue[i].state = USBC_CORE_QUEUE_STATE_INITIATED;
+        }
+    }
+}
+
+static kal_bool usbc_class_device_submit_io_request_priv(hif_queue_type_e core_queue_hif_type, usbc_core_queue_t *pQueue, usbc_io_request_t *io_request, kal_uint8 queue_no)
+{
+    usbc_io_request_t  *current_request = io_request;
+    usbc_io_request_t  *next_request;
+    qbm_gpd            *first_gpd      = NULL;
+    qbm_gpd            *last_gpd       = NULL;
+    qbm_gpd            *current_gpd    = NULL;
+    kal_bool isTx = KAL_FALSE;
+
+    while ( current_request != NULL )
+    {
+        next_request = current_request->next_request;
+
+        first_gpd = current_request->first_gpd;
+        last_gpd = current_request->last_gpd;
+        current_gpd = first_gpd;
+        /* try to traverse gpd list if last_gpd is not filled */
+        if (last_gpd == NULL)
+        {
+            while ( current_gpd->p_next != NULL )
+            {
+                current_gpd = current_gpd->p_next;
+            }
+            last_gpd = current_gpd;
+        }
+
+#ifdef __USBCORE_DEBUG__
+        usbc_core_printf("[USBCORE] submit type %d queue no %d first gpd %x last gpd %x\r\n", core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no), first_gpd, last_gpd);
+        //usbc_core_dump_gpd_list(first_gpd, last_gpd);
+#endif
+        isTx = ((queue_no & PIPE_QUEUE_RX_MASK) != PIPE_QUEUE_RX_MASK)?KAL_TRUE:KAL_FALSE;
+        usbc_core_trace_gpd_info(first_gpd, last_gpd, HIFUSB_EPNO_2_QNO(pQueue->ep_no), isTx, 1);
+        
+        usbc_core_set_usbhifq_gpd(core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no), first_gpd, last_gpd);
+
+        current_request = next_request;
+    }
+
+    return KAL_TRUE;
+}
+
+
+
+kal_bool
+usbc_core_get_queue_info(
+    kal_uint8           class_device_id,
+    kal_uint8           queue_no,
+    usbc_core_queue_t **queue,
+    hif_queue_type_e   *queue_type)
+{
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    kal_uint8           core_queue_no;
+
+    if ((class_device_id >= pUsbCore->total_class_devices) ||
+        (pUsbCore->class_device[class_device_id].state != USBC_CORE_CLASS_DEVICE_STATE_REGISTERED)) {
+        EXT_ASSERT(0, USBCORE_LOC_QUERY_QUE_DEVICE_NOT_REGISTER, (kal_uint32)class_device_id, (kal_uint32)pUsbCore->class_device[class_device_id].state);
+        return KAL_FALSE;
+    }
+
+    if ((queue_no & ~PIPE_QUEUE_RX_MASK) > MAX_USBCORE_QUEUE_NUM) {
+        EXT_ASSERT(0, USBCORE_LOC_QUERY_QUE_OVERSIZE_QUE_NUMBER, (kal_uint32)class_device_id, (kal_uint32)queue_no);
+        return KAL_FALSE;
+    }
+
+    if ((queue_no & PIPE_QUEUE_RX_MASK) != PIPE_QUEUE_RX_MASK) {
+        core_queue_no = queue_no;
+        *queue_type = HIFQ_TYPE_TX;
+        *queue = &(pUsbCore->tx_queue[core_queue_no]);
+    } else {
+        core_queue_no = queue_no & ~PIPE_QUEUE_RX_MASK;
+        *queue_type = HIFQ_TYPE_RX;
+        *queue = &(pUsbCore->rx_queue[core_queue_no]);
+    }
+
+    if ((*queue)->class_device_id != class_device_id) {
+        EXT_ASSERT(0, USBCORE_LOC_QUERY_QUE_CLASS_ID_NOT_MATCH, (kal_uint32)class_device_id, (kal_uint32)((*queue)->class_device_id));
+        return KAL_FALSE;
+    }
+
+    if ((*queue)->state != USBC_CORE_QUEUE_STATE_ACTIVE) {
+        usbc_trace_info(USBCORE_CLASS_OP_INACTIVATE_QUE, class_device_id, queue_no);
+    }
+
+    return KAL_TRUE;
+}
+
+usbc_class_device_instance_t* usbc_class_device_register(
+    kal_uint8                 class_device_id,
+    usbc_class_device_info_t *device_info)
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();
+    if (pUsbCore == NULL) {
+        ASSERT(0);
+        return NULL;
+    }
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    return usbc_core_device_register(class_device_id, pUsbCore, device_info);
+}
+
+usbc_class_device_instance_t* usbc_core_device_register(
+    kal_uint8                 class_device_id,
+    usbc_core_t              *pUsbCore,
+    usbc_class_device_info_t *device_info)
+{
+    usbc_core_class_device_t* pClassDevice = NULL;
+    usbc_class_device_instance_t* pClassDeviceInstance = NULL;
+    usbc_core_queue_t* pQueue = NULL;
+    kal_uint8 acquire_queue = 0;
+    kal_uint8 i = 0;
+
+    if (device_info == NULL) {
+        ASSERT(0);
+        return NULL;
+    }
+
+    /* Check state of class device -> it should be initiated state */
+    if (pUsbCore->class_device[class_device_id].state != USBC_CORE_CLASS_DEVICE_STATE_INITIATED) {
+        EXT_ASSERT(0, USBCORE_LOC_REGISTER_CLASS_NOT_INITIALIZE, (kal_uint32)class_device_id, (kal_uint32)(pUsbCore->class_device[class_device_id].state));
+        return NULL;
+    }
+
+    /* found available device instance, use it and apply register infromation */
+    pClassDevice = &(pUsbCore->class_device[class_device_id]);
+    if (device_info->total_pipes != pClassDevice->total_pipes) {
+        // pipe number not match, return NULL
+        ASSERT(0);
+        return NULL;
+    }
+
+    pClassDeviceInstance                    = &(pClassDevice->device_instance);
+    pClassDeviceInstance->id                = class_device_id;
+    pClassDeviceInstance->speed             = pUsbCore->speed;
+    pClassDeviceInstance->total_interfaces  = 0;
+    pClassDeviceInstance->context           = device_info->class_device_context;
+    pClassDevice->state             = USBC_CORE_CLASS_DEVICE_STATE_REGISTERED;
+    pClassDevice->notify_usb_state  = device_info->notify_usb_state;
+    pClassDevice->notify_usb_speed  = device_info->notify_usb_speed;
+#ifdef ATEST_SYS_USBCORE
+  #if USBC_UT_FAKE_CLASS_CALLBACK
+    pClassDevice->notify_func_wk_ability    = usbc_ut_fake_notify_func_wk_ability;
+    pClassDevice->query_func_wk_status      = usbc_ut_fake_query_func_wk_status;
+  #else
+    pClassDevice->notify_func_wk_ability    = device_info->notify_func_wk_ability;
+    pClassDevice->query_func_wk_status      = device_info->query_func_wk_status;
+  #endif
+#else
+    pClassDevice->notify_func_wk_ability    = device_info->notify_func_wk_ability;
+    pClassDevice->query_func_wk_status      = device_info->query_func_wk_status;
+#endif
+
+    for ( i=0; i<pUsbCore->total_class_interfaces; i++ )
+    {
+        if ( (pUsbCore->class_interface[i].state == USBC_CORE_CLASS_INTERFACE_STATE_INITIATED) &&
+             (pUsbCore->class_interface[i].class_device_id == class_device_id) )
+        {
+            /* fill Device Instance interface information */
+            pClassDeviceInstance->interface_type[pClassDeviceInstance->total_interfaces] = pUsbCore->class_interface[i].interface_type;
+            pClassDeviceInstance->interface_no[pClassDeviceInstance->total_interfaces] = pUsbCore->class_interface[i].interface_no;
+            pClassDeviceInstance->total_interfaces++;
+
+            /* fill USB Core interface information */
+            pUsbCore->class_interface[i].state = USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE;
+            pUsbCore->class_interface[i].notify_control_setup_packet = device_info->notify_control_setup_packet;
+            pUsbCore->class_interface[i].notify_control_complete = device_info->notify_control_complete;
+            pUsbCore->class_interface[i].notify_alternate_setting = device_info->notify_alternate_setting;
+        }
+    }
+
+    for ( i=0; i<device_info->total_pipes; i++ )
+    {
+        acquire_queue = acquire_pipe_queue(class_device_id, device_info->pipe_type[i]);
+        if ( acquire_queue == INVALID_PIPE_QUEUE_ID )
+        {
+            //can't satisfy, release acquired resource if any
+            release_pipe_queue(class_device_id);
+            release_class_device(class_device_id);
+            ASSERT(0);
+            return NULL;
+        }
+
+        /* fill Device Instance Queue information */
+        pClassDeviceInstance->queue_no_for_pipe[i] = acquire_queue;
+
+        /* fill USB Core Queue information */
+        if ( (acquire_queue & PIPE_QUEUE_RX_MASK) != PIPE_QUEUE_RX_MASK )
+        {
+            pQueue = &(pUsbCore->tx_queue[acquire_queue]);
+        } else {
+            pQueue = &(pUsbCore->rx_queue[acquire_queue & ~PIPE_QUEUE_RX_MASK]);
+        }
+        pQueue->state               = USBC_CORE_QUEUE_STATE_ACTIVE;
+        pQueue->notify_complete     = device_info->notify_pipe_complete[i];
+        pQueue->notify_rb_complete  = device_info->notify_rb_pipe_complete[i];
+        pQueue->notify_stall        = device_info->notify_pipe_stall[i];
+    }
+
+    return pClassDeviceInstance;
+}
+
+
+kal_bool usbc_class_device_deregister(kal_uint8 class_device_id)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    if ( (class_device_id >= pUsbCore->total_class_devices) ||
+         (pUsbCore->class_device[class_device_id].state != USBC_CORE_CLASS_DEVICE_STATE_REGISTERED) )
+    {
+        EXT_ASSERT(0, USBCORE_LOC_DEREGISTER_CLASS_NOT_REGISTERED, (kal_uint32)class_device_id, (kal_uint32)(pUsbCore->class_device[class_device_id].state));
+        return KAL_FALSE;
+    }
+
+    release_pipe_queue(class_device_id);
+    release_class_device(class_device_id);
+
+    return KAL_TRUE;
+}
+
+
+void* usbc_class_device_get_context(kal_uint8 class_device_id)
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();
+    usbc_core_class_device_t *pClassDevice = &(pUsbCore->class_device[class_device_id]);
+    usbc_class_device_instance_t *pClassDeviceInstance = &(pClassDevice->device_instance);
+
+    return pClassDeviceInstance->context;
+}
+
+
+kal_bool usbc_class_device_submit_control_request(
+    kal_uint8 class_device_id, kal_uint8* buffer, kal_uint32 length,
+    usbc_control_request_type_e type)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    if (!USBC_IS_IN_EXCEPTION_MODE())
+    {
+        USBC_CLASS_DEVICE_CONTEXT_CHECK();
+    }
+
+    if ( (class_device_id >= pUsbCore->total_class_devices) ||
+         (pUsbCore->class_device[class_device_id].state != USBC_CORE_CLASS_DEVICE_STATE_REGISTERED) )
+    {
+        EXT_ASSERT(0, USBCORE_LOC_SUBMIT_CTRL_REQ_CLASS_NOT_REGISTERED, (kal_uint32)class_device_id, (kal_uint32)(pUsbCore->class_device[class_device_id].state));
+        return KAL_FALSE;
+    }
+
+    return usbc_core_set_control_request(buffer, length, type);
+}
+
+
+kal_bool usbc_class_device_submit_io_request(
+    kal_uint8 class_device_id, kal_uint8 queue_no,
+    usbc_io_request_t* io_request)
+{
+    usbc_core_queue_t  *pQueue = NULL;
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    hif_queue_type_e    core_queue_hif_type;
+    kal_bool            ret;
+
+    HIF_SWLA_START("UD1");
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();  
+    
+    if ((queue_no & PIPE_QUEUE_RX_MASK) == PIPE_QUEUE_RX_MASK) 
+        USBC_QUEUE_GPD_TAKE_MUTEX(pUsbCore->rx_submit_enhmuexid[queue_no & ~PIPE_QUEUE_RX_MASK]);
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        HIF_SWLA_STOP("UD1");
+        return KAL_FALSE;
+    }
+
+    ret = usbc_class_device_submit_io_request_priv(core_queue_hif_type, pQueue, io_request, queue_no);
+    HIF_SWLA_STOP("UD1");
+    
+    if ((queue_no & PIPE_QUEUE_RX_MASK) == PIPE_QUEUE_RX_MASK) 
+        USBC_QUEUE_GPD_GIVE_MUTEX(pUsbCore->rx_submit_enhmuexid[queue_no & ~PIPE_QUEUE_RX_MASK]);
+    return ret;
+}
+
+kal_bool usbc_class_device_restore_gpd_pwrsave(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_queue_t  *pQueue = NULL;
+    hif_queue_type_e    core_queue_hif_type;
+    kal_bool            ret;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    // Restore GPDs
+    if (core_queue_hif_type == HIFQ_TYPE_TX) {
+        usbc_data_trace(MD_TRC_USBCORE_RESTORE_TX_GPD_SWQ2HWQ, (core_queue_hif_type << 8) | (queue_no & 0xFF) );
+    }
+    else if (core_queue_hif_type == HIFQ_TYPE_RX) {
+        usbc_data_trace(MD_TRC_USBCORE_RESTORE_RX_GPD_SWQ2HWQ, (core_queue_hif_type << 8) | (queue_no & 0xFF) );
+    }
+    ret = hifusbq_pwrsave_restore_gpd(core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no));
+
+    return ret;
+}
+
+kal_bool usbc_class_device_submit_io_request_ext(
+    kal_uint8 class_device_id, kal_uint8 queue_no,
+    usbc_io_request_t  *io_request, 
+    usbc_io_ext_info_t *info)
+{
+    usbc_core_queue_t  *pQueue = NULL;
+    hif_queue_type_e    core_queue_hif_type;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    switch (info->type) {
+    case USBC_IO_TX_NO_FLUSH:
+        core_queue_hif_type = HIFQ_TYPE_TX_NO_FLUSH;
+        break;
+
+    default:
+        ASSERT(KAL_FALSE);
+        return KAL_FALSE;
+    }
+
+    return usbc_class_device_submit_io_request_priv(core_queue_hif_type, pQueue, io_request, queue_no);
+}
+
+
+kal_bool usbc_class_device_submit_drb(kal_uint8 class_device_id, kal_uint8 queue_no,kal_uint32 submit_drb_count)
+{
+    kal_bool ret;
+    usbc_core_queue_t  *pQueue = NULL;
+    hif_queue_type_e    core_queue_hif_type;
+
+    HIF_SWLA_START("UD1");
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    ret = ubm_drb_submit(HIFUSB_EPNO_2_QNO(pQueue->ep_no), submit_drb_count);
+
+    HIF_SWLA_STOP("UD1");
+    return ret;
+}
+
+kal_bool usbc_class_device_flush_rb(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    usbc_core_queue_t* pQueue = NULL;
+    hif_queue_type_e core_queue_hif_type;
+    //hif_flush_type_e core_queue_flush_type = HIFQ_FLUSH_FREE;        // USBCLASS owner requests RB queue flushing is done USB driver;
+    kal_uint32 startIdx, endIdx;
+    kal_uint32 num = 0;
+    kal_bool result;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    if(core_queue_hif_type == HIFQ_TYPE_TX)
+    {
+        result = ubm_drb_flush(HIFUSB_EPNO_2_QNO(pQueue->ep_no), &startIdx, &endIdx, &num);    // Flush DRB and NFHB by USB driver
+    } else {
+        queue_no &= ~PIPE_QUEUE_RX_MASK;
+        (pUsbCore->rx_xit_meta)[queue_no].xit2meta_retry = KAL_FALSE;
+        (pUsbCore->rx_xit_meta)[queue_no].remain_num = (pUsbCore->rx_xit_meta)[queue_no].startIdx = (pUsbCore->rx_xit_meta)[queue_no].endIdx = 0;
+        result = ubm_xit_flush(HIFUSB_EPNO_2_QNO(pQueue->ep_no), &startIdx, &endIdx, &num);    // Flush XIT and PRB by USB driver
+    }
+
+    return result;
+}
+
+kal_bool usbc_class_device_rst_ep_pipe(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_queue_t  *pQueue = NULL;
+    hif_queue_type_e    core_queue_hif_type;
+    kal_bool 			is_tx;
+	
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+    if(pQueue->owner == USB_CLASS_OWNER_MD){
+        is_tx = core_queue_hif_type == HIFQ_TYPE_TX ? KAL_TRUE : KAL_FALSE;
+        usbc_core_rst_ep(is_tx, pQueue->ep_no);
+    }
+
+    return KAL_TRUE;
+
+}
+kal_bool usbc_class_device_flush_io_request(
+    kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_queue_t* pQueue = NULL;
+    hif_queue_type_e core_queue_hif_type;
+    hif_flush_type_e core_queue_flush_type;
+    qbm_gpd* first_gpd  = NULL;
+    qbm_gpd* last_gpd   = NULL;
+    kal_uint32 num = 0;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    if ( pQueue->notify_complete == NULL )
+    {
+        core_queue_flush_type = HIFQ_FLUSH_FREE;
+    } else {
+        core_queue_flush_type = HIFQ_FLUSH_DEQ;
+    }
+
+    // Flush GPDs that are configured in hardware, and give GPDs back to uppoer layers
+    num = usbc_core_flush_hifusbq_gpd(core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no), core_queue_flush_type, (void**)&first_gpd, (void**)&last_gpd);
+    if ( num != 0 )
+    {
+#ifdef __USBCORE_DEBUG__
+        usbc_core_printf("[USBCORE] flush type %d queue no %d first gpd %x last gpd %x\r\n", core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no), first_gpd, last_gpd);
+        //usbc_core_dump_gpd_list(first_gpd, last_gpd);
+#endif
+        if ( pQueue->notify_complete != NULL )
+        {
+            if ( first_gpd == NULL )
+            {
+                /* just indicate a notification */
+                usbc_data_trace(MD_TRC_USBCORE_CLASS_FLUSH_HW_QUEUE, queue_no, num, 0x00, 0x00);
+                usbc_trace_warn(USBCORE_CLASS_FLUSH_HW_QUEUE_PS, queue_no, num, 0x00, 0x00);
+                pQueue->notify_complete(pQueue->class_device_id, NULL);
+            } else {
+                usbc_io_request_t* request = NULL;
+                usbc_data_trace(MD_TRC_USBCORE_CLASS_FLUSH_HW_QUEUE, queue_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);                
+                usbc_trace_warn(USBCORE_CLASS_FLUSH_HW_QUEUE_PS, queue_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
+                request = (usbc_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(first_gpd);
+                request->next_request = NULL;
+                request->first_gpd = first_gpd;
+                request->last_gpd = last_gpd;
+                pQueue->notify_complete(pQueue->class_device_id, request);
+            }
+        }
+    }
+    else
+    {
+        usbc_data_trace(MD_TRC_USBCORE_CLASS_FLUSH_HW_QUEUE, queue_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);                
+        usbc_trace_warn(USBCORE_CLASS_FLUSH_HW_QUEUE_PS, queue_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
+    }
+
+    // Flush GPDs that are buffered in DRAM, and give GPDs back to uppoer layers
+    num = usbc_core_flush_sw_hifusbq_gpd(core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no), core_queue_flush_type, (void**)&first_gpd, (void**)&last_gpd);
+    if ( num != 0 )
+    {
+#ifdef __USBCORE_DEBUG__
+        usbc_core_printf("[USBCORE] flush type %d queue no %d first gpd %x last gpd %x\r\n", core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no), first_gpd, last_gpd);
+        //usbc_core_dump_gpd_list(first_gpd, last_gpd);
+#endif
+        if ( pQueue->notify_complete != NULL )
+        {
+            if ( first_gpd == NULL )
+            {
+                /* just indicate a notification */
+                usbc_data_trace(MD_TRC_USBCORE_CLASS_FLUSH_SW_QUEUE, queue_no, num, 0x00, 0x00);
+                usbc_trace_warn(USBCORE_CLASS_FLUSH_SW_QUEUE_PS, queue_no, num, 0x00, 0x00);
+                pQueue->notify_complete(pQueue->class_device_id, NULL);
+            } else {
+                usbc_io_request_t* request = NULL;
+                usbc_data_trace(MD_TRC_USBCORE_CLASS_FLUSH_SW_QUEUE, queue_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);                
+                usbc_trace_warn(USBCORE_CLASS_FLUSH_SW_QUEUE_PS, queue_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
+                request = (usbc_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(first_gpd);
+                request->next_request = NULL;
+                request->first_gpd = first_gpd;
+                request->last_gpd = last_gpd;
+                pQueue->notify_complete(pQueue->class_device_id, request);
+            }
+        }
+    }
+    else
+    {
+        usbc_data_trace(MD_TRC_USBCORE_CLASS_FLUSH_SW_QUEUE, queue_no, num, 0x00, 0x00);
+        usbc_trace_warn(USBCORE_CLASS_FLUSH_SW_QUEUE_PS, queue_no, num, 0x00, 0x00);
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool usbc_class_device_flush_rx_io_with_submit(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_queue_t* pQueue = NULL;
+    hif_queue_type_e core_queue_hif_type;
+    hif_flush_type_e core_queue_flush_type;
+    qbm_gpd* first_gpd  = NULL;
+    qbm_gpd* last_gpd   = NULL;
+    kal_uint32 num = 0;
+    qbm_gpd* curr_gpd = NULL;
+    usbc_io_request_t* request = NULL;
+    usbc_core_t *pUsbCore = usbc_core_get_instance();
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    ASSERT(core_queue_hif_type == HIFQ_TYPE_RX);
+    USBC_QUEUE_GPD_TAKE_MUTEX(pUsbCore->rx_submit_enhmuexid[queue_no & ~PIPE_QUEUE_RX_MASK]);
+
+    core_queue_flush_type = HIFQ_FLUSH_DEQ;
+    // Flush GPDs that are configured in hardware, and submit to USB driver
+    num = usbc_core_flush_hifusbq_gpd(core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no), core_queue_flush_type, (void**)&first_gpd, (void**)&last_gpd);
+    if ( num != 0 )
+    {
+        usbc_data_trace(MD_TRC_USBCORE_CLASS_FLUSH_HW_QUEUE, queue_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
+        curr_gpd = first_gpd;
+        while(curr_gpd)
+        {
+            usbc_trace_info(USBCORE_FLUSH_RX_HW_GPD_WITH_SUBMIT, queue_no & ~PIPE_QUEUE_RX_MASK, curr_gpd, QBM_DES_GET_DATALEN(curr_gpd));
+        
+            QBM_DES_SET_DATALEN(curr_gpd, 0);
+            QBM_DES_SET_HWO(curr_gpd);
+            qbm_cal_set_checksum(curr_gpd);
+            QBM_CACHE_FLUSH(curr_gpd, sizeof(qbm_gpd));
+            
+            if(curr_gpd == last_gpd) break;
+            curr_gpd = QBM_DES_GET_NEXT(curr_gpd);
+        }
+        request = (usbc_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(first_gpd);
+        request->next_request = NULL;
+        request->first_gpd = first_gpd;
+        request->last_gpd = last_gpd;
+        usbc_class_device_submit_io_request_priv(core_queue_hif_type, pQueue, request, queue_no);
+    }
+    
+    // Flush GPDs that are buffered in DRAM, and submit to USB driver
+    num = usbc_core_flush_sw_hifusbq_gpd(core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no), core_queue_flush_type, (void**)&first_gpd, (void**)&last_gpd);
+    if ( num != 0 )
+    {
+        usbc_data_trace(MD_TRC_USBCORE_CLASS_FLUSH_SW_QUEUE, queue_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
+        curr_gpd = first_gpd;
+        while(curr_gpd)
+        {
+            usbc_trace_info(USBCORE_FLUSH_RX_SW_GPD_WITH_SUBMIT, queue_no & ~PIPE_QUEUE_RX_MASK, curr_gpd, QBM_DES_GET_DATALEN(curr_gpd));
+
+            QBM_DES_SET_DATALEN(curr_gpd, 0);
+            QBM_DES_SET_HWO(curr_gpd);
+            qbm_cal_set_checksum(curr_gpd);
+            QBM_CACHE_FLUSH(curr_gpd, sizeof(qbm_gpd));
+        
+            if(curr_gpd == last_gpd) break;
+            curr_gpd = QBM_DES_GET_NEXT(curr_gpd);
+        }
+        request = (usbc_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(first_gpd);
+        request->next_request = NULL;
+        request->first_gpd = first_gpd;
+        request->last_gpd = last_gpd;
+        usbc_class_device_submit_io_request_priv(core_queue_hif_type, pQueue, request, queue_no);
+    }
+    USBC_QUEUE_GPD_GIVE_MUTEX(pUsbCore->rx_submit_enhmuexid[queue_no & ~PIPE_QUEUE_RX_MASK]);
+    return KAL_TRUE;
+}
+
+
+kal_bool usbc_class_device_change_notify_complete(
+    kal_uint8 class_device_id, kal_uint8 queue_no,
+    void (*notify_complete)(kal_uint8 class_device_id, usbc_io_request_t* io_request))
+{
+    usbc_core_queue_t* pQueue = NULL;
+    hif_queue_type_e core_queue_hif_type;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    pQueue->notify_complete = notify_complete;
+
+    return KAL_TRUE;
+}
+
+
+kal_bool usbc_class_device_set_hif_disconnect(kal_uint8 class_device_id)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if ( (class_device_id >= pUsbCore->total_class_devices) ||
+         (pUsbCore->class_device[class_device_id].state != USBC_CORE_CLASS_DEVICE_STATE_REGISTERED) )
+    {
+        ASSERT(0);
+        return KAL_FALSE;
+    }
+
+    usbc_normal_hif_disconnect();
+
+    return KAL_TRUE;
+}
+
+
+void usbc_wk_notify_timeout()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 class_device_id = 0;
+    kal_uint8 i;
+
+    USBC_CLASS_REMOTE_WK_LOCK(pUsbCore->usbc_class_renotify_mutex);
+    for(i=0; i<pUsbCore->total_class_devices; i++)
+    {
+        if(pUsbCore->func_notify_list[i] == KAL_TRUE)
+        {
+            class_device_id = i;
+            pUsbCore->func_notify_list[i] = KAL_FALSE;
+            break;
+        }
+    }
+
+    if (i == pUsbCore->total_class_devices)
+    {
+        pUsbCore->wk_eventid = NULL;
+        USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_renotify_mutex);
+        return;
+    }
+    USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_renotify_mutex);
+
+    // check the access of the function
+    if ( !pUsbCore->is_func_be_accessed[class_device_id] )
+    {
+        usbc_set_wk_notify_timer(class_device_id);
+    }
+}
+
+
+void usbc_set_wk_notify_timer(kal_uint8 class_device_id)
+{
+    eventid         eid;
+    kal_uint8       nInterface;
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    /*
+     * To prevent race condition of event cancelling and set,
+     * there shall be only one such event for simplicity.
+     */
+    ASSERT(NULL != pUsbCore->usbc_es_wk_notify_g);
+
+    usbc_trace_info(USBCORE_REMOTE_WK_SET_NOTIFY_TIMER, class_device_id);
+
+    USBC_CLASS_REMOTE_WK_LOCK(pUsbCore->usbc_class_renotify_mutex);
+
+    // usb a bitmap to maintain the list of function wakeup notification
+    pUsbCore->func_notify_list[class_device_id] = KAL_TRUE;
+
+    // get the firtst interface ot the function
+    nInterface = usbc_class_device_get_1st_interface(class_device_id);
+    // send function remote wakeup notification via HIF driver
+    usbc_normal_hif_ss_wk_notify(nInterface); 
+
+    if (NULL == pUsbCore->wk_eventid)
+    {
+        eid = evshed_set_event(
+                pUsbCore->usbc_es_wk_notify_g,
+                usbc_wk_notify_timeout,     // timeout handler
+                NULL, /* event_hf_param */
+                USBC_WK_NOTIFY_CHECK_MS); /* elapse_time */
+        ASSERT(eid);
+    }
+
+    USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_renotify_mutex);
+}
+
+
+kal_bool usbc_class_device_func_remote_wk(kal_uint8 class_device_id)
+{
+
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_bool isDeviceSuspend;
+    usbc_ind_t          ind_to_enqueue;
+    usbc_func_state_e    state;
+
+    usbc_trace_info(USBCORE_REMOTE_WK_START, class_device_id);
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    /* Check whether the requested function is capable to wakeup the host and remote wakeup is enabled.
+       Return KAL_FALSE if the function is not valid to wakeup host
+     */
+    if ( pUsbCore->class_device[class_device_id].query_func_wk_status(class_device_id) != 0x03 )
+    {
+        usbc_trace_error(USBCORE_REMOTE_WK_INVALID, class_device_id, pUsbCore->class_device[class_device_id].query_func_wk_status(class_device_id));
+        EXT_ASSERT(0, USBCORE_LOC_NO_ABILITY_TO_REMOTE_WK, (kal_uint32)usbcore_classid_to_module(class_device_id), 
+                (kal_uint32)(pUsbCore->class_device[class_device_id].query_func_wk_status(class_device_id)));
+        return KAL_FALSE;
+    }
+
+    // check for the remote wakeup once a function at the same time
+    USBC_CLASS_REMOTE_WK_LOCK(pUsbCore->usbc_class_remote_wk_mutex);
+
+    // reset the status of function accessing of class device id
+    USBC_CLASS_REMOTE_WK_LOCK(pUsbCore->usbc_class_func_access_mutex);
+    pUsbCore->is_func_be_accessed[class_device_id] = KAL_FALSE;
+    USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_func_access_mutex);
+
+    isDeviceSuspend = (pUsbCore->state == USBC_USB_STATE_SUSPENDED)? KAL_TRUE:KAL_FALSE;
+
+    /* If it is resumed from device suspend,
+            then send hifusb_remote_wakeup first and wait for the resume callback to know LPM state to U0.
+       If it is resumed from function suspend,
+            then send notification to resume the suspended function in USB Core context.
+     */
+    if ( isDeviceSuspend )
+    {
+        usbc_trace_info(USBCORE_REMOTE_WK_DEVICE, class_device_id);      
+        if(pUsbCore->usb_low_power_enable)
+        {
+            while(pUsbCore->waiting_ap_clk_disable_flag ){
+                kal_sleep_task(USBC_DEV_RESUME_DURATION_TICK);
+            }            
+            usbc_core_mask_wakeup_event(KAL_TRUE);
+            usbc_core_set_clock_cg(KAL_TRUE);            
+            usbc_core_mask_intr(KAL_FALSE);
+        }
+        usb_idle_set_clockGating(KAL_FALSE);    // nofity USBIDLE that it does not have to gate the clock of USB IP 
+        usbc_normal_hif_remote_wakeup();
+    }
+
+    //else if ( pUsbCore->class_device[class_device_id].is_func_suspend )
+    if ( pUsbCore->class_device[class_device_id].is_func_suspend )
+    {
+        // block until device resume
+        while ( isDeviceSuspend )
+        {
+            kal_sleep_task(USBC_DEV_RESUME_DURATION_TICK);
+            isDeviceSuspend = (pUsbCore->state_in_hisr == USBC_USB_STATE_SUSPENDING)? KAL_TRUE:KAL_FALSE;
+            usbc_trace_warn(USBCORE_REMOTE_WK_DEVICE_WAIT, class_device_id);
+        }
+
+        usbc_trace_info(USBCORE_REMOTE_WK_FUNC, class_device_id);
+        // call HIF driver API to send function wakeup notification, and resend if needed
+        if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+        {
+            usbc_set_wk_notify_timer(class_device_id);
+        }
+
+        /*if class_device is AP owner, do not notify MD class in task ,because setup packet will be send to AP
+        , so notify MD class here.*/
+        if(USB_CLASS_OWNER_MD != pUsbCore->class_device[class_device_id].owner)
+        {
+            usbc_core_notify_function_state_resume(class_device_id);
+        }
+        else
+        {
+            // send callback to notify class device of resuming
+            state = USBC_FUNC_STATE_RESUME;
+            // Enqueue USB function state which will be handled in USB context later.
+            ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
+            ind_to_enqueue.ext = class_device_id;
+            ind_to_enqueue.data = (kal_uint8)state;
+            usbc_enqueue_ind(&ind_to_enqueue);
+            // Wake up USBCORE task to process indications.
+            hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+        }
+
+    }
+
+    // release for the remote wakeup of a function
+    USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_remote_wk_mutex);
+
+    return KAL_TRUE;
+}
+
+void usbc_class_device_netifx_suspend_notify(kal_uint8 class_device_id, kal_bool suspend, kal_bool remote_wakeup)
+{
+    usbcore_usbidle_l4_power_saving_req_struct *rsp_msg_p;
+
+    if ( 1 
+#ifdef __USB_RNDIS_SUPPORT__    
+         && (usbc_core_get_instance()->class_device[class_device_id].class_type != USB_CLASS_RNDIS)
+#endif
+#ifdef __USB_MBIM_SUPPORT__
+         && (usbc_core_get_instance()->class_device[class_device_id].class_type != USB_CLASS_MBIM)
+#endif
+#ifdef __USB_ECM_SUPPORT__
+         && (usbc_core_get_instance()->class_device[class_device_id].class_type != USB_CLASS_ECM)
+#endif
+       )
+    {
+        ASSERT(0);
+        return;
+    }       
+
+    // In current implemnntation, only notifying L4 of USB suspended/resuming with remote wakeup is allowed
+    ASSERT(remote_wakeup);
+    if( suspend )
+    {
+        rsp_msg_p = (usbcore_usbidle_l4_power_saving_req_struct*)construct_local_para(sizeof(usbcore_usbidle_l4_power_saving_req_struct), TD_RESET);
+        ASSERT(rsp_msg_p);
+        rsp_msg_p->notify_suspend = suspend;
+        rsp_msg_p->notify_suspend_with_remote_wk = remote_wakeup;
+        usb_idle_set_l4_power_saving(KAL_TRUE);
+        msg_send6(MOD_USBCORE,  // src module
+                  MOD_USBIDLE,  // dst module
+                  0,       // sap id
+                  MSG_ID_USBCORE_IDLE_NOTIFY_TO_L4,
+                  (local_para_struct*)rsp_msg_p,
+                  0);    
+    }
+    else
+    {
+        usb_idle_set_l4_power_saving(KAL_FALSE);
+        usb_idle_event_notify_to_l4(suspend, remote_wakeup);
+    }        
+}
+
+kal_bool usbc_class_device_check_ep_empty(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_queue_t* pQueue = NULL;
+    hif_queue_type_e core_queue_hif_type;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    return usbc_core_check_hifusbq_empty(core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no));
+}
+
+kal_uint8 usbc_class_device_get_phy_queue_num(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_queue_t* pQueue = NULL;
+    hif_queue_type_e core_queue_hif_type;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    return HIFUSB_EPNO_2_QNO(pQueue->ep_no);
+}
+
+kal_bool usbc_class_device_set_header_rule(kal_uint32 header_rule, void *ph_addr, void *xh_addr, kal_uint16 ph_length, kal_uint16 xh_length)
+{
+    usb_header_rule_data_t rule_data = {.ph_start_ptr = ph_addr, .xh_start_ptr = xh_addr, .ph_size = ph_length, .xh_size = xh_length};
+
+    return hifusbq_set_header_rule((usb_header_rule_enum)header_rule, &rule_data);
+}
+
+kal_bool usbc_class_device_set_stall(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_queue_t  *pQueue = NULL;
+    hif_queue_type_e    core_queue_hif_type;
+    kal_bool 			is_tx;
+	
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    pQueue->state = USBC_CORE_QUEUE_STATE_STALL;
+    if(pQueue->owner == USB_CLASS_OWNER_MD){
+        is_tx = core_queue_hif_type == HIFQ_TYPE_TX ? KAL_TRUE : KAL_FALSE;
+        usbc_core_set_stall(is_tx, pQueue->ep_no);
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool usbc_class_device_clear_stall(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_queue_t  *pQueue = NULL;
+    hif_queue_type_e    core_queue_hif_type;
+    kal_bool 			is_tx;
+	
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    pQueue->state = USBC_CORE_QUEUE_STATE_ACTIVE;    
+    if(pQueue->owner == USB_CLASS_OWNER_MD){
+        is_tx = core_queue_hif_type == HIFQ_TYPE_TX ? KAL_TRUE : KAL_FALSE;
+        usbc_core_clear_stall(is_tx, pQueue->ep_no);
+    }
+    return KAL_TRUE;
+}
+
+kal_bool usbc_class_device_start_data_q(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+	usbc_core_queue_t  *pQueue = NULL;
+    hif_queue_type_e    core_queue_hif_type;
+	kal_bool 			is_tx;
+	
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type)) {
+        return KAL_FALSE;
+    }
+
+    is_tx = core_queue_hif_type == HIFQ_TYPE_TX ? KAL_TRUE : KAL_FALSE;
+    usbc_core_start_dataq(is_tx, HIFUSB_EPNO_2_QNO(pQueue->ep_no));
+
+	return KAL_TRUE;
+}
+
+void usbc_class_device_stall_ep0(void)
+{
+    usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+}
+
+usb_class_owner_e usbc_class_get_class_device_owner(kal_uint8 class_device)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    
+    return pUsbCore->class_device[class_device].owner;
+}
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_cosim.c b/mcu/middleware/hif/usbcore/src/usbcore_cosim.c
new file mode 100644
index 0000000..f12d3d2
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_cosim.c
@@ -0,0 +1,246 @@
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "hif_usb.h"
+#include "usbcore_main.h"
+#include "usbcore_ind_q.h"
+#include "usbcore_hif.h"
+#include "hifusb_qmu.h"
+#include "usbcore_class_device.h"
+#include "hif_ior.h"
+#include "qmu_bm_util.h"
+#include "qmu_bm.h"
+#include "hmu.h"
+#include "hmu_conf_data.h"
+#include "sysservice_msgid.h"
+#include "hif_mw_msgid.h"
+#include "usbcore_cosim.h"
+
+/************************************************
+ * USBHIF driver APIs for ESL COSIM
+ ************************************************/
+static kal_bool usbc_cosim_hif_connect(void)
+{
+    /* emulate driver connection */
+    usbc_core_notify_state_attaching();
+
+    return KAL_TRUE;
+}
+
+static kal_bool usbc_cosim_hif_disconnect(void)
+{
+    usbc_core_notify_state_detaching();
+
+    return KAL_TRUE;
+}
+
+/************************************************
+ * USBCORE HIF APIs for ESL COSIM
+ ************************************************/
+
+static void usbc_cosim_hif_factory(void)
+{
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    usbc_esl_printf("Use DRVHIF ESL APIs...\n");
+    usbc_core_set_property = hifusb_set_property_emulate;
+    usbc_core_set_usbhif_address = hifusb_set_usb_address_emulate;
+    usbc_core_set_usbhif_configuration = hifusb_set_usb_configuration_emulate;
+    usbc_core_set_usbhif_connect = usbc_cosim_hif_connect;
+    usbc_core_set_usbhif_disconnect = usbc_cosim_hif_disconnect;
+}
+
+static void usbc_cosim_hif_attach(void)
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();
+    
+    usbc_esl_printf("Emulare USB enumeration...\n");
+
+    /* emulate reset and speed change */
+    usbc_esl_printf("Emulare USB speed change and reset...\n");
+    usbc_core_speed_change(pUsbCore, USBC_USB_SPEED_USB30);
+    usbc_core_notify_speed_change(USBC_USB_SPEED_USB30);
+    usbc_core_set_hif_configuration();      // emulate reset notify
+    usbc_core_notify_state_reset();
+    usbc_cosim_hif_factory();
+
+    /* emulate SetAddress */
+    usbc_esl_printf("Emulare HIF USB set address...\n");
+    usbc_core_set_usb_address(1);     // set USB address
+
+    /* emulate SetConfig */
+    usbc_esl_printf("Emulare USB set configuration...\n");
+    usbc_core_set_usb_configuration(1);   //set USB configuration, assume there is only one configuration in META mode
+    usbc_core_notify_state_attached();
+
+    // Clean USB indication queue
+    usbc_cosim_hif_factory();
+    usbc_empty_ind_queue();
+}
+
+static void usbc_cosim_notify_data_connect(void)
+{
+    module_type dest_mod;
+    msg_type msg_id;
+    usbc_class_device_esl_connect_parm  *rsp_msg_p;
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    usbc_esl_printf("Set USB class to connected state...\n");
+
+    // change USB classes state to transfer data
+    rsp_msg_p = (usbc_class_device_esl_connect_parm*)construct_local_para(sizeof(usbc_class_device_esl_connect_parm), TD_RESET);
+    ASSERT(rsp_msg_p);
+    rsp_msg_p->class_device_id = 0;
+    msg_id = MSG_ID_USBCLASS_USBCORE_ESL_ENTER_CONNECTED_STATE_REQ;
+
+    switch ((pUsbCore->class_device[0]).class_type)
+    {
+#ifdef __USB_MBIM_SUPPORT__
+        case USB_CLASS_MBIM:
+            dest_mod = MOD_MBIM;
+            break;
+#endif
+#ifdef __USB_ECM_SUPPORT__
+        case USB_CLASS_ECM:
+            dest_mod = MOD_ECM;
+            break;
+#endif
+#ifdef __USB_RNDIS_SUPPORT__			
+        case USB_CLASS_RNDIS:
+            dest_mod = MOD_RNDIS;
+            break;
+#endif			
+        default:
+            // We assume the first class device must be a NIC for ESL CO-SIM
+            ASSERT(0);
+            return;
+            break;
+     }
+
+     msg_send6(MOD_USBCORE,  // src module
+               dest_mod,  // dst module
+               0,       // sap id
+               msg_id,
+               (local_para_struct*)rsp_msg_p,
+               0); //msg id
+}
+
+/************************************************
+ * USBCORE task APIs for ESL COSIM
+ ************************************************/
+
+kal_bool usbc_cosim_core_task_init(void)
+{
+    usbc_core_t* pUsbCore;
+    kal_char usbc_class_mutex_name[50];
+
+#ifdef IPCORE_NOT_PRESENT
+    hmu_boot_init();
+#endif
+
+    usbc_set_op_mode(USBC_OP_MODE_NORMAL);
+    kal_mem_set(usbc_core_get_instance(), 0, sizeof(usbc_core_t));
+
+    usbc_core_clear_register();
+    usbc_core_clear_status();
+
+    pUsbCore = usbc_core_get_instance();
+    // create enhance mutex
+    sprintf(usbc_class_mutex_name, "USBC_CLASS_REMOTE_WK_MUTEX");
+    pUsbCore->usbc_class_remote_wk_mutex = kal_create_enh_mutex(usbc_class_mutex_name);
+    sprintf(usbc_class_mutex_name, "USBC_CLASS_RENOTIFY_MUTEX");
+    pUsbCore->usbc_class_renotify_mutex = kal_create_enh_mutex(usbc_class_mutex_name);
+    sprintf(usbc_class_mutex_name, "USBC_CLASS_FUNC_ACCESS_MUTEX");
+    pUsbCore->usbc_class_func_access_mutex = kal_create_enh_mutex(usbc_class_mutex_name);
+    if ( NULL == pUsbCore->usbc_class_remote_wk_mutex ||
+         NULL == pUsbCore->usbc_class_renotify_mutex ||
+         NULL == pUsbCore->usbc_class_func_access_mutex )
+    {
+        ASSERT(0);
+    }
+
+    // initial an evnet scheduler
+    pUsbCore->usbc_es_wk_notify_g = evshed_create(
+                        "USBC_WK_NOTIFY", /* timer_name: event scheduler name */
+                        MOD_USBCORE, /* dest_mod_id: system sends timeout message to this module when event scheduler timeout happens */
+                        0, /* fuzz */
+                        (KAL_TICKS_10_MSEC * 255 / 2)); /* max_delay_ticks */
+    if (pUsbCore->usbc_es_wk_notify_g) {
+        evshed_set_index(pUsbCore->usbc_es_wk_notify_g, USBC_WK_NOTIFY_INDEX);
+    } else {
+        ASSERT(0);
+    }
+
+    usbc_normal_hif_factory();
+    usbc_cosim_hif_factory();
+
+    usbc_stack_checkin(USB_CLASS_NUM, NULL);
+
+    return KAL_TRUE;
+}
+
+void usbc_cosim_core_task_main(task_entry_struct* task_entry_ptr)
+{
+    ilm_struct current_ilm;
+    kal_uint32 rt_event;
+    kal_uint16 timer_index; 
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    kal_set_active_module_id(MOD_USBCORE);
+    kal_mem_set(&current_ilm, 0, sizeof(ilm_struct));
+
+    // Emulate USB plug-in for ESL COSIM
+    usbc_cosim_hif_attach();
+    // Emulate USB classes' requests
+    usbc_cosim_notify_data_connect();
+
+    usbc_esl_printf("Start USBCORE task loop...\n");
+    while(1)
+    {
+        while ( msg_get_extq_messages() > 0 )
+        {
+            if ( msg_receive_extq(&current_ilm) != KAL_TRUE )
+            {
+                break;
+            }
+
+            switch (current_ilm.msg_id)
+            {
+                case MSG_ID_TIMER_EXPIRY:
+                    timer_index = evshed_get_index(&current_ilm);
+                    switch (timer_index)
+                    {
+                        case USBC_WK_NOTIFY_INDEX:
+                            ASSERT(0);
+                            evshed_timer_handler(pUsbCore->usbc_es_wk_notify_g);
+                            break;
+
+                        default:
+                            break;
+                    }
+                    break;
+
+                default:
+                    break;
+            }
+
+            destroy_ilm(&current_ilm);
+        }
+
+        /* Wait someone notify HMU to wake up HIF. */
+        rt_event = hmu_hifeg_wait(HIF_DRV_EG_HIF_TICK_EVENT | HIF_DRV_EG_USBC_IND_EVENT);
+        if ((HIF_DRV_EG_HIF_TICK_EVENT & rt_event) &&
+            (pUsbCore->state != USBC_USB_STATE_SUSPENDED))
+        {
+            /* poll HIF queue data */
+            usbc_esl_printf("Start HIF USB poll queue...\n");
+            usbc_normal_hif_poll_queue();
+            usbc_esl_printf("End HIF USB poll queue...\n");
+        }
+        if ((HIF_DRV_EG_USBC_IND_EVENT & rt_event))
+        {
+            /* Handle indications */
+            usbc_normal_hif_process_indications();
+        }
+    }
+}
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_direct.c b/mcu/middleware/hif/usbcore/src/usbcore_direct.c
new file mode 100644
index 0000000..ca0c146
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_direct.c
@@ -0,0 +1,372 @@
+/*!
+ *  @file usbcore_direct.c
+ *  @author Roger Huang <bo-kai.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main functions of usbcore
+ */
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "usbcore_hif.h"
+#include "usbcore_usbstd.h"
+#include "usbcore_main.h"
+#include "hmu.h"
+#include "hmu_conf_data.h"
+#include "sysservice_msgid.h"
+#include "nvram_interface.h"
+#include "nvram_data_items.h"
+#include "usbcore_debug.h"
+
+#include "hif_usb.h"
+#include "usbcore_main.h"
+#include "usbcore_hif.h"
+#include "hifusb_qmu.h"
+#include "hif_ior.h"
+#include "qmu_bm_util.h"
+#include "qmu_bm.h"
+#include "usbcore_ind_q.h"
+#include "usbcore_direct.h"
+#include "ufpm_if.h"
+
+void usbc_direct_hif_usbcore_send_indication()
+{
+    usbc_ind_t ind_to_enqueue;
+
+    ind_to_enqueue.type = USBC_IND_UFPM_POLL;
+    ind_to_enqueue.ext = 0;
+    ind_to_enqueue.data = 0;
+    usbc_enqueue_ind(&ind_to_enqueue);
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+}
+
+void usbc_direct_hif_enable_poll_queue(kal_bool enable)
+{
+    usbc_core_get_instance()->hmu_indication = enable? (HIF_DRV_EG_HIF_TICK_EVENT | HIF_DRV_EG_USBC_IND_EVENT):HIF_DRV_EG_USBC_IND_EVENT;
+
+    if(enable) {
+        usbc_direct_hif_usbcore_send_indication();
+    }
+}
+
+// Notify USB classes for USB evnets
+void usbc_direct_hif_notify_usb_func_event(kal_uint8 class_device_id, usbc_usb_state_e state)
+{
+    usbc_core_indicate_function_state(class_device_id, state);
+
+    return;
+}
+
+// notify USBCORE for USB events
+void usbc_direct_hif_notify_usb_core_event(usbc_usb_state_e state)
+{
+    usbc_core_get_instance()->state = state;
+}
+
+// Notify USBCORE for configuration state, but do not broadcast ATTACHED notification for USB class
+void usbc_direct_hif_attach(usbc_usb_speed_e speed, kal_uint8 address, kal_uint8 configuration)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    // Emulate speed change for USBCORE only
+    pUsbCore->speed = speed;                    // emulate speed change notify: We do not need to re-compose configuration descriptors in MDT, so do NOT use usbc_core_speed_change
+    usbc_core_notify_speed_change(speed);
+    usbc_direct_hif_factory();
+
+    // Emulate SetAddress for USBCORE only
+    usbc_core_set_usb_address(address);     // set USB address
+
+    // Emulate SetConfig for USBCORE only
+    usbc_direct_core_set_config(configuration);
+
+    // Update USBCORE callbacks
+    usbc_direct_hif_factory();
+}
+
+// Notify USBCORE for RESET, but do NOT broadcast RESET notifucation for USB class
+void usbc_direct_hif_detach()
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+
+    // Clean USB indication queue
+    usbc_empty_ind_queue(); 
+
+    usbc_core_set_hif_configuration();
+    pUsbCore->usb_configuration = 0;
+    pUsbCore->state = USBC_USB_STATE_RESET;
+    usbc_core_clear_status();
+}
+
+void usbc_direct_set_config_class_device(kal_uint8 class_device_id, kal_uint8 configuration)
+{
+    #define CFG_TO_INDEX(config)   (config-1)
+
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    usbc_class_set_config_func_t class_set_config_func;
+    usb_class_type_e    type;
+    usb_cfg_param_t     cfg_param;
+
+    cfg_param = pUsbCore->dev_param->mode_param[pUsbCore->mode].cfg_param[CFG_TO_INDEX(configuration)];
+    type = cfg_param.class_type[class_device_id];
+    class_set_config_func = usbc_get_class_set_config_func(type);
+
+    if (class_set_config_func) {
+        class_set_config_func(class_device_id, CFG_TO_INDEX(configuration), cfg_param.class_ctxt[class_device_id]);
+    }
+}
+
+void usbc_direct_core_set_config(kal_uint8 configuration)
+{
+    #define CFG_TO_INDEX(config)   (config-1)
+
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    //kal_bool            result = KAL_TRUE;
+    kal_uint32          idx_class;
+    usb_class_type_e    type;
+    kal_uint32          idx_if;
+    kal_uint32          idx_ep;
+
+    /* Check if configuration is changed */
+    if (pUsbCore->usb_configuration == configuration) {
+        usbc_trace_info(USBCORE_HIF_SET_CONFIG_UNCHANGED);
+        return;
+    }
+    pUsbCore->usb_configuration = configuration;
+
+    /* Reinit usb classes of old configuration */
+    usbc_trace_info(USBCORE_HIF_SET_CONFIG_REINIT_START);
+    usbc_reinit_class();
+    usbc_trace_info(USBCORE_HIF_SET_CONFIG_REINIT_END);
+
+    if (configuration == 0)
+    {  /* Clear all class device / interface / tx_queue / rx_queue number */
+       pUsbCore->total_class_devices = 0;
+       pUsbCore->total_class_interfaces = 0;
+       pUsbCore->total_tx_queues = 0;
+       pUsbCore->total_rx_queues = 0;
+    } else
+    {
+        /* Fill class_device / interface / tx_queue / rx_queue */
+        pUsbCore->total_class_devices = pUsbCore->dev_param->mode_param[pUsbCore->mode].cfg_param[CFG_TO_INDEX(configuration)].class_num;
+        for (idx_class = 0; idx_class < pUsbCore->total_class_devices; idx_class ++)
+        {
+            type = pUsbCore->dev_param->mode_param[pUsbCore->mode].cfg_param[CFG_TO_INDEX(configuration)].class_type[idx_class];
+            pUsbCore->class_device[idx_class].state = USBC_CORE_CLASS_DEVICE_STATE_INITIATED;
+            pUsbCore->class_device[idx_class].class_type = type;
+            pUsbCore->class_device[idx_class].total_pipes = 0;
+        }
+
+        pUsbCore->total_class_interfaces = pUsbCore->resource_interface_number[CFG_TO_INDEX(configuration)];
+        for (idx_if = 0; idx_if < pUsbCore->total_class_interfaces; idx_if ++)
+        {
+            kal_mem_cpy(&pUsbCore->class_interface[idx_if],
+                           &pUsbCore->if_info[CFG_TO_INDEX(configuration)][idx_if].class_interface,
+                           sizeof(usbc_core_class_interface_t));
+            pUsbCore->class_interface[idx_if].state = USBC_CORE_CLASS_INTERFACE_STATE_INITIATED;
+        }
+
+        pUsbCore->total_tx_queues = pUsbCore->resource_ep_tx_number[CFG_TO_INDEX(configuration)];
+        for (idx_ep = 0; idx_ep < pUsbCore->total_tx_queues; idx_ep ++)
+        {
+            kal_mem_cpy(&pUsbCore->tx_queue[idx_ep],
+                           &pUsbCore->ep_tx_info[CFG_TO_INDEX(configuration)][idx_ep].queue_info,
+                           sizeof(usbc_core_queue_t));
+            pUsbCore->tx_queue[idx_ep].state = USBC_CORE_QUEUE_STATE_INITIATED;
+            pUsbCore->class_device[pUsbCore->tx_queue[idx_ep].class_device_id].total_pipes ++;
+        }
+
+        pUsbCore->total_rx_queues = pUsbCore->resource_ep_rx_number[CFG_TO_INDEX(configuration)];
+        for (idx_ep = 0; idx_ep < pUsbCore->total_rx_queues; idx_ep ++)
+        {
+            kal_mem_cpy(&pUsbCore->rx_queue[idx_ep],
+                           &pUsbCore->ep_rx_info[CFG_TO_INDEX(configuration)][idx_ep].queue_info,
+                           sizeof(usbc_core_queue_t));
+            pUsbCore->rx_queue[idx_ep].state = USBC_CORE_QUEUE_STATE_INITIATED;
+            pUsbCore->class_device[pUsbCore->rx_queue[idx_ep].class_device_id].total_pipes ++;
+        }
+    }
+
+    /* According to Ming's comment in 2013/4/24, we can still set old property to hif if usb_configuration is changed to 0 */
+    //usbc_core_set_hif_configuration();
+
+    //usbc_trace_info(USBCORE_HIF_SET_CONFIG_HIF, pUsbCore->usb_configuration);
+    //usbc_core_set_usbhif_configuration(pUsbCore->usb_configuration);
+
+    if (pUsbCore->usb_configuration > 0) {
+        pUsbCore->state = USBC_USB_STATE_ATTACHED;
+    } else {
+        pUsbCore->state = USBC_USB_STATE_ATTACHING;
+    }
+
+
+    return;
+}
+
+
+kal_bool usbc_direct_dispatch_control_setup_packet(kal_uint8 class_device_id, void* pkt_ptr)
+{
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    kal_bool handled = KAL_TRUE;
+    hifusb_setup_packet_t *p_setup = (hifusb_setup_packet_t*)pkt_ptr;
+    kal_uint8 infx;
+
+    pUsbCore->setup_packet.bmRequestType    = p_setup->bmRequestType;
+    pUsbCore->setup_packet.bRequest         = p_setup->bRequest;
+    pUsbCore->setup_packet.wValue           = USBC_EF16P((kal_uint8*)&p_setup->wValue);
+    pUsbCore->setup_packet.wIndex           = USBC_EF16P((kal_uint8*)&p_setup->wIndex);
+    pUsbCore->setup_packet.wLength          = USBC_EF16P((kal_uint8*)&p_setup->wLength);
+
+    infx = usbc_class_device_get_1st_interface(class_device_id);
+
+    if ( (pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_TYPE_MASK) == USBC_REQUEST_TYPE_CLASS &&
+         (pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK) == USBC_REQUEST_RECIP_INTERFACE &&
+         (infx < pUsbCore->total_class_interfaces) ) {
+
+        (pUsbCore->class_interface[infx]).notify_control_setup_packet(class_device_id, pkt_ptr);
+    }
+    else {
+        /* unknown reqeuset */
+        //ASSERT(0);
+        handled = KAL_FALSE;
+    }
+   
+    return handled; 
+}
+
+void usbc_direct_class_device_submit_control_request(ufpm_send_ap_ep0_msg_t* ep0_rsp_ptr, kal_bool isIndication)
+{
+    // Send control results vai UFPM
+    ufpm_set_control_request(ep0_rsp_ptr, isIndication);
+}
+
+kal_bool usbc_direct_hif_usbq_chk_empty(hif_queue_type_e core_queue_hif_type, kal_uint8 logic_queue_no)
+{
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    kal_bool isEmpty;
+    kal_bool isTx = ((core_queue_hif_type == HIFQ_TYPE_RX) || (core_queue_hif_type == HIFQ_TYPE_RX_W_BPS))? KAL_FALSE:KAL_TRUE;
+    kal_uint8 phy_queue_no = (isTx)? HIFUSB_EPNO_2_QNO(pUsbCore->tx_queue[logic_queue_no].ep_no):HIFUSB_EPNO_2_QNO(pUsbCore->rx_queue[logic_queue_no].ep_no);
+
+    isEmpty = hifusb_chk_que_empty(isTx, phy_queue_no);
+
+    usbc_data_trace(MD_TRC_USBCORE_DIRECT_CHK_QUEUE_EMPTY, isTx, logic_queue_no, phy_queue_no, isEmpty);
+
+    return isEmpty;
+}
+
+void usbc_direct_hifusb_set_usb_address_emulate(kal_uint8 address)
+{
+    // Do nothing because USB driver does not have to be notified for speed in USB fast path
+    return;
+}
+
+kal_bool usbc_direct_hifusb_set_usbhif_connect_disconnect()
+{
+    // Do nothing because USB driver does not have to be connect/disconnect USB
+    return KAL_TRUE;
+}
+
+void usbc_direct_init_ufpm_mapping_table(kal_uint8 config_no, kal_uint8 class_device_id, ufpm_usb_mapping_t* perClassMapTlb)
+{
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    usbc_endpoint_info_t    *tx_ep, *rx_ep;
+    usbc_core_queue_t   *tx_q, *rx_q;
+    kal_uint8 idx, mapTlbIdx = 0;
+
+    // Fill Tx EP/queue info into perClassMapTlb
+    for(idx = 0; idx < pUsbCore->resource_ep_tx_number[config_no]; idx++) {
+        tx_ep = &(pUsbCore->ep_tx_info[config_no][idx]);
+        tx_q = &(tx_ep->queue_info);
+
+        if(0 == tx_ep->epdscr_size) {
+            break;
+        }
+        else {
+            if(tx_q->class_device_id == class_device_id) {
+                perClassMapTlb[mapTlbIdx].type = 0x40 | ((tx_q->xfer_type - 1) << 2) | 0x00;
+                perClassMapTlb[mapTlbIdx].map = tx_q->ep_no;
+                perClassMapTlb[mapTlbIdx].maxPktSize = tx_q->max_packet_size;
+                perClassMapTlb[mapTlbIdx].queue_config = tx_q->config;
+                perClassMapTlb[mapTlbIdx].fifo_n = tx_q->fifo_n;
+                mapTlbIdx++;
+            }
+        }
+    }
+
+    // Fill Rx EP/queue info into perClassMapTlb
+    for(idx = 0; idx < pUsbCore->resource_ep_rx_number[config_no]; idx++) {
+        rx_ep = &(pUsbCore->ep_rx_info[config_no][idx]);
+        rx_q = &(rx_ep->queue_info);
+
+        if(0 == rx_ep->epdscr_size) {
+            break;
+        }
+        else {
+            if(rx_q->class_device_id == class_device_id) {
+                perClassMapTlb[mapTlbIdx].type = 0x40 | ((rx_q->xfer_type - 1) << 2) | 0x01;
+                perClassMapTlb[mapTlbIdx].map = rx_q->ep_no;
+                perClassMapTlb[mapTlbIdx].maxPktSize = rx_q->max_packet_size;
+                perClassMapTlb[mapTlbIdx].queue_config = rx_q->config;
+                perClassMapTlb[mapTlbIdx].fifo_n = rx_q->fifo_n;
+                mapTlbIdx++;
+            }
+        }
+    }
+
+    return;
+}
+
+kal_bool usbc_direct_hif_init(void)
+{
+    kal_bool        result = KAL_FALSE;
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    result = hifusb_init_ufp();
+    ASSERT(result);
+    return result;
+}
+
+
+void usbc_direct_set_usb_mapping(kal_bool isTx, kal_uint8 md_q_no, kal_uint8 ap_ep_no)
+{
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+
+    if(isTx) {
+        pUsbCore->tx_queue[md_q_no].ep_no = ap_ep_no;
+
+    } else {
+        pUsbCore->rx_queue[md_q_no].ep_no = ap_ep_no;
+    }
+}
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_direct_ut.c b/mcu/middleware/hif/usbcore/src/usbcore_direct_ut.c
new file mode 100644
index 0000000..4ff1011
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_direct_ut.c
@@ -0,0 +1,99 @@
+/*!
+ *  @file usbcore_direct_ut.c
+ *  @author Roger Huang <bo-kai.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main functions of usbcore
+ */
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "usbcore_hif.h"
+#include "usbcore_usbstd.h"
+#include "usbcore_main.h"
+#include "hmu.h"
+#include "hmu_conf_data.h"
+#include "sysservice_msgid.h"
+#include "nvram_interface.h"
+#include "nvram_data_items.h"
+#include "usbcore_debug.h"
+
+#include "hif_usb.h"
+#include "usbcore_main.h"
+#include "usbcore_hif.h"
+#include "hifusb_qmu.h"
+#include "hif_ior.h"
+#include "qmu_bm_util.h"
+#include "qmu_bm.h"
+#include "usbcore_ind_q.h"
+#include "usbcore_direct.h"
+#include "ufpm_if.h"
+
+usbc_usb_speed_e usbc_direct_ut_get_speed()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    return pUsbCore->speed;
+}
+
+kal_uint8 usbc_direct_ut_get_address()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    return pUsbCore->usb_address;
+}
+
+kal_uint8 usbc_direct_ut_get_config()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    return pUsbCore->usb_configuration;
+}
+
+usbc_usb_state_e usbc_direct_ut_get_state()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    return pUsbCore->state;
+}
+
+kal_uint8 usbc_direct_ut_get_total_device()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    return pUsbCore->total_class_devices;
+}
+
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_dual_owner.c b/mcu/middleware/hif/usbcore/src/usbcore_dual_owner.c
new file mode 100644
index 0000000..6f4d349
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_dual_owner.c
@@ -0,0 +1,616 @@
+/*!
+ *  @file usbcore_dual_owner.c
+ *  @author Yuhao.Ye <yuhao.ye@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides functions of usbcore dual owner handle
+ */
+
+#include "kal_public_api.h"
+#include "usbcore_main.h"
+#include "usbcore_hif.h"
+#include "usbcore_common.h"
+#include "usbcore_dual_owner.h"
+#include "usbcore_usbstd.h"
+#include "usbcore_debug.h"
+#include "hif_mw_msgid.h"
+#include "us_timer.h"
+#include "sleepdrv_interface.h"
+
+dual_usb_owner_msg_s g_dual_usb_owner_msg = {0};
+char apusb_ctrl_data_buffer[1024] = {0};
+kal_bool g_write_done_flag;
+kal_uint32 g_apusb_rsp_flag = APUBS_SETUP_RSP_IDLE;
+
+void dual_usb_owner_write_done_callback()
+{
+    g_write_done_flag = KAL_TRUE;
+}
+kal_bool dual_usb_owner_send_msg_over_ccci()
+{
+    kal_int32 write_ret = 0;
+    kal_uint32 tick_count = 0;
+    g_write_done_flag = KAL_FALSE;
+    
+    write_ret = nccci_write(CCCI_USB_FWD_CHANNEL, &g_dual_usb_owner_msg, g_dual_usb_owner_msg.msg_hdr.msg_length);
+    if(write_ret < 0){
+        /*error handle*/        
+        usbc_trace_error(USBCORE_DUAL_OWNER_CCCI_WRITE, write_ret);
+        EXT_ASSERT(0, USBCORE_LOC_SEND_OVER_CCCI_FAIL, (kal_uint32)g_dual_usb_owner_msg.msg_hdr.msg_type, (kal_uint32)g_dual_usb_owner_msg.msg_hdr.msg_length);
+        return KAL_FALSE;
+    }
+    else if(write_ret == 0)
+    {
+        /*wait for callback function*/
+        while(1)
+        {
+            kal_sleep_task(USBC_DEV_DURATION_CCCI_DL_DONE_TICK);
+            /*sleep, wait for AP response, then break*/
+            if(g_write_done_flag ==  KAL_TRUE)
+            {
+                write_ret = nccci_write(CCCI_USB_FWD_CHANNEL, &g_dual_usb_owner_msg, g_dual_usb_owner_msg.msg_hdr.msg_length);
+                break;
+            }
+            
+            if((++tick_count) > USB_DUAL_OWNER_WRITE_DONE_MAX_TICK)
+            {
+                /*error log*/                
+                usbc_trace_error(USBCORE_DUAL_OWNER_RECEIVE_CCCI_DL_DONE_TIMEOUT);                
+                //EXT_ASSERT(0, USBCORE_LOC_SEND_OVER_CCCI_TIMEOUT, (kal_uint32)g_dual_usb_owner_msg.msg_hdr.msg_type, (kal_uint32)g_dual_usb_owner_msg.msg_hdr.msg_length);
+                return KAL_FALSE;       
+            }
+        }
+    }
+    else if(write_ret < g_dual_usb_owner_msg.msg_hdr.msg_length){
+        /*error handle*/        
+        usbc_trace_error(USBCORE_DUAL_OWNER_CCCI_WRITE, write_ret);
+        return KAL_FALSE;
+    }
+
+    /*write OK*/
+    return KAL_TRUE;
+
+}
+
+kal_bool dual_usb_owner_read_data_over_ccci(char * buffer, kal_uint32 size)
+{
+    kal_uint32 read_ret;
+
+    read_ret = nccci_read(CCCI_USB_FWD_CHANNEL, buffer, size);
+    if(read_ret != size)
+    {
+        /*error handle*/        
+        usbc_trace_error(USBCORE_DUAL_OWNER_CCCI_READ, read_ret);        
+        EXT_ASSERT(0, USBCORE_LOC_READ_OVER_CCCI_FAIL, 0, 0);
+        return KAL_FALSE;
+    }
+    return KAL_TRUE;
+}
+
+dual_usb_owner_class_type_e class_device_type_to_dual_class_type(usb_class_type_e type)
+{
+    dual_usb_owner_class_type_e transfer_type;
+    switch(type)
+    {
+#ifdef __USB_ACM_SUPPORT__
+        case USB_CLASS_ACM1:
+            transfer_type = USB_CLASS_TYPE_CDC_ACM1;
+            break;
+        case USB_CLASS_ACM2:
+            transfer_type = USB_CLASS_TYPE_CDC_ACM2;
+            break;
+        case USB_CLASS_ACM3:
+            transfer_type = USB_CLASS_TYPE_CDC_ACM3;
+            break;
+#endif
+#ifdef __USB_ADB_SUPPORT__
+        case USB_CLASS_ADB:
+            transfer_type = USB_CLASS_TYPE_ADB;
+            break;
+#endif
+//#ifdef __USB_MSD_SUPPORT__
+        case USB_CLASS_MS:
+            transfer_type = USB_CLASS_TYPE_MS;
+            break;
+//#endif
+        default:
+            transfer_type = USB_CLASS_TYPE_CDC_ACM1;
+            break;
+    }
+    return transfer_type;
+}
+
+
+void dual_usb_owner_load_device_info()
+{
+    usb_deivce_info_s device_info = {0};    
+    usbc_core_t *pUsbCore = usbc_core_get_instance();        
+    kal_uint32 device_class_idx, interface_idx, ep_idx;
+    kal_uint32 total_ep_num, total_if_num;
+    kal_uint32 if_num;
+    class_device_info_s *class_device_info;
+    interface_info_s *interface_info;
+    endpoint_info_s *endpont_info;
+    kal_uint32 ap_class_device_num = 0;
+    
+    for(device_class_idx = 0; device_class_idx < pUsbCore->total_class_devices; device_class_idx++)
+    {
+        total_ep_num = 0;
+        if(pUsbCore->class_device[device_class_idx].owner == USB_CLASS_OWNER_MD)
+            continue;
+        pUsbCore->config_has_ap_port = KAL_TRUE;
+        class_device_info = &device_info.class_device_info[ap_class_device_num];
+        class_device_info->class_device_id = device_class_idx;
+        class_device_info->class_device_type = class_device_type_to_dual_class_type(pUsbCore->class_device[device_class_idx].class_type);       
+        total_if_num = pUsbCore->class_device[device_class_idx].device_instance.total_interfaces;
+        class_device_info->total_interface_num = total_if_num;
+        usbc_trace_info(USBCORE_DUAL_OWNER_DEBUG_ATTACHED_INFO, "device_id", device_class_idx, "class_type", class_device_info->class_device_type );
+
+        for(interface_idx = 0; interface_idx < total_if_num; interface_idx++)
+        {
+            interface_info = &class_device_info->if_info[interface_idx];
+        
+            if_num = pUsbCore->class_device[device_class_idx].device_instance.interface_no[interface_idx];
+            interface_info->interface_id = if_num;
+            interface_info->interface_type = pUsbCore->class_interface[if_num].interface_type;
+            usbc_trace_info(USBCORE_DUAL_OWNER_DEBUG_ATTACHED_INFO, "if_num", if_num, "if_type",  interface_info->interface_type );
+        }
+        for ( ep_idx = 0; ep_idx < MAX_USBCORE_QUEUE_NUM; ep_idx++ )
+        {
+            if(pUsbCore->tx_queue[ep_idx].class_device_id == device_class_idx)
+            {
+                endpont_info = &class_device_info->ep_info[total_ep_num++];
+                endpont_info->class_device_id = device_class_idx;
+                endpont_info->maxpacketsize = pUsbCore->tx_queue[ep_idx].max_packet_size;
+                endpont_info->ep_type = pUsbCore->tx_queue[ep_idx].xfer_type;
+                endpont_info->endpoint_address = pUsbCore->tx_queue[ep_idx].ep_no | USBC_REQUEST_DIR_IN;                
+                usbc_trace_info(USBCORE_DUAL_OWNER_DEBUG_ATTACHED_INFO, "ep_num", endpont_info->endpoint_address, "ep_class",  device_class_idx );
+            }
+
+            if(pUsbCore->rx_queue[ep_idx].class_device_id == device_class_idx)
+            {
+                endpont_info = &class_device_info->ep_info[total_ep_num++];
+                endpont_info->class_device_id = device_class_idx;
+                endpont_info->maxpacketsize = pUsbCore->rx_queue[ep_idx].max_packet_size;
+                endpont_info->ep_type = pUsbCore->rx_queue[ep_idx].xfer_type;
+                endpont_info->endpoint_address = pUsbCore->rx_queue[ep_idx].ep_no | USBC_REQUEST_DIR_OUT;                
+                usbc_trace_info(USBCORE_DUAL_OWNER_DEBUG_ATTACHED_INFO, "ep_num", endpont_info->endpoint_address, "ep_class",  device_class_idx );
+            }
+        }
+        ap_class_device_num++;
+    }
+    device_info.total_class_device = ap_class_device_num;
+
+    kal_mem_cpy(&(g_dual_usb_owner_msg.msg_data), &device_info, sizeof(usb_deivce_info_s));
+    return ;
+}
+
+void dual_usb_wait_ap_suspend_done_timeout()
+{
+    usbc_trace_warn(USBCORE_WAIT_AP_SUSPEND_DOWN_TIMEOUT);
+    usbc_core_get_instance()->waiting_ap_clk_disable_flag = KAL_FALSE;    
+    usbc_core_mask_intr(KAL_FALSE);
+    SleepDrv_UnlockSleep(SLEEP_CTL_USBCORE, SMP);
+}
+
+void dual_usb_wait_ap_attach_done_timeout()
+{
+    usbc_trace_warn(USBCORE_WAIT_AP_ATTACH_DOWN_TIMEOUT);
+    usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_RECEIVE);
+}
+
+kal_bool dual_usb_owner_send_device_state(kal_uint32 type, kal_uint8 ext)
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();  
+    kal_uint32 msg_type = NOTIFY_MSG_ID_NUM;
+    kal_bool ret;
+    kal_uint32 length = sizeof(dual_usb_owner_msg_hdr_s);
+    kal_mem_set(&g_dual_usb_owner_msg, 0, sizeof(dual_usb_owner_msg_s));
+
+    switch(type)
+    {
+        case USBC_USB_STATE_ATTACHING:        
+        case USBC_USB_STATE_DETACHED:
+            return KAL_TRUE;
+        case USBC_USB_STATE_ATTACHED:
+            msg_type = NOTIFY_EVT_ATTACHED;
+            length += sizeof(usb_deivce_info_s);
+            /*load data*/
+            dual_usb_owner_load_device_info();       
+            if(pUsbCore->config_has_ap_port)
+                kal_set_timer(pUsbCore->usbc_ap_rsp_attached_done_timerid, dual_usb_wait_ap_attach_done_timeout, NULL, 20 * KAL_TICKS_100_MSEC_REAL, 0);
+            break;
+        case USBC_USB_STATE_DETACHING:
+            return KAL_TRUE;      
+        case USBC_USB_STATE_SUSPENDING:
+            if(pUsbCore->state_in_hisr != USBC_USB_STATE_SUSPENDING)
+                return KAL_TRUE;
+            msg_type = NOTIFY_EVT_SUSPEND;   
+            g_dual_usb_owner_msg.msg_hdr.msg_type = msg_type;
+            g_dual_usb_owner_msg.msg_hdr.msg_length = length;
+            ret = dual_usb_owner_send_msg_over_ccci();
+            usbc_trace_warn(USBCORE_DUAL_OWNER_NOTIFY_USB_STATE, msg_type, length, ret);
+
+            if(pUsbCore->usb_low_power_enable)
+            {
+                pUsbCore->waiting_ap_clk_disable_flag = KAL_TRUE;            
+                msg_type = NOTIFY_EVT_SUSPENDED;   
+                g_dual_usb_owner_msg.msg_hdr.msg_type = msg_type;
+                g_dual_usb_owner_msg.msg_hdr.msg_length = length;
+                ret = dual_usb_owner_send_msg_over_ccci();                
+                kal_set_timer(pUsbCore->usbc_ap_rsp_suspend_done_timerid, dual_usb_wait_ap_suspend_done_timeout, NULL, USBC_AP_RSP_CHECK_MS, 0);
+                usbc_trace_warn(USBCORE_DUAL_OWNER_NOTIFY_USB_STATE, msg_type, length, ret);
+            }
+            return ret;
+        case USBC_USB_STATE_SUSPENDED:
+            return KAL_TRUE;
+        case USBC_USB_STATE_RESUME:
+            msg_type = NOTIFY_EVT_RESUME;
+            break;
+        case USBC_USB_STATE_RESET:
+            msg_type = NOTIFY_EVT_RESET;
+            length += sizeof(kal_uint32);
+            *(kal_uint32*)(g_dual_usb_owner_msg.msg_data) = (kal_uint32)ext;
+            usbc_core_get_instance()->ap_response_reset_evt_done = KAL_FALSE;
+            usbc_core_get_instance()->ap_response_evt_time = ust_get_current_time();
+            break;
+        case USBC_USB_STATE_PWRDOWN:
+            msg_type = NOTIFY_EVT_IP_PWRDOWN;
+            break;
+        default:
+            msg_type = type;
+            break;
+    }
+    g_dual_usb_owner_msg.msg_hdr.msg_type = msg_type;
+    g_dual_usb_owner_msg.msg_hdr.msg_length = length;
+
+    ret = dual_usb_owner_send_msg_over_ccci();
+    usbc_trace_warn(USBCORE_DUAL_OWNER_NOTIFY_USB_STATE, msg_type, length, ret);
+
+    return ret;
+}
+
+kal_bool dual_usb_owner_send_request( mdusb_msg_id_e msg_type)
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();  
+    kal_mem_set(&g_dual_usb_owner_msg, 0, sizeof(dual_usb_owner_msg_s));
+
+    g_dual_usb_owner_msg.msg_hdr.msg_type = msg_type;
+    g_dual_usb_owner_msg.msg_hdr.msg_length = sizeof(dual_usb_owner_msg_hdr_s) + sizeof(usbc_setup_packet_t);
+    kal_mem_cpy(&(g_dual_usb_owner_msg.msg_data), &(pUsbCore->setup_packet), sizeof(usbc_setup_packet_t));
+
+    if(msg_type == NOTIFY_EVT_FEATURE_SC)
+        usbc_trace_warn(USBCORE_DUAL_OWNER_NOTIFY_FEATURE_SC, pUsbCore->setup_packet.bRequest, pUsbCore->setup_packet.wValue, pUsbCore->setup_packet.wIndex);
+    else
+        usbc_trace_warn(USBCORE_DUAL_OWNER_NOTIFY_SEND_CLASS_REQUEST, pUsbCore->setup_packet.bRequest, pUsbCore->setup_packet.wValue, pUsbCore->setup_packet.wIndex);
+    
+    return dual_usb_owner_send_msg_over_ccci();
+}
+
+void dual_usb_owner_send_feature_request()
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();  
+    kal_uint8 bRecip = pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK;
+    kal_bool ret = 0;
+    ret = dual_usb_owner_send_request(NOTIFY_EVT_FEATURE_SC);
+
+    /*Set/clear STALL will not response host ACK directly, response host after AP handle done*/
+    if(bRecip == USBC_REQUEST_RECIP_ENDPOINT)
+    {
+        if(ret == KAL_TRUE)
+        {
+            g_apusb_rsp_flag = APUBS_SETUP_RSP_INIT;
+            dual_usb_owner_set_ap_rsp_timer();
+        }
+        else
+        {
+            usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+        }
+    }
+    return;
+}
+
+kal_bool dual_usb_owner_send_req_data( )
+{
+    kal_bool ret = 0;
+    usbc_core_t *pUsbCore = usbc_core_get_instance();    
+    kal_mem_set(&g_dual_usb_owner_msg, 0, sizeof(dual_usb_owner_msg_s));
+
+    g_dual_usb_owner_msg.msg_hdr.msg_type = NOTIFY_EVT_CTRL_DATA;
+    g_dual_usb_owner_msg.msg_hdr.msg_length = sizeof(dual_usb_owner_msg_hdr_s) + pUsbCore->ap_setup_buf_rx_expected_len;
+    kal_mem_cpy(&(g_dual_usb_owner_msg.msg_data), &(pUsbCore->ap_setup_buf), pUsbCore->ap_setup_buf_rx_expected_len);
+    usbc_trace_warn(USBCORE_DUAL_OWNER_SEND_CTRL_OUT_DATA, g_dual_usb_owner_msg.msg_hdr.msg_length);                
+    ret = dual_usb_owner_send_msg_over_ccci();
+    return ret;
+}
+
+void dual_usb_owner_ap_rsp_timeout()
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();  
+
+    /*MD do not receive rsp from AP*/
+    usbc_trace_error(USBCORE_DUAL_OWNER_SEND_CLASS_REQUEST_NO_RSP, pUsbCore->setup_packet.bRequest, pUsbCore->setup_packet.wValue, pUsbCore->setup_packet.wIndex);            
+    //EXT_ASSERT(0, USBCORE_LOC_AP_RESPONSE_TIMEOUT, (kal_uint32)pUsbCore->setup_packet.bRequest, 0);
+    usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);    
+    g_apusb_rsp_flag = APUSB_SETUP_RSP_TIMEOUT;
+}
+
+void dual_usb_owner_set_ap_rsp_timer()
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();    
+    
+    kal_set_timer(pUsbCore->usbc_es_ap_rsp_timerid, dual_usb_owner_ap_rsp_timeout, NULL, USBC_AP_RSP_CHECK_MS, 0);
+    return;
+}
+
+void dual_usb_owner_class_control_request()
+{
+    kal_bool ret;
+    ret = dual_usb_owner_send_request(NOTIFY_EVT_CLASS_CTRL_REQ);
+    if(ret != KAL_TRUE)
+        return;
+
+    g_apusb_rsp_flag = APUBS_SETUP_RSP_INIT;
+    dual_usb_owner_set_ap_rsp_timer();
+
+    return ;
+}
+
+void dual_usb_owner_class_control_complete()
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    
+    if(!(pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_DIR_IN))
+    {
+        (void)dual_usb_owner_send_req_data();
+    }
+    return;
+}
+
+void dual_usb_owner_apusb_remote_wakeup()
+{
+    kal_uint32 class_device_id = 0;
+    
+    dual_usb_owner_read_data_over_ccci((char*)&class_device_id, sizeof(kal_uint32));
+    usbc_class_device_func_remote_wk((kal_uint8)class_device_id);
+
+    kal_mem_set(&g_dual_usb_owner_msg, 0, sizeof(dual_usb_owner_msg_s));
+
+    g_dual_usb_owner_msg.msg_hdr.msg_type = NOTIFY_EVT_FUNCTION_RESUME;
+    g_dual_usb_owner_msg.msg_hdr.msg_length = sizeof(dual_usb_owner_msg_hdr_s) + sizeof(kal_uint32);
+    *(kal_uint32*)g_dual_usb_owner_msg.msg_data = class_device_id;
+    usbc_trace_warn(USBCORE_DUAL_OWNER_RECEIVE_REMOTE_WAKEUP, class_device_id);                
+    dual_usb_owner_send_msg_over_ccci();
+
+    return ;
+}
+
+void dual_usb_owner_apusb_ep_halt()
+{
+    apusb_ep_info_s ep_info = {0};  
+    kal_uint32  i;
+    kal_bool ret;
+    usbc_core_queue_t* pQueue = NULL;
+    usbc_core_t *pUsbCore = usbc_core_get_instance();    
+    ret = dual_usb_owner_read_data_over_ccci((char*)&ep_info, sizeof(apusb_ep_info_s));
+
+    /*TX*/
+    if (ep_info.endpoint_direct)
+    {
+        for ( i=0; i<MAX_USBCORE_QUEUE_NUM; i++ )
+        {
+            if ( (pUsbCore->tx_queue[i].ep_no == ep_info.endpoint_num) &&
+                 (pUsbCore->tx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED) )
+            {
+                pQueue = &pUsbCore->tx_queue[i];
+                break;
+            }
+        }
+    } else {
+        for ( i=0; i<MAX_USBCORE_QUEUE_NUM; i++ )
+        {
+            if ( (pUsbCore->rx_queue[i].ep_no == ep_info.endpoint_num) &&
+                 (pUsbCore->rx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED) )
+            {
+                pQueue = &pUsbCore->rx_queue[i];
+                break;
+            }
+        }
+    }
+
+    if(ret != KAL_TRUE || pQueue == NULL)
+    {
+        EXT_ASSERT(0, USBCORE_LOC_AP_SET_STALL_INVALID_EP, (kal_uint32)ep_info.endpoint_num, (kal_uint32)ep_info.endpoint_direct);
+        return ;
+    }
+
+    pQueue->state = USBC_CORE_QUEUE_STATE_STALL;
+    return;
+}
+
+void dual_usb_owner_ilm_handle()
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();    
+    dual_usb_owner_msg_hdr_s msg_hdr = {0};
+
+    if(KAL_TRUE != dual_usb_owner_read_data_over_ccci((char*)&msg_hdr, sizeof(dual_usb_owner_msg_hdr_s)))
+    {
+        g_apusb_rsp_flag = APUSB_SETUP_RSP_FAIL;
+        return ;
+    }
+
+    if((msg_hdr.msg_length - sizeof(dual_usb_owner_msg_hdr_s)) > 0)
+    {
+        kal_mem_set(&apusb_ctrl_data_buffer, 0 , sizeof(apusb_ctrl_data_buffer));
+        dual_usb_owner_read_data_over_ccci((char*)&apusb_ctrl_data_buffer, msg_hdr.msg_length - sizeof(dual_usb_owner_msg_hdr_s));
+    }
+    
+    usbc_trace_warn(USBCORE_DUAL_OWNER_RECEIVE_ILM_MSG, msg_hdr.msg_type, msg_hdr.msg_length);
+
+    switch(msg_hdr.msg_type)
+    {
+        case APUSB_RSP_STATUS_SUCCESS:
+            /*if g_apusb_rsp_flag != APUBS_SETUP_RSP_INIT, the class request has handled,ignore this msg*/
+            if(g_apusb_rsp_flag != APUBS_SETUP_RSP_INIT)
+                break;
+            
+            kal_cancel_timer(pUsbCore->usbc_es_ap_rsp_timerid);
+            g_apusb_rsp_flag = APUSB_SETUP_RSP_SUCCESS;
+            pUsbCore->ap_setup_buf_rx_expected_len = pUsbCore->setup_packet.wLength;
+
+            if(pUsbCore->setup_packet.wLength > 0)
+            {                
+                /*OUT requset*/
+                kal_mem_set(&(pUsbCore->ap_setup_buf), 0, MAX_USBCORE_CONTROL_REQUEST_BUFFER_SIZE);
+                usbc_core_set_control_request(pUsbCore->ap_setup_buf, pUsbCore->setup_packet.wLength, HIFUSB_CONTROL_REQUEST_TYPE_RECEIVE);
+            }
+            else
+            {
+                /*No data stage requset*/
+                usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_RECEIVE);
+            }
+            break;
+        case APUSB_RSP_STATUS_STALL:
+            /*if g_apusb_rsp_flag != APUBS_SETUP_RSP_INIT, the class request has handled,ignore this msg*/
+            if(g_apusb_rsp_flag != APUBS_SETUP_RSP_INIT)
+                break;
+            
+            kal_cancel_timer(pUsbCore->usbc_es_ap_rsp_timerid);
+            g_apusb_rsp_flag = APUSB_SETUP_RSP_STALL;
+            usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+            break;
+        case APUSB_RSP_SEND_DATA:
+            /*if g_apusb_rsp_flag != APUBS_SETUP_RSP_INIT, the class request has handled,ignore this msg*/
+            if(g_apusb_rsp_flag != APUBS_SETUP_RSP_INIT)
+                break;
+            
+            kal_cancel_timer(pUsbCore->usbc_es_ap_rsp_timerid);
+            g_apusb_rsp_flag = APUSB_SETUP_RSP_DATA;
+            /*copy data to buffer*/   
+            if((msg_hdr.msg_length - sizeof(dual_usb_owner_msg_hdr_s)) != pUsbCore->setup_packet.wLength){
+                /*warning*/                
+                usbc_trace_warn(USBCORE_DUAL_OWNER_IN_DATA_LEN_ERROR, pUsbCore->setup_packet.wLength, (msg_hdr.msg_length - sizeof(dual_usb_owner_msg_hdr_s)));
+            }
+            usbc_core_set_control_request((kal_uint8 *)&apusb_ctrl_data_buffer, pUsbCore->setup_packet.wLength, HIFUSB_CONTROL_REQUEST_TYPE_SEND);
+            break;            
+        case APUSB_NOTIFY_EVT_REMOTE_WAKEUP:
+            dual_usb_owner_apusb_remote_wakeup();
+            break;
+        case APUSB_NOTIFY_EVT_EP_HALT:
+            dual_usb_owner_apusb_ep_halt();
+            break;
+        case APUSB_NOTIFY_EVT_RESET_DONE:
+            pUsbCore->ap_response_reset_evt_done = KAL_TRUE;
+            break;
+        case APUSB_NOTIFY_EVT_SUSPEND_DONE:             
+            kal_cancel_timer(pUsbCore->usbc_ap_rsp_suspend_done_timerid);
+            pUsbCore->usbc_wait_wakeup_event = KAL_TRUE;
+            usbc_core_mask_wakeup_event(KAL_FALSE);                 
+            pUsbCore->waiting_ap_clk_disable_flag = KAL_FALSE;            
+            SleepDrv_UnlockSleep(SLEEP_CTL_USBCORE,SMP);
+            break;
+        case APUSB_NOTIFY_EVT_ATTACHED_DONE:
+            kal_cancel_timer(pUsbCore->usbc_ap_rsp_attached_done_timerid);
+            usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_RECEIVE);
+            break;
+        default:
+            g_apusb_rsp_flag = APUSB_SETUP_RSP_FAIL;
+            break;
+    }
+}
+
+void dual_usb_owner_init()
+{
+    kal_int32 ret = 0;
+    NCCCI_ILM_REGISTRATION_STRUCT nccci_ilm_reg;
+    usbc_core_t *pUsbCore = usbc_core_get_instance();    
+
+    /*init dual usb owner ap rsp timer*/
+    pUsbCore->usbc_es_ap_rsp_timerid = kal_create_timer("USBC_AP_RSP");
+    if (pUsbCore->usbc_es_ap_rsp_timerid == NULL)
+    {        
+        EXT_ASSERT(0, USBCORE_LOC_DUAL_OWNER_TIMER_INIT_FAIL, 0, 0);
+        return;
+    }
+
+    pUsbCore->usbc_ap_rsp_suspend_done_timerid = kal_create_timer("USBC_SUSPEND_RSP");
+    if (pUsbCore->usbc_ap_rsp_suspend_done_timerid == NULL)
+    {        
+        EXT_ASSERT(0, USBCORE_LOC_DUAL_OWNER_TIMER_INIT_FAIL, 0, 1);
+        return;
+    }
+
+    pUsbCore->usbc_ap_rsp_attached_done_timerid = kal_create_timer("USBC_ATTACHED_RSP");
+    if (pUsbCore->usbc_ap_rsp_attached_done_timerid == NULL)
+    {        
+        EXT_ASSERT(0, USBCORE_LOC_DUAL_OWNER_TIMER_INIT_FAIL, 0, 2);
+        return;
+    }
+
+    ret = nccci_open(CCCI_USB_FWD_CHANNEL);
+    if(ret < 0)
+    {
+        EXT_ASSERT(0, USBCORE_LOC_INIT_CCCI_CHANNEL_FAIL_1, 0, 0);
+        return;
+    }
+
+    ret = nccci_ioctl(CCCI_USB_FWD_CHANNEL, NCCCI_IOCTL_SET_DL_CALLBACK, &dual_usb_owner_write_done_callback);
+    if(ret < 0)
+    {
+        EXT_ASSERT(0, USBCORE_LOC_INIT_CCCI_CHANNEL_FAIL_2, 0, 0);
+        return;
+    }
+
+    nccci_ilm_reg.module_id = MOD_USBCORE;
+    nccci_ilm_reg.msg_id = MSG_ID_USBCORE_DUAL_OWNER_MSG_RECEIVE;
+    nccci_ilm_reg.sap = 0;
+    ret = nccci_ioctl(CCCI_USB_FWD_CHANNEL, NCCCI_IOCTL_SET_UL_DONE_ILM, nccci_ilm_reg);
+    if(ret < 0)
+    {
+        EXT_ASSERT(0, USBCORE_LOC_INIT_CCCI_CHANNEL_FAIL_3, 0, 0);
+        return;
+    }
+    return ;
+}
+
+void dual_owner_funciton_register()
+{
+    usbc_dual_owner_init = dual_usb_owner_init;
+    usbc_dual_owner_ilm_handle = dual_usb_owner_ilm_handle;
+    usbc_dual_owner_class_ctrl_request = dual_usb_owner_class_control_request;
+    usbc_dual_owner_class_ctrl_complete = dual_usb_owner_class_control_complete;
+    usbc_dual_owner_send_feature_request = dual_usb_owner_send_feature_request;
+    usbc_dual_owner_notify_event = dual_usb_owner_send_device_state;
+}
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_except.c b/mcu/middleware/hif/usbcore/src/usbcore_except.c
new file mode 100644
index 0000000..928b64f
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_except.c
@@ -0,0 +1,1427 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   usbcore_except.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   USB Core exception mode wrapper.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+
+#include "usbcore_common.h"
+#include "usbcore_main.h"
+#include "usbcore_class_device.h"
+#include "usbcore_hif.h"
+#include "usbcore_except.h"
+
+#include "hifusb_qmu.h"
+#include "hifusb_qmu_except.h"
+#include "hif_usb_except.h"
+
+#if (defined(__MTK_TARGET__) && defined(__PRODUCTION_RELEASE__))
+#include "dcl.h"
+#endif
+
+#define CPU_PMU_CNT_WRAP  (0xFFFFFFFFUL)
+#define CPU_GET_DURATION(_start, _end) \
+    ((_end) >= (_start)) ? ((_end) - (_start)) : (CPU_PMU_CNT_WRAP - (_start) + (_end) + 1))
+
+#ifdef __MTK_TARGET__
+    #ifdef USE_US_TIMER
+        #error "TODO: USE_US_TIMER"
+    #else /*use CPU performance counter, it might be not compatible for MAUI platform*/
+        //#include "cpu.h"
+
+        #define GET_CURR_TICK(_curr_tick) \
+                (_curr_tick) = kal_get_systicks()
+                //cpu_event_counter_get_cycle(_curr_tick)
+    
+        #define GET_DURATION_MS(_start_tick, _end_tick) \
+                kal_ticks_to_milli_secs((CPU_GET_DURATION(_start_tick, _end_tick))
+                //CPU_PMUTICK2MS(cpu_event_get_duration(_start_tick, _end_tick))
+    #endif
+#else
+    #define GET_CURR_TICK(_curr_tick) (_curr_tick) = 0
+
+    #define GET_DURATION_MS(_start_tick, _end_tick) 0
+#endif
+
+/*------------------------------------------------------------------------------
+ * Constant definition.
+ *----------------------------------------------------------------------------*/
+#define USBC_EXCEPT_INFINITE_TIMEOUT    0xffffffff /* No timeout. */
+
+#define USBC_EXCEPT_MIN_ENUM_TIMEOUT    100 /* Minmal USB enumeration timeout in ms. */
+#define USBC_EXCEPT_DEF_ENUM_TIMEOUT    20000 /* Minmal USB enumeration timeout in ms. */
+
+#define USBC_EXCEPT_MIN_TX_TIMEOUT      100 /* Minmal USB tx transfer timeout in ms. */
+#define USBC_EXCEPT_DEF_TX_TIMEOUT      5000 /* Minmal USB tx transfer timeout in ms. */
+
+#define USBC_EXCEPT_CALL_EXCEPT_INIT     0x00000001
+#define USBC_EXCEPT_CALL_CLEAR_CH        0x00000002
+#define USBC_EXCEPT_CALL_RESET_CH        0x00000004
+#define USBC_EXCEPT_CALL_ENUM_LOOP       0x00000008
+#define USBC_EXCEPT_CALL_SUBMIT_GPD      0x00000010
+#define USBC_EXCEPT_CALL_POLL_QUEUE      0x00000020
+#define USBC_EXCEPT_CALL_HIF_STATE       0x00000040
+#define USBC_EXCEPT_CALL_HIF_POLL        0x00000080
+
+#define USBC_EXCEPT_NOTIFY_RESET         0x00000100
+#define USBC_EXCEPT_NOTIFY_SPEED_CHANGE  0x00000200
+
+#define USBC_EXCEPT_CALL_FLUSH           0x00001000
+
+#define USBC_EXCEPT_CLEAR_CH_NG          0x00010000
+#define USBC_EXCEPT_ENUM_LOOP_OK         0x00020000
+#define USBC_EXCEPT_ENUM_LOOP_TO         0x00040000
+#define USBC_EXCEPT_SUBMIT_GPD_NG        0x00080000
+#define USBC_EXCEPT_POLL_QUEUE_NG        0x00100000
+#define USBC_EXCEPT_HIF_STATE_NG         0x00200000
+#define USBC_EXCEPT_HIF_STATE_TO         0x00400000
+#define USBC_EXCEPT_FLUSH_NG             0x01000000
+
+
+#define INVALID_CLASS_DEVICE_ID          0xff
+#define INVALID_PIPE_QUEUE_ID            0xff
+#define PIPE_QUEUE_RX_MASK               0x80
+
+
+/*!
+ *  @brief USB Core control transfer state in exception mode.
+ */
+typedef enum _usbc_except_ct_state {
+    USBC_EXCEPT_CT_READY                = 0,
+    USBC_EXCEPT_CT_SETUP                = 1,
+    USBC_EXCEPT_CT_DATA                 = 2,
+} usbc_except_ct_state_e;
+
+/*!
+ *  @brief USB Core exception mode data path information for troubleshooting.
+ */
+typedef struct _usbc_except_data_log {
+    kal_uint32                          tx_submit_called;
+    kal_uint32                          tx_poll_called;
+    kal_uint32                          tx_completed;
+    qbm_gpd                            *tx_last_gpd_submitted;
+    qbm_gpd                            *tx_last_gpd_polled;
+    kal_uint32                          rx_submit_called;
+    kal_uint32                          rx_poll_called;
+    kal_uint32                          rx_completed;
+    qbm_gpd                            *rx_last_gpd_submitted;
+    qbm_gpd                            *rx_last_gpd_polled;
+} usbc_except_data_log;
+
+/*!
+ *  @brief USB Core exception mode context.
+ */
+typedef struct _usbc_except_doc {
+    /*!
+     *  @brief HIF driver allocated buffer for IN/OUT data of a control transfer in exception mode
+     */
+    kal_uint8                          *ct_data_ptr;
+    /*!
+     *  @brief Bytes used in except_ct_data_ptr
+     */
+    kal_uint32                          ct_data_len;
+    /*!
+     *  @brief Result of the control transfer.
+     */
+    hifusb_control_request_type_e       ct_result;
+    /*!
+     *  @brief Control transfer state.
+     */
+    usbc_except_ct_state_e              ct_state;
+    kal_uint8                           rsvd[2];
+    /*!
+     *  @brief USB enumeration tiemout in unit of ms.
+     */
+    kal_uint32                          enum_timeout; 
+    /*!
+     *  @brief Tx transfer tiemout in unit of ms.
+     */
+    kal_uint32                          tx_timeout; 
+} usbc_except_doc_t;
+
+static usbc_except_doc_t                usbc_except_doc_s;
+#define usbc_except_get_doc()           (&usbc_except_doc_s)
+
+static volatile kal_uint32              usbc_except_flags_s = 0; /* For troubleshooting USBCORE exception mode API.*/
+#define usbc_set_flag(_flag)            usbc_except_flags_s |= (_flag)
+
+static usbc_except_data_log             usbc_except_dlog_s; /* For USBCORE exception mode data path troubleshooting.*/
+#define usbc_dlog_reset() \
+        kal_mem_set( &usbc_except_dlog_s, 0, sizeof(usbc_except_data_log) )
+#define usbc_dlog_submit_gpd(_queue_type, _gpd) \
+    do { \
+        if (HIFQ_TYPE_TX == _queue_type) { \
+            usbc_except_dlog_s.tx_submit_called++; \
+            usbc_except_dlog_s.tx_last_gpd_submitted = (qbm_gpd *)(_gpd); \
+        } else { \
+            usbc_except_dlog_s.rx_submit_called++; \
+            usbc_except_dlog_s.rx_last_gpd_submitted = (qbm_gpd *)(_gpd); \
+        } \
+    } while (0)
+#define usbc_dlog_poll_queue(_queue_type, _gpd_cnt, _gpd) \
+    do { \
+        if (HIFQ_TYPE_TX == _queue_type) { \
+            usbc_except_dlog_s.tx_poll_called++; \
+            if (0 < (_gpd_cnt)) { \
+                usbc_except_dlog_s.tx_completed += (_gpd_cnt); \
+                usbc_except_dlog_s.tx_last_gpd_polled = (_gpd); \
+            } \
+        } else { \
+            usbc_except_dlog_s.rx_poll_called++; \
+            if (0 < (_gpd_cnt)) { \
+                usbc_except_dlog_s.rx_completed += (_gpd_cnt); \
+                usbc_except_dlog_s.rx_last_gpd_polled = (_gpd); \
+            } \
+        } \
+    } while (0)
+
+/*------------------------------------------------------------------------------
+ * Device/configuration/interface/endpoint Descriptors
+ *----------------------------------------------------------------------------*/
+#define USBC_DEF_VID                        0x0E8D
+#define USBC_DEF_PID                        0x7101
+#define USBC_TOTAL_INTERFACE_NUM            2
+#define USBC_INTERFACE_MTK_COM_0            0
+#define USBC_INTERFACE_MTK_COM_1            1
+
+#define USBC_DEF_STR_IDX_MANUFACTURER       0x01
+#define USBC_DEF_STR_IDX_PRODUCT            0x02
+#define USBC_DEF_STR_IDX_SERIALNUM          0x03
+
+#define __CDC_ACM_REPORT_IAD__
+
+/* MODE CDC_ACM Device Descriptors */
+static usbc_device_descriptor_t usbc_device_descriptor_cdc_acm =
+{
+    /* Device Descriptor */
+    0x12,                           /* bLength              */
+    USBC_DT_DEVICE,                 /* DEVICE               */
+    0x0200,                         /* USB 2.0              */
+#ifdef __CDC_ACM_REPORT_IAD__
+    0xEF,                           /* CLASS                */
+    0x02,                           /* Subclass             */
+    0x01,                           /* Protocol             */
+#else
+    0x02,                           /* CLASS                */
+    0x00,                           /* Subclass             */
+    0x00,                           /* Protocol             */
+#endif
+    0x40,                           /* bMaxPktSize0         */
+    USBC_DEF_VID,                   /* idVendor             */
+    USBC_DEF_PID,                   /* idProduct            */
+    0x0001,                         /* bcdDevice            */
+    USBC_DEF_STR_IDX_MANUFACTURER,  /* iManufacturer        */
+    USBC_DEF_STR_IDX_PRODUCT,       /* iProduct             */
+#ifdef __PRODUCTION_RELEASE__
+    0x00,
+#else
+/* under construction !*/
+#endif
+    0x01                            /* One configuration    */
+};
+
+
+/* MODE CDC_ACM Configuration Descriptors */
+static struct _usbc_configuration_descriptor_cdc_acm {
+    usbc_configuration_descriptor_t                 configuration_descriptor;
+#ifdef __CDC_ACM_REPORT_IAD__
+    usbc_interface_association_descriptor_t         interface_association_descriptor;
+#endif
+    usbc_interface_descriptor_t                     control_interface_descriptor;
+    usbc_cs_header_descriptor_t                     cs_header_descriptor;
+    usbc_cs_call_manage_descriptor_t                cs_call_manage_descriptor;
+    usbc_cs_abstract_control_manage_descriptor_t    cs_abstrac_control_manage_descriptor;
+    usbc_cs_union_function_descriptor_t             cs_union_function_descriptor;
+    usbc_endpoint_descriptor_t                      commin_endpoint_descriptor;
+    usbc_interface_descriptor_t                     data_interface_descriptor;
+    usbc_endpoint_descriptor_t                      datain_endpoint_descriptor;
+    usbc_endpoint_descriptor_t                      dataout_endpoint_descriptor;
+} usbc_configuration_descriptor_cdc_acm = {
+{
+    /* Configuration Descriptor */
+    0x09,                       /* bLength              */
+    0x02,                       /* CONFIGURATION        */
+#ifdef __CDC_ACM_REPORT_IAD__
+    0x004B,                     /* length               */
+#else
+    0x0043,                     /* length               */
+#endif
+    USBC_TOTAL_INTERFACE_NUM,   /* bNumInterfaces       */
+    0x01,                       /* bConfigurationValue  */
+    0x00,                       /* iConfiguration       */
+    0x80,                       /* bmAttributes (required + self-powered) */
+    0xFA                        /* power                */
+},
+#ifdef __CDC_ACM_REPORT_IAD__
+{
+    /* Interface Association Descriptor */
+    0x08,                       /* bLength              */
+    USBC_DT_IAD,                /* bDescriptorType      */
+    USBC_INTERFACE_MTK_COM_0,   /* bFristInterface      */
+    0x02,                       /* bInterfaceCount      */
+    0x02,                       /* bFunctionClass       */
+    0x02,                       /* bFunctionSubClass    */
+    0x01,                       /* bFunctionProtocol    */
+    0x00                        /* iFunction            */
+},
+#endif
+{
+    /* Comm Interface Descriptor */
+    0x09,                       /* bLength              */
+    USBC_DT_INTERFACE,          /* INTERFACE            */
+    USBC_INTERFACE_MTK_COM_0,   /* bInterfaceNumber     */
+    0x00,                       /* bAlternatSetting     */
+    0x01,                       /* bNumberEnpoints      */
+    0x02,                       /* bInterface Class     */
+    0x02,                       /* SubClass             */
+    0x01,                       /* Protocol             */
+    0x00                        /* Index of String      */
+},
+{
+    /* CS Header Descriptor */
+    0x05,                       /* bLength;             */
+    0x24,                       /* bDescriptorType;     */
+    0x00,                       /* bDescriptorSubType;  */
+    0x0110                      /* bcdCDC;              */
+},
+{
+    /* CS Call Manage Descriptor */
+    0x05,                       /* bLength              */
+    0x24,                       /* bDescriptorType      */
+    0x01,                       /* bDescriptorSubType   */
+    0x03,                       /* bmCapabilities       */
+    USBC_INTERFACE_MTK_COM_1    /* bDataInterface       */
+},
+{
+    /* CS Abstract Control Manage Descriptor */
+    0x04,                       /* bLength              */
+    0x24,                       /* bDescriptorType      */
+    0x02,                       /* bDescriptorSubType   */
+    0x0F                        /* bmCapabilities       */
+},
+{
+    /* CS Union Function Descriptor */
+    0x05,                       /* bLength;             */
+    0x24,                       /* bDescriptorType;     */
+    0x06,                       /* bDescriptorSubType;  */
+    USBC_INTERFACE_MTK_COM_0,   /* bMasterInterface;    */
+    USBC_INTERFACE_MTK_COM_1    /* bSlaveInterface;     */
+},
+{
+    /* Comm EndpointDescriptor */
+    0x07,                       /* bLength              */
+    0x05,                       /* bDescriptorType      */
+    0x82,                       /* bEndpointAddress     */
+    0x03,                       /* bmAttributes         */
+    0x0040,                     /* wMaxPacketSize       */
+    0x01                        /* bInterval            */
+},
+{
+    /* Data Interface Descriptor */
+    0x09,                       /* bLength              */
+    USBC_DT_INTERFACE,          /* INTERFACE            */
+    USBC_INTERFACE_MTK_COM_1,   /* bInterfaceNumber     */
+    0x00,                       /* bAlternatSetting     */
+    0x02,                       /* bNumberEnpoints      */
+    0x0A,                       /* bInterface Class     */
+    0x00,                       /* SubClass             */
+    0x00,                       /* Protocol             */
+    0x00                        /* Index of String      */
+},
+{
+    /* Data In Endpoint Descriptor */
+    0x07,                       /* bLength              */
+    0x05,                       /* bDescriptorType      */
+    0x81,                       /* bEndpointAddress     */
+    0x02,                       /* bmAttributes         */
+    0x0200,                     /* wMaxPacketSize       */
+    0x00                        /* bInterval            */
+},
+{
+    /* Data Out EndpointDescriptor */
+    0x07,                       /* bLength              */
+    0x05,                       /* bDescriptorType      */
+    0x01,                       /* bEndpointAddress     */
+    0x02,                       /* bmAttributes         */
+    0x0200,                     /* wMaxPacketSize       */
+    0x00                        /* bInterval            */
+}
+};
+
+/* MODE CDC_ACM Device Qualifier Descriptors */
+static usbc_device_qualifier_descriptor_t usbc_device_qualifier_descriptor_cdc_acm =
+{
+    /* Device Qualifier Descriptor */
+    0x0A,                       /* bLength              */
+    USBC_DT_DEVICE_QUALIFIER,   /* Device Qualifier     */
+    0x0200,                     /* USB Version          */
+#ifdef __CDC_ACM_REPORT_IAD__
+    0xEF,                       /* CLASS                */
+    0x02,                       /* Subclass             */
+    0x01,                       /* Protocol             */
+#else
+    0x02,                       /* CLASS                */
+    0x00,                       /* Subclass             */
+    0x00,                       /* Protocol             */
+#endif
+    0x40,                       /* Max Packet Length    */
+    0x01,                       /* Number of other speed config */
+    0x00                        /* Reserved             */
+};
+
+/* Default String Descriptor Language ID */
+static kal_uint8 usbc_string_descriptor_language_default[] =
+{
+    /* String Descriptor */
+    0x04,                       /* bLength              */
+    0x03,                       /* bDescriptorType      */
+    0x09,0x04
+};
+
+
+/* Default String Descriptor Manufacturer */
+static kal_uint8 usbc_string_descriptor_manufacturer_default[] =
+{
+    /* String Descriptor */
+    0x1c,                       /* bLength              */
+    0x03,                       /* bDescriptorType      */
+    'M',0x00,'e',0x00,'d',0x00,'i',0x00,
+    'a',0x00,'T',0x00,'e',0x00,'k',0x00,
+    ' ',0x00,'I',0x00,'n',0x00,'c',0x00,
+    '.',0x00
+};
+
+
+/* Default String Descriptor Product */
+static kal_uint8 usbc_string_descriptor_product_default[] =
+{
+    /* String Descriptor */
+    0x1a,                       /* bLength              */
+    0x03,                       /* bDescriptorType      */
+    'L',0x00,'T',0x00,'E',0x00,' ',0x00,
+    'U',0x00,'S',0x00,'B',0x00,' ',0x00,
+    'C',0x00,'A',0x00,'R',0x00,'D',0x00,
+};
+
+
+/* Default String Descriptor SerialNum */
+static kal_uint8 usbc_string_descriptor_serialnum_default[] =
+{
+    /* String Descriptor Serial Number */
+    0x1a,                       /* bLength              */
+    0x03,                       /* bDescriptorType      */
+    '6',0x00,'6',0x00,'5',0x00,'5',0x00,
+    '4',0x00,'4',0x00,'3',0x00,'3',0x00,
+    '2',0x00,'2',0x00,'1',0x00,'1',0x00
+};
+
+/*------------------------------------------------------------------------------
+ * Private implementation.
+ *----------------------------------------------------------------------------*/
+#define USBC_EXCEPT_MAX_TRACE_NUM 30
+#define USBC_EXCEPT_TRACE_SIG 0xBA000000
+
+kal_uint32 usbc_except_trace[USBC_EXCEPT_MAX_TRACE_NUM];
+kal_uint32 usbc_except_trace_idx = 0;
+void usbc_excpet_log_trace (kal_uint16 func_flag, kal_uint8 ret)
+{
+    usbc_except_trace_idx %= USBC_EXCEPT_MAX_TRACE_NUM;
+
+    usbc_except_trace[usbc_except_trace_idx] = USBC_EXCEPT_TRACE_SIG;
+    usbc_except_trace[usbc_except_trace_idx] |= ((func_flag & 0xFFFF) << 8);
+    usbc_except_trace[usbc_except_trace_idx] |= ret;
+
+    usbc_except_trace_idx ++;
+}
+
+static kal_bool usbc_except_hif_indicate_control_setup_packet(kal_uint8 intf_idx, usbc_setup_packet_t *packet)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    usbc_core_class_interface_t *intf = &pUsbCore->class_interface[intf_idx];
+
+    intf->notify_control_setup_packet(intf->class_device_id, packet);
+    return KAL_TRUE;
+}
+
+static void usbc_except_hif_indicate_control_complete(kal_uint8 intf_idx)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    usbc_core_class_interface_t *intf = &pUsbCore->class_interface[intf_idx];
+
+    intf->notify_control_complete(intf->class_device_id);
+}
+
+static kal_bool usbc_except_hif_set_control_request(kal_uint8 *buffer, kal_uint32 length, usbc_control_request_type_e type)
+{
+    ASSERT(USBC_EXCEPT_CT_SETUP == usbc_except_get_doc()->ct_state);
+    usbc_except_get_doc()->ct_state = USBC_EXCEPT_CT_DATA;
+
+    switch (type) {
+    case USBC_CONTROL_REQUEST_TYPE_SEND:
+        /*
+         * Control IN.
+         */
+        ASSERT(HIFUSB_CONTROL_REQUEST_TYPE_SEND == usbc_except_get_doc()->ct_result);
+        if (length > usbc_except_get_doc()->ct_data_len) {
+            length = usbc_except_get_doc()->ct_data_len;
+        }
+        kal_mem_cpy(usbc_except_get_doc()->ct_data_ptr, buffer, length);
+        usbc_except_get_doc()->ct_data_len = length;
+        usbc_except_get_doc()->ct_result = HIFUSB_CONTROL_REQUEST_TYPE_SEND;
+        break;
+
+    case USBC_CONTROL_REQUEST_TYPE_RECEIVE:
+        /*
+         * Control OUT.
+         */
+        ASSERT(HIFUSB_CONTROL_REQUEST_TYPE_RECEIVE == usbc_except_get_doc()->ct_result);
+        if (usbc_except_get_doc()->ct_data_len > length) {
+            usbc_except_get_doc()->ct_data_len = length;
+        }
+        kal_mem_cpy(buffer, usbc_except_get_doc()->ct_data_ptr, usbc_except_get_doc()->ct_data_len);
+        usbc_except_get_doc()->ct_result = HIFUSB_CONTROL_REQUEST_TYPE_RECEIVE;
+        break;
+    
+    case USBC_CONTROL_REQUEST_TYPE_STALL:
+        /*
+         * HIF driver only allows control IN to return STALL
+         */
+        if (HIFUSB_CONTROL_REQUEST_TYPE_SEND == usbc_except_get_doc()->ct_result) {
+            usbc_except_get_doc()->ct_result = HIFUSB_CONTROL_REQUEST_TYPE_STALL;
+        } else {
+            usbc_except_get_doc()->ct_data_len = 0;
+        }
+        break;
+
+    default:
+        ASSERT(0);
+        usbc_except_get_doc()->ct_data_len = 0;
+        break;
+    }
+    return KAL_TRUE;
+}
+
+static kal_bool usbc_except_hif_set_usb_address(kal_uint8 address)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+
+    pUsbCore->usb_address = address;
+    hifusb_except_set_usb_address(pUsbCore->usb_address);
+
+    return KAL_TRUE;
+}
+
+static kal_bool usbc_except_hif_set_usb_configuration(kal_uint8 configuration)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+
+    pUsbCore->usb_configuration = configuration;
+    hifusb_except_set_usb_configuration(pUsbCore->usb_configuration);
+
+    if ( pUsbCore->usb_configuration > 0 ) {
+        pUsbCore->state = USBC_USB_STATE_ATTACHED;
+    } else {
+        pUsbCore->state = USBC_USB_STATE_ATTACHING;
+    }
+
+    return KAL_TRUE;
+}
+
+static void usbc_except_hif_set_stall(kal_bool is_tx, kal_uint8 nEnd)
+{
+}
+
+static void usbc_except_hif_clear_stall(kal_bool is_tx, kal_uint8 nEnd)
+{
+}
+
+static kal_bool usbc_except_hif_set_usb_testmode(hifusb_test_mode_e testmode)
+{
+    return KAL_FALSE;
+}
+
+static void usbc_except_hif_start_dataq(kal_bool isTx, kal_uint8 q_no)
+{
+}
+
+static void usbc_except_hif_factory(void)
+{
+    usbc_core_indicate_control_setup_packet = usbc_except_hif_indicate_control_setup_packet;
+    usbc_core_indicate_control_complete = usbc_except_hif_indicate_control_complete;
+    usbc_core_indicate_alternate_setting = usbc_core_notify_alternate_setting;
+    usbc_core_indicate_stall = usbc_core_notify_stall;
+    usbc_core_set_control_request = usbc_except_hif_set_control_request;
+    usbc_core_set_property = hifusb_except_set_property;
+    usbc_core_set_usb_address = usbc_except_hif_set_usb_address;
+    usbc_core_set_usb_configuration = usbc_except_hif_set_usb_configuration;
+    usbc_core_set_stall = usbc_except_hif_set_stall;
+    usbc_core_clear_stall = usbc_except_hif_clear_stall;
+    usbc_core_set_usb_testmode = usbc_except_hif_set_usb_testmode;
+    usbc_core_start_dataq = usbc_except_hif_start_dataq;
+}
+
+static void usbc_except_load_settings(void)
+{
+    if (usbc_core_get_hmu_info()->enum_timeout >= USBC_EXCEPT_MIN_ENUM_TIMEOUT) {
+        usbc_except_get_doc()->enum_timeout = usbc_core_get_hmu_info()->enum_timeout;
+    } else {
+        usbc_except_get_doc()->enum_timeout = USBC_EXCEPT_DEF_ENUM_TIMEOUT;
+    }
+    if (usbc_core_get_hmu_info()->tx_timeout >= USBC_EXCEPT_MIN_TX_TIMEOUT) {
+        usbc_except_get_doc()->tx_timeout = usbc_core_get_hmu_info()->tx_timeout;
+    } else {
+        usbc_except_get_doc()->tx_timeout = USBC_EXCEPT_DEF_TX_TIMEOUT;
+    }
+}
+
+static void usbc_except_init_context(void)
+{
+    /*if project suppot factory mode, use factory PID*/
+    if(USBC_OP_MODE_FACTORY == usbc_get_op_mode())
+        usbc_device_descriptor_cdc_acm.idProduct = usb_get_factory_mode_pid();
+
+    /*
+     * Initialize USB Core context for exception mode.
+     */
+    kal_mem_set(usbc_except_get_doc(), 0, sizeof(usbc_except_doc_t));
+    usbc_except_load_settings();
+
+    usbc_set_op_mode(USBC_OP_MODE_EXCEPTION);
+    kal_mem_set(usbc_core_get_instance(), 0, sizeof(usbc_core_t));
+
+    usbc_except_hif_factory();
+    usbc_resource_reset();
+    usbc_core_clear_register();
+    usbc_core_clear_status();
+}
+
+static void usbc_except_read_configuration(void)
+{
+    /*
+     * Currently, we assume exception mode only uses 1 CDC/ACM COM port configuration.
+     */
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    /* configure descriptor */
+    kal_mem_cpy(pUsbCore->descriptors.device, &usbc_device_descriptor_cdc_acm, USBC_DEVICE_DESC_SIZE);
+    kal_mem_cpy(pUsbCore->descriptors.configuration[0], &usbc_configuration_descriptor_cdc_acm, sizeof(usbc_configuration_descriptor_cdc_acm));
+    kal_mem_cpy(&pUsbCore->device_qualifier_descriptor   , &usbc_device_qualifier_descriptor_cdc_acm, sizeof(usbc_device_qualifier_descriptor_t));
+
+    pUsbCore->total_class_devices           = 1;
+    /* configure 1st class device */
+    pUsbCore->class_device[0].class_type    = USB_CLASS_ACM2;
+    pUsbCore->class_device[0].state         = USBC_CORE_CLASS_DEVICE_STATE_INITIATED;
+    pUsbCore->class_device[0].total_pipes   = 3;
+
+    pUsbCore->total_class_interfaces        = 2;
+    /* configure 1st class interface */
+    pUsbCore->class_interface[0].class_device_id    = 0;
+    pUsbCore->class_interface[0].interface_no       = usbc_configuration_descriptor_cdc_acm.control_interface_descriptor.bInterfaceNumber;
+    pUsbCore->class_interface[0].interface_type     = USBC_INTERFACE_TYPE_CDC_ACM_CONTROL;
+    pUsbCore->class_interface[0].state              = USBC_CORE_CLASS_INTERFACE_STATE_INITIATED;
+    pUsbCore->class_interface[0].alternate_setting  = 0;
+
+    /* configure 2nd class interface */
+    pUsbCore->class_interface[1].class_device_id    = 0;
+    pUsbCore->class_interface[1].interface_no       = usbc_configuration_descriptor_cdc_acm.data_interface_descriptor.bInterfaceNumber;
+    pUsbCore->class_interface[1].interface_type     = USBC_INTERFACE_TYPE_CDC_ACM_DATA;
+    pUsbCore->class_interface[1].state              = USBC_CORE_CLASS_INTERFACE_STATE_INITIATED;
+    pUsbCore->class_interface[1].alternate_setting  = 0;
+
+    pUsbCore->total_tx_queues               = 2;
+    /* configure 1st transmit queue */
+    pUsbCore->tx_queue[0].class_device_id   = 0;
+    pUsbCore->tx_queue[0].state             = USBC_CORE_QUEUE_STATE_INITIATED;
+    pUsbCore->tx_queue[0].pipe_type         = USBC_PIPE_TYPE_CDC_ACM_DATA_IN;
+    pUsbCore->tx_queue[0].xfer_type         = HIFUSB_EP_XFER_TYPE_BULK;
+    pUsbCore->tx_queue[0].ep_no             = usbc_configuration_descriptor_cdc_acm.datain_endpoint_descriptor.bEndpointAddress & ~0x80;
+    pUsbCore->tx_queue[0].max_packet_size   = usbc_configuration_descriptor_cdc_acm.datain_endpoint_descriptor.wMaxPacketSize;
+    pUsbCore->tx_queue[0].fifo_n            = 2;
+#ifdef ENABLE_QMU_CHECKSUM
+    pUsbCore->tx_queue[0].config            = HIFUSB_QMU_EN | HIFUSB_QMU_CS_EN | HIFUSB_QMU_TXQ_ZLP | HIFUSB_QMU_TXQ_EMPTY_ENQ | HIFUSB_QMU_TXQ_SPD_EN;
+#else
+    pUsbCore->tx_queue[0].config            = HIFUSB_QMU_EN | HIFUSB_QMU_TXQ_ZLP | HIFUSB_QMU_TXQ_EMPTY_ENQ | HIFUSB_QMU_TXQ_SPD_EN;
+#endif
+
+    /* configure 2nd transmit queue */
+    pUsbCore->tx_queue[1].class_device_id   = 0;
+    pUsbCore->tx_queue[1].state             = USBC_CORE_QUEUE_STATE_INITIATED;
+    pUsbCore->tx_queue[1].pipe_type         = USBC_PIPE_TYPE_CDC_ACM_COMM_IN;
+    pUsbCore->tx_queue[1].xfer_type         = HIFUSB_EP_XFER_TYPE_INT;
+    pUsbCore->tx_queue[1].ep_no             = usbc_configuration_descriptor_cdc_acm.commin_endpoint_descriptor.bEndpointAddress & ~0x80;
+    pUsbCore->tx_queue[1].max_packet_size   = usbc_configuration_descriptor_cdc_acm.commin_endpoint_descriptor.wMaxPacketSize;
+    pUsbCore->tx_queue[1].fifo_n            = 1;
+#ifdef ENABLE_QMU_CHECKSUM
+    pUsbCore->tx_queue[1].config            = HIFUSB_QMU_EN | HIFUSB_QMU_CS_EN;
+#else
+    pUsbCore->tx_queue[1].config            = HIFUSB_QMU_EN;
+#endif
+
+    pUsbCore->total_rx_queues   = 1;
+    /* configure 1st receive queue */
+    pUsbCore->rx_queue[0].class_device_id   = 0;
+    pUsbCore->rx_queue[0].state             = USBC_CORE_QUEUE_STATE_INITIATED;
+    pUsbCore->rx_queue[0].pipe_type         = USBC_PIPE_TYPE_CDC_ACM_DATA_OUT;
+    pUsbCore->rx_queue[0].xfer_type         = HIFUSB_EP_XFER_TYPE_BULK;
+    pUsbCore->rx_queue[0].ep_no             = usbc_configuration_descriptor_cdc_acm.dataout_endpoint_descriptor.bEndpointAddress & ~0x80;
+    pUsbCore->rx_queue[0].max_packet_size   = usbc_configuration_descriptor_cdc_acm.dataout_endpoint_descriptor.wMaxPacketSize;
+    pUsbCore->rx_queue[0].fifo_n            = 2;
+#ifdef ENABLE_QMU_CHECKSUM
+    pUsbCore->rx_queue[0].config            = HIFUSB_QMU_EN | HIFUSB_QMU_CS_EN;
+#else
+    pUsbCore->rx_queue[0].config            = HIFUSB_QMU_EN;
+#endif
+
+    /* String descriptor */
+    pUsbCore->string_descriptor[0] = (usbc_string_descriptor_t*)usbc_string_descriptor_language_default;
+    pUsbCore->string_descriptor[USBC_DEF_STR_IDX_MANUFACTURER] = (usbc_string_descriptor_t*)usbc_string_descriptor_manufacturer_default;
+    pUsbCore->string_descriptor[USBC_DEF_STR_IDX_PRODUCT] = (usbc_string_descriptor_t*)usbc_string_descriptor_product_default;
+    pUsbCore->string_descriptor[USBC_DEF_STR_IDX_SERIALNUM] = (usbc_string_descriptor_t*)usbc_string_descriptor_serialnum_default;
+    pUsbCore->resource_string_number = 4;
+
+    /* Reset speed */
+    pUsbCore->speed = USBC_USB_SPEED_MIN;
+}
+
+static void usbc_except_restart_watchdog(void)
+{
+#if (defined(__MTK_TARGET__) && defined(__PRODUCTION_RELEASE__))
+    DCL_HANDLE dcl_wdt_handle;
+
+    dcl_wdt_handle = DclWDT_Open(DCL_WDT, 0);
+    DclWDT_Control(dcl_wdt_handle,WDT_CMD_RESTART, 0);
+    DclWDT_Close(dcl_wdt_handle);
+
+#endif  // #if (defined(__MTK_TARGET__) && defined(__PRODUCTION_RELEASE__))
+}
+
+/*------------------------------------------------------------------------------
+ * HIF callback functions.
+ *----------------------------------------------------------------------------*/
+static void usbc_except_compile_ep_companion(kal_uint8 *dst_desc, kal_uint8 transfer_type)
+{
+    USBC_SET_DESC_LENGTH(dst_desc, USBC_ENDPOINT_COMPANION_DESC_SIZE);
+    USBC_SET_DESC_TYPE(dst_desc, USBC_DT_ENDPOINT_COMPANION);
+    USBC_SET_EPC_ATTRIBUTES(dst_desc, 0);
+
+    if (USBC_BULK_TRANSFER == transfer_type) {
+        USBC_SET_EPC_MAX_BURST(dst_desc, 1);
+        USBC_SET_EPC_BYTES_PER_INTERVAL(dst_desc, 0);
+    } else {
+        USBC_SET_EPC_MAX_BURST(dst_desc, 0);
+        USBC_SET_EPC_BYTES_PER_INTERVAL(dst_desc, 0x40);
+    }
+}
+
+static void usbc_except_configuration_speed_change(usbc_core_t *pUsbCore, usbc_usb_speed_e speed)
+{
+    kal_uint32 total_len;
+    kal_uint32 bytes_read;
+    kal_uint32 bytes_written;
+    kal_uint8 *desc_read;
+    kal_uint8 *desc_to_write;
+    kal_uint32 desc_len;
+    kal_uint32 idx_ep;
+    kal_uint8  conf[USBC_MAX_CONF_SIZE];
+
+    kal_mem_cpy(conf, pUsbCore->descriptors.configuration[0], USBC_MAX_CONF_SIZE);
+    bytes_read = 0;
+    bytes_written = 0;
+    total_len = USBC_GET_CONF_TOTAL_LENGTH(conf);
+
+    while (bytes_read < total_len)
+    {
+        desc_read = conf + bytes_read;
+        desc_to_write = pUsbCore->descriptors.configuration[0] + bytes_written;
+        desc_len = USBC_GET_DESC_LENGTH(desc_read);
+
+        kal_mem_cpy(desc_to_write, desc_read, desc_len);
+        bytes_written += desc_len;
+
+        switch (USBC_GET_DESC_TYPE(desc_read))
+        {
+            case USBC_DT_ENDPOINT:
+            {
+                if (USBC_BULK_TRANSFER == USBC_GET_EP_TRANSFER_TYPE(desc_to_write))
+                {
+                    switch (speed) {
+                        case USBC_USB_SPEED_USB11:
+                        {
+                            USBC_SET_EP_MAX_PACKET_SIZE(desc_to_write, USBC_USB11_MAX_PACKET_SIZE);
+                            break;
+                        }
+                        case USBC_USB_SPEED_USB20:
+                        {
+                            USBC_SET_EP_MAX_PACKET_SIZE(desc_to_write, USBC_USB20_MAX_PACKET_SIZE);
+                            break;
+                        }
+                        case USBC_USB_SPEED_USB30:
+                        {
+                            USBC_SET_EP_MAX_PACKET_SIZE(desc_to_write, USBC_USB30_MAX_PACKET_SIZE);
+                            break;
+                        }
+                        default:
+                        {
+                            break;
+                        }
+                    }
+                }
+                if (speed == USBC_USB_SPEED_USB30) {
+                    if (bytes_written + USBC_ENDPOINT_COMPANION_DESC_SIZE <= USBC_MAX_CONF_SIZE) {
+                        usbc_except_compile_ep_companion(desc_to_write + desc_len, USBC_GET_EP_TRANSFER_TYPE(desc_to_write));
+                        bytes_written += USBC_ENDPOINT_COMPANION_DESC_SIZE;
+                    }
+                }
+                break;
+            }  
+            default:
+               break;
+        }
+        bytes_read += desc_len;
+    }
+
+    /*
+     * Patch configuration descriptor.
+     */
+    if (speed == USBC_USB_SPEED_USB30) {
+        USBC_SET_CONF_MAX_POWER(pUsbCore->descriptors.configuration[0], (896 / USBC_USB30_POWER_DESC_UINT));
+    }
+    USBC_SET_CONF_TOTAL_LENGTH(pUsbCore->descriptors.configuration[0], bytes_written);
+
+    /*
+     * Modify max packet size in tx/rx endpoint queue info
+     */
+    for (idx_ep = 0; idx_ep < pUsbCore->total_tx_queues; idx_ep ++)
+    {
+        if (pUsbCore->tx_queue[idx_ep].xfer_type == HIFUSB_EP_XFER_TYPE_BULK)
+        {
+            switch (speed) {
+                case USBC_USB_SPEED_USB11:
+                {
+                    pUsbCore->tx_queue[idx_ep].max_packet_size = USBC_USB11_MAX_PACKET_SIZE;
+                    break;
+                }
+                case USBC_USB_SPEED_USB20:
+                {
+                    pUsbCore->tx_queue[idx_ep].max_packet_size = USBC_USB20_MAX_PACKET_SIZE;
+                    break;
+                }
+                case USBC_USB_SPEED_USB30:
+                {
+                    pUsbCore->tx_queue[idx_ep].max_packet_size = USBC_USB30_MAX_PACKET_SIZE;
+                    break;
+                }
+                default:
+                {
+                    break;
+                }
+            }
+        }
+    }
+    for (idx_ep = 0; idx_ep < pUsbCore->total_rx_queues; idx_ep ++)
+    {
+        if (pUsbCore->rx_queue[idx_ep].xfer_type == HIFUSB_EP_XFER_TYPE_BULK)
+        {
+            switch (speed) {
+                case USBC_USB_SPEED_USB11:
+                {
+                    pUsbCore->rx_queue[idx_ep].max_packet_size = USBC_USB11_MAX_PACKET_SIZE;
+                    break;
+                }
+                case USBC_USB_SPEED_USB20:
+                {
+                    pUsbCore->rx_queue[idx_ep].max_packet_size = USBC_USB20_MAX_PACKET_SIZE;
+                    break;
+                }
+                case USBC_USB_SPEED_USB30:
+                {
+                    pUsbCore->rx_queue[idx_ep].max_packet_size = USBC_USB30_MAX_PACKET_SIZE;
+                    break;
+                }
+                default:
+                {
+                    break;
+                }
+            }
+        }
+    }
+}
+static void usbc_except_speed_change(usbc_core_t *pUsbCore, usbc_usb_speed_e speed)
+{
+	usbc_device_descriptor_t *dev_desc;
+
+    pUsbCore->speed = speed;
+    dev_desc = (usbc_device_descriptor_t *)pUsbCore->descriptors.device;
+
+    /*
+     *  Device descriptor speed change
+     */
+    switch (speed) {
+        case USBC_USB_SPEED_USB30:
+            dev_desc->bcdUSB = 0x0300;
+            dev_desc->bMaxPacketSize0 = USBC_USB30_EP0_PACKET_SIZE;
+            break;
+    
+        default:
+            dev_desc->bcdUSB = 0x0210;
+            dev_desc->bMaxPacketSize0 = 64;
+            break;
+    }
+     
+    /*
+     *  Configuration descriptor speed change
+     */
+    usbc_except_configuration_speed_change(pUsbCore, speed);
+}
+
+static void usbc_core_notify_usb_event(hifusb_notify_evt_e event, void *data)
+{
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    usbc_usb_speed_e    speed;
+
+    USBC_EXCEPTION_MODE_CHECK();
+
+    /*
+     * In exception mode: 
+     *
+     * 1. For simplicity, we don't indicate any USB event to USB Class.
+     * 2. When HIF driver indicates RESET event to USBCORE,
+     * we will notify USB Class about the current USB speed and then 
+     * set HIF IP related configruation.
+     *
+     */
+    switch (event) {
+    case HIFUSB_NOTIFY_EVT_RESET:
+        usbc_set_flag(USBC_EXCEPT_NOTIFY_RESET);
+        speed = *(usbc_usb_speed_e*)data;
+        usbc_excpet_log_trace(USBC_EXCEPT_NOTIFY_RESET, 0);
+        if (speed != pUsbCore->speed) {
+            /*
+             * Change USB link speed and related settings.
+             */
+            usbc_set_flag(USBC_EXCEPT_NOTIFY_SPEED_CHANGE);
+            usbc_except_speed_change(pUsbCore, speed);
+            usbc_core_notify_speed_change(speed);
+            usbc_excpet_log_trace(USBC_EXCEPT_NOTIFY_SPEED_CHANGE, 0);
+        }
+        pUsbCore->state = USBC_USB_STATE_RESET;
+        usbc_core_set_hif_configuration();
+        usbc_core_notify_state_reset();
+        pUsbCore->usb_configuration = 0;
+        usbc_except_get_doc()->ct_state = USBC_EXCEPT_CT_READY;
+
+        break;
+
+    default:
+        break;
+    }
+}
+
+static hifusb_control_request_type_e usbc_except_notify_usb_except_control_in(hifusb_setup_packet_t *p_setup, void *p_buf, kal_uint32 *p_len)
+{
+    usbc_core_t                    *pUsbCore = usbc_core_get_instance();
+    hifusb_control_request_type_e   result;
+
+    USBC_EXCEPTION_MODE_CHECK();
+
+    ASSERT(USBC_EXCEPT_CT_READY == usbc_except_get_doc()->ct_state);
+    usbc_except_get_doc()->ct_data_ptr = (kal_uint8 *)p_buf;
+    usbc_except_get_doc()->ct_data_len = HIFUSB_EXCEPT_EP_BUF_SZ;
+    usbc_except_get_doc()->ct_result = HIFUSB_CONTROL_REQUEST_TYPE_SEND;
+    usbc_except_get_doc()->ct_state = USBC_EXCEPT_CT_SETUP;
+
+    usbc_core_dispatch_control_setup_packet(pUsbCore, p_setup);
+    ASSERT(USBC_EXCEPT_CT_DATA == usbc_except_get_doc()->ct_state);
+
+    *p_len = usbc_except_get_doc()->ct_data_len;
+    result = usbc_except_get_doc()->ct_result;
+    usbc_core_notify_control_complete(pUsbCore);
+    usbc_except_get_doc()->ct_state = USBC_EXCEPT_CT_READY;
+
+    return result;
+}
+
+static hifusb_control_request_type_e usbc_except_notify_usb_except_control_out(hifusb_setup_packet_t *p_setup, void *p_buf, kal_uint32 len)
+{
+    usbc_core_t                    *pUsbCore = usbc_core_get_instance();
+    hifusb_control_request_type_e   result;
+
+    USBC_EXCEPTION_MODE_CHECK();
+
+    ASSERT(USBC_EXCEPT_CT_READY == usbc_except_get_doc()->ct_state);
+    usbc_except_get_doc()->ct_data_ptr = (kal_uint8 *)p_buf;
+    usbc_except_get_doc()->ct_data_len = len;
+    usbc_except_get_doc()->ct_result = HIFUSB_CONTROL_REQUEST_TYPE_RECEIVE;
+    usbc_except_get_doc()->ct_state = USBC_EXCEPT_CT_SETUP;
+
+    usbc_core_dispatch_control_setup_packet(pUsbCore, p_setup);
+    ASSERT(USBC_EXCEPT_CT_DATA == usbc_except_get_doc()->ct_state);
+
+    result = usbc_except_get_doc()->ct_result;
+    usbc_core_notify_control_complete(pUsbCore);
+    usbc_except_get_doc()->ct_state = USBC_EXCEPT_CT_READY;
+
+    return result;
+}
+
+/*------------------------------------------------------------------------------
+ * Public interface.
+ *----------------------------------------------------------------------------*/
+
+kal_bool usbc_except_init(void)
+{
+    usbc_set_flag(USBC_EXCEPT_CALL_EXCEPT_INIT);
+
+    usbc_except_load_settings();
+    hifusbq_except_initial();
+
+    usbc_excpet_log_trace(USBC_EXCEPT_CALL_EXCEPT_INIT, 1);
+    return KAL_TRUE;
+}
+
+kal_bool usbc_except_clear_ch(kal_uint8 class_device_id, kal_uint8 queue_no)
+{
+    usbc_core_queue_t  *queue;
+    hif_queue_type_e    queue_type;
+
+    usbc_set_flag(USBC_EXCEPT_CALL_CLEAR_CH);
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &queue, &queue_type)) {
+        usbc_set_flag(USBC_EXCEPT_CLEAR_CH_NG);
+        usbc_excpet_log_trace(USBC_EXCEPT_CALL_CLEAR_CH, 0);
+        return KAL_FALSE;
+    }
+
+    hifusbq_except_clear_q(queue_type, HIFUSB_EPNO_2_QNO(queue->ep_no));
+    usbc_excpet_log_trace(USBC_EXCEPT_CALL_CLEAR_CH, 1);
+    return KAL_TRUE;
+}
+
+static kal_uint8 usbc_except_acquire_pipe_queue(kal_uint8 class_device_id, usbc_pipe_type_e type)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 pipe_queue = INVALID_PIPE_QUEUE_ID;
+    kal_uint8 i = 0;
+
+    for ( i=0; i< MAX_USBCORE_QUEUE_NUM; i++ )
+    {
+        if ( (pUsbCore->tx_queue[i].class_device_id == class_device_id) &&
+             (pUsbCore->tx_queue[i].pipe_type == type) &&
+             (pUsbCore->tx_queue[i].state == USBC_CORE_QUEUE_STATE_INITIATED))
+        {
+            pipe_queue = i;
+            break;
+        }
+    }
+
+    if ( pipe_queue != INVALID_PIPE_QUEUE_ID )
+    {
+        return pipe_queue;
+    }
+
+    for ( i=0; i< MAX_USBCORE_QUEUE_NUM; i++ )
+    {
+        if ( (pUsbCore->rx_queue[i].class_device_id == class_device_id) &&
+             (pUsbCore->rx_queue[i].pipe_type == type) &&
+             (pUsbCore->rx_queue[i].state == USBC_CORE_QUEUE_STATE_INITIATED))
+        {
+            pipe_queue = (i | PIPE_QUEUE_RX_MASK);
+            break;
+        }
+    }
+
+    return pipe_queue;
+}
+
+static usbc_class_device_instance_t*
+usbc_except_device_register(
+    usbc_core_t              *pUsbCore,
+    usbc_class_device_info_t *device_info)
+{
+    usbc_core_class_device_t* pClassDevice = NULL;
+    usbc_class_device_instance_t* pClassDeviceInstance = NULL;
+    usbc_core_queue_t* pQueue = NULL;
+    kal_uint8 acquire_queue = 0;
+    kal_uint8 i = 0;
+
+    if (device_info == NULL) {
+        return NULL;
+    }
+
+    /* found available device instance, use it and apply register infromation */
+    pClassDevice = &(pUsbCore->class_device[0]);
+    if (device_info->total_pipes != pClassDevice->total_pipes) {
+        // pipe number not match, return NULL
+        return NULL;
+    }
+
+    pClassDeviceInstance                    = &(pClassDevice->device_instance);
+    pClassDeviceInstance->id                = 0;
+    pClassDeviceInstance->speed             = pUsbCore->speed;
+    pClassDeviceInstance->total_interfaces  = 0;
+    pClassDeviceInstance->context           = device_info->class_device_context;
+    pClassDevice->state             = USBC_CORE_CLASS_DEVICE_STATE_REGISTERED;
+    pClassDevice->notify_usb_state  = device_info->notify_usb_state;
+    pClassDevice->notify_usb_speed  = device_info->notify_usb_speed;
+    for ( i=0; i<pUsbCore->total_class_interfaces; i++ )
+    {
+        if ( (pUsbCore->class_interface[i].state == USBC_CORE_CLASS_INTERFACE_STATE_INITIATED) &&
+             (pUsbCore->class_interface[i].class_device_id == 0) )
+        {
+            /* fill Device Instance interface information */
+            pClassDeviceInstance->interface_type[pClassDeviceInstance->total_interfaces] = pUsbCore->class_interface[i].interface_type;
+            pClassDeviceInstance->interface_no[pClassDeviceInstance->total_interfaces] = pUsbCore->class_interface[i].interface_no;
+            pClassDeviceInstance->total_interfaces++;
+
+            /* fill USB Core interface information */
+            pUsbCore->class_interface[i].state = USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE;
+            pUsbCore->class_interface[i].notify_control_setup_packet = device_info->notify_control_setup_packet;
+            pUsbCore->class_interface[i].notify_control_complete = device_info->notify_control_complete;
+            pUsbCore->class_interface[i].notify_alternate_setting = device_info->notify_alternate_setting;
+        }
+    }
+
+    for ( i=0; i<device_info->total_pipes; i++ )
+    {
+        acquire_queue = usbc_except_acquire_pipe_queue(0, device_info->pipe_type[i]);
+        if ( acquire_queue == INVALID_PIPE_QUEUE_ID )
+        {
+            return NULL;
+        }
+
+        /* fill Device Instance Queue information */
+        pClassDeviceInstance->queue_no_for_pipe[i] = acquire_queue;
+
+        /* fill USB Core Queue information */
+        if ( (acquire_queue & PIPE_QUEUE_RX_MASK) != PIPE_QUEUE_RX_MASK )
+        {
+            pQueue = &(pUsbCore->tx_queue[acquire_queue]);
+        } else {
+            pQueue = &(pUsbCore->rx_queue[acquire_queue & ~PIPE_QUEUE_RX_MASK]);
+        }
+        pQueue->state               = USBC_CORE_QUEUE_STATE_ACTIVE;
+        pQueue->notify_complete     = device_info->notify_pipe_complete[i];
+        pQueue->notify_stall        = device_info->notify_pipe_stall[i];
+    }
+
+    return pClassDeviceInstance;
+}
+
+
+usbc_class_device_instance_t *usbc_except_reset_ch(usbc_class_device_info_t *device_info)
+{
+    usbc_class_device_instance_t   *dev_inst;
+    static hifusb_except_cb_t       except_cb;
+
+    usbc_set_flag(USBC_EXCEPT_CALL_RESET_CH);
+    usbc_dlog_reset();
+
+    usbc_except_init_context();
+    usbc_except_read_configuration();
+
+    /*
+     * Register exception mode callback function to HIF driver and 
+     * disconnect and then connect to USB to trigger USB re-enumeration.
+     */
+    except_cb.notify_usb_except_evt = usbc_core_notify_usb_event;
+    except_cb.notify_usb_except_control_in = usbc_except_notify_usb_except_control_in;
+    except_cb.notify_usb_except_control_out = usbc_except_notify_usb_except_control_out;
+    hifusb_except_change_ch(&except_cb);
+
+    /*
+     * Find the device instance for the USB CLASS in exception.
+     */
+    dev_inst = usbc_except_device_register(usbc_core_get_instance(), device_info);
+    usbc_excpet_log_trace(USBC_EXCEPT_CALL_RESET_CH, 2);
+    return dev_inst;
+}
+
+kal_bool usbc_except_enum_loop(void)
+{
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+
+    usbc_set_flag(USBC_EXCEPT_CALL_ENUM_LOOP);
+    USBC_EXCEPTION_MODE_CHECK();
+
+    /*
+     * Wait untill SET_CONFIGURATION or timeout to make sure 
+     * host side driver is ready.
+     */
+#if (defined(__MTK_TARGET__) && defined(__PRODUCTION_RELEASE__))
+    kal_uint32          begin_tick;     
+    GET_CURR_TICK(begin_tick);
+#endif  // #if (defined(__MTK_TARGET__) && defined(__PRODUCTION_RELEASE__))
+    do {
+        usbc_except_restart_watchdog();     // Restart watchdog timer to avoid silient reboot
+
+		hifusb_except_poll_isr();
+
+#if (defined(__MTK_TARGET__) && defined(__PRODUCTION_RELEASE__))
+        kal_uint32          curr_tick;
+        kal_uint64          ms_passed;
+        GET_CURR_TICK(curr_tick);
+        ms_passed = GET_DURATION_MS(begin_tick, curr_tick);
+        
+        if (USBC_EXCEPT_INFINITE_TIMEOUT != usbc_except_get_doc()->enum_timeout && 
+          ms_passed > usbc_except_get_doc()->enum_timeout) {
+            usbc_set_flag(USBC_EXCEPT_ENUM_LOOP_TO);
+            usbc_excpet_log_trace(USBC_EXCEPT_CALL_ENUM_LOOP, 0);
+            return KAL_FALSE;
+        }
+#endif  // #if (defined(__MTK_TARGET__) && defined(__PRODUCTION_RELEASE__))
+    } while (USBC_USB_STATE_ATTACHED != pUsbCore->state);
+    usbc_set_flag(USBC_EXCEPT_ENUM_LOOP_OK);
+
+    usbc_excpet_log_trace(USBC_EXCEPT_CALL_ENUM_LOOP, 1);
+    return KAL_TRUE;
+}
+
+kal_bool usbc_except_hif_poll(kal_uint8 class_device_id)
+{
+    usbc_set_flag(USBC_EXCEPT_CALL_HIF_POLL);
+    USBC_EXCEPTION_MODE_CHECK();
+
+    hifusb_except_poll_isr();
+//    usbc_excpet_log_trace(USBC_EXCEPT_CALL_HIF_POLL, 1);
+    return KAL_TRUE;
+}
+
+kal_bool 
+usbc_except_submit_gpd(
+    kal_uint8       class_device_id, 
+    kal_uint8       queue_no, 
+    void           *p_first_gpd, 
+    void           *p_last_gpd)
+{
+    usbc_core_queue_t  *queue;
+    hif_queue_type_e    queue_type;
+
+    usbc_set_flag(USBC_EXCEPT_CALL_SUBMIT_GPD);
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &queue, &queue_type)) {
+        usbc_set_flag(USBC_EXCEPT_SUBMIT_GPD_NG);
+//        usbc_excpet_log_trace(USBC_EXCEPT_CALL_SUBMIT_GPD, 0);
+        return KAL_FALSE;
+    }
+    usbc_dlog_submit_gpd(queue_type, p_last_gpd);
+
+//    usbc_excpet_log_trace(USBC_EXCEPT_CALL_SUBMIT_GPD, 2);
+    return hifusbq_except_set_gpd(queue_type, HIFUSB_EPNO_2_QNO(queue->ep_no), p_first_gpd, p_last_gpd);
+}
+
+kal_bool 
+usbc_except_poll_queue(
+    kal_uint8       class_device_id, 
+    kal_uint8       queue_no, 
+    void          **pp_first_gpd, 
+    void          **pp_last_gpd, 
+    kal_uint32     *gpd_num)
+{
+    usbc_core_queue_t  *queue;
+    hif_queue_type_e    queue_type;
+    hif_deq_info_t      deq_info;
+
+    usbc_set_flag(USBC_EXCEPT_CALL_POLL_QUEUE);
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &queue, &queue_type)) {
+        usbc_set_flag(USBC_EXCEPT_POLL_QUEUE_NG);
+//        usbc_excpet_log_trace(USBC_EXCEPT_CALL_POLL_QUEUE, 0);
+        return KAL_FALSE;
+    }
+
+    kal_mem_set(&deq_info, 0, sizeof(hif_deq_info_t));
+    deq_info.q_type = queue_type;
+    deq_info.que_no = HIFUSB_EPNO_2_QNO(queue->ep_no);
+    deq_info.deq_type = HIFQ_DEQ;
+
+    *gpd_num = hifusbq_except_poll_queue(deq_info, pp_first_gpd, pp_last_gpd);
+    usbc_dlog_poll_queue(queue_type, *gpd_num, *pp_last_gpd);
+
+//    usbc_excpet_log_trace(USBC_EXCEPT_CALL_POLL_QUEUE, 1);
+    return KAL_TRUE;
+}
+
+
+kal_bool 
+usbc_except_hif_state(
+    kal_uint8               class_device_id, 
+    kal_uint8               queue_no, 
+    usbc_except_link_st_e  *link_state)
+{
+    usbc_core_queue_t  *queue;
+    hif_queue_type_e    queue_type;
+    kal_uint32          inactive_interval;
+
+    usbc_set_flag(USBC_EXCEPT_CALL_HIF_STATE);
+
+    if (!usbc_core_get_queue_info(class_device_id, queue_no, &queue, &queue_type)) {
+        usbc_set_flag(USBC_EXCEPT_HIF_STATE_NG);
+//        usbc_excpet_log_trace(USBC_EXCEPT_CALL_HIF_STATE, 0);
+        return KAL_FALSE;
+    }
+
+    inactive_interval = hifusbq_except_get_txq_timeout(HIFUSB_EPNO_2_QNO(queue->ep_no));
+    if (inactive_interval > usbc_except_get_doc()->tx_timeout) {
+        usbc_set_flag(USBC_EXCEPT_HIF_STATE_TO);
+        *link_state = USBC_LINK_TX_TIMEOUT;
+    } else {
+        *link_state = USBC_LINK_NO_ERROR;
+    }
+//    usbc_excpet_log_trace(USBC_EXCEPT_CALL_HIF_STATE, 1);
+    return KAL_TRUE;
+}
+
+kal_bool usbc_except_reset_flush(
+    kal_uint8 class_device_id, kal_uint8 queue_no, void** first_gpd, void** last_gpd, kal_uint32* gpd_num)
+{
+    usbc_core_queue_t* pQueue = NULL;
+    hif_queue_type_e core_queue_hif_type;
+    hif_flush_type_e core_queue_flush_type = HIFQ_FLUSH_DEQ;
+
+    usbc_set_flag(USBC_EXCEPT_CALL_FLUSH);
+    usbc_except_restart_watchdog();     // Restart watchdog timer to avoid silient reboot
+
+    if (usbc_core_get_queue_info(class_device_id, queue_no, &pQueue, &core_queue_hif_type))
+    {
+        *gpd_num = hifusbq_except_flush_gpd(core_queue_hif_type, HIFUSB_EPNO_2_QNO(pQueue->ep_no), 
+                                            core_queue_flush_type, first_gpd, last_gpd);
+    }
+    else
+    {
+        usbc_set_flag(USBC_EXCEPT_FLUSH_NG);
+        usbc_excpet_log_trace(USBC_EXCEPT_CALL_FLUSH, 0xFF);
+        return KAL_FALSE;
+    }
+
+    usbc_excpet_log_trace(USBC_EXCEPT_CALL_FLUSH, (kal_uint8)*gpd_num);
+    return KAL_TRUE;
+}
+
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_hif.c b/mcu/middleware/hif/usbcore/src/usbcore_hif.c
new file mode 100644
index 0000000..d8753c7
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_hif.c
@@ -0,0 +1,2179 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   usbcore_hif.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   USB Core HIF interface and normal mode implementation.
+ *   One can tell the type of HIF interface from function name prefix:
+ *      (1) usbc_normal_hif_xxx(): implementation for normal mode HIF.
+ *      (2) usbc_core_xxx(): shared between normal mode and exception mode HIF.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "hif_usb.h"
+#include "usbcore_main.h"
+#include "usbcore_ind_q.h"
+#include "usbcore_hif.h"
+#include "usbc_custom.h"
+#include "hifusb_qmu.h"
+#include "hif_ior.h"
+#include "qmu_bm_util.h"
+#include "qmu_bm.h"
+#include "hif_spd_ext.h"
+#include "hmu.h"
+#include "hmu_conf_data.h"
+#include "usbidle_if.h"
+#include "usbcore_debug.h"
+#include "hif_swla.h"
+#include "usbcore_dual_owner.h"
+#include "usbc_custom.h"
+#include "dcl.h"
+#include "us_timer.h"
+#include "sleepdrv_interface.h"
+
+#ifdef __MULTI_BOOT__
+#include "multiboot_config.h"
+#endif /* __MULTI_BOOT__ */
+#ifdef __USB_OSD_SUPPORT__
+#include "usbosd.h"
+#endif /* __USB_OSD_SUPPORT__ */
+
+#ifdef ATEST_SYS_USBCORE
+#include "usbcore_ut.h"
+#endif
+
+#ifdef __MTK_MD_DIRECT_USB_SUPPORT__
+#include "usbcore_direct.h"
+#endif
+
+extern kal_uint32 dipc_mode, port_mode, pcie_status;
+/*
+ * Set up max capable speed by project makefile configuration, HIF_USB30_SUPPORT.
+ * See also usbcore.mak.
+ */
+#if __USBC_USB30_SUPPORT__
+    #define USBC_MAX_SPEED HIFUSB_USB_SPEED_USB30
+#else
+    #define USBC_MAX_SPEED HIFUSB_USB_SPEED_USB20
+#endif
+
+extern kal_uint16 INT_BootMode(void);
+
+#if __USBC_TARGET_HIF_DRIVER_SUPPORT__
+#define __USBCORE_TARGET_DEBUG__
+#endif
+
+/* switch to control OSD enable state */
+extern kal_bool osd_enable;
+
+usb_current_cfg_param_t usbc_current_param[USB_MAX_CLASS_NUM] = {0};
+
+/*trace for setup packet*/
+#define USBC_REQ_RECORD_MAX_NUM 20
+usbc_setup_packet_t usbc_request_record[USBC_REQ_RECORD_MAX_NUM] = {0};
+hifusb_control_request_type_e usbc_set_request_record[USBC_REQ_RECORD_MAX_NUM] = {0};
+kal_uint8 usbc_request_record_index = 0;
+kal_uint8 usbc_set_control_index = 0;
+/*exception setup packet trace*/
+usbc_setup_packet_t usbc_except_request_record[USBC_REQ_RECORD_MAX_NUM] = {0};
+kal_uint8 usbc_except_request_record_index = 0;
+
+kal_bool usbc_set_connect_flag = KAL_FALSE;
+
+/*record last polling tick time from HMU*/
+kal_uint32 usbc_last_polling_time = 0;
+
+/*
+ * HIF function pointers, actural mapping is defined in
+ * usbc_normal_hif_factory() and usbc_except_hif_factor() for
+ * normal mode and exception mode respectively.
+ */
+USBC_INDICATE_CONTROL_SETUP_PACKET  usbc_core_indicate_control_setup_packet = NULL;
+USBC_INDICATE_CONTROL_COMPLETE      usbc_core_indicate_control_complete = NULL;
+USBC_INDICATE_ALTERNATE_SETTING     usbc_core_indicate_alternate_setting = NULL;
+USBC_INDICATE_STALL                 usbc_core_indicate_stall = NULL;
+USBC_SET_CONTROL_REQUEST            usbc_core_set_control_request = NULL;
+USBC_SET_PROPERTY                   usbc_core_set_property = NULL;
+USBC_SET_USB_ADDRESS                usbc_core_set_usb_address = NULL;
+USBC_SET_USB_CONFIGURATION          usbc_core_set_usb_configuration = NULL;
+USBC_SET_STALL                      usbc_core_set_stall = NULL;
+USBC_CLEAR_STALL                    usbc_core_clear_stall = NULL;
+USBC_RST_EP							usbc_core_rst_ep = NULL;
+USBC_SET_USB_TESTMODE               usbc_core_set_usb_testmode = NULL;
+USBC_SET_SS_DEV_INIT_U1_EN          usbc_core_set_ss_dev_init_u1_en = NULL;
+USBC_SET_SS_DEV_INIT_U2_EN          usbc_core_set_ss_dev_init_u2_en = NULL;
+USBC_SET_USBHIF_ADDRESS             usbc_core_set_usbhif_address = NULL;
+USBC_SET_UFBHIF_CONFIGURATION       usbc_core_set_usbhif_configuration = NULL;
+USBC_SET_USBHIF_CONNECT             usbc_core_set_usbhif_connect = NULL;
+USBC_SET_USBHIF_DISCONNECT          usbc_core_set_usbhif_disconnect = NULL;
+USBC_SET_USBHIFQ_GPD                usbc_core_set_usbhifq_gpd = NULL;
+USBC_POLL_USBHIFQ_GPD               usbc_core_poll_hifusbq_gpd = NULL;
+USBC_CHECK_USBHIFQ_EMPTY            usbc_core_check_hifusbq_empty = NULL;
+USBC_FLUSH_USBHIFQ_GPD              usbc_core_flush_hifusbq_gpd = NULL;
+USBC_FLUSH_SW_USBHIFQ_GPD           usbc_core_flush_sw_hifusbq_gpd = NULL;
+USBC_CHK_NEWPKT                     usbc_core_check_new_packet = NULL;
+USBC_START_DATAQ                    usbc_core_start_dataq = NULL;
+USBC_POWER_DOWN                     usbc_core_power_down = NULL;
+USBC_SET_CLOCK_CG                   usbc_core_set_clock_cg = NULL;
+USBC_MASK_WAKEUP_EVENT              usbc_core_mask_wakeup_event = NULL;
+USBC_MASK_INTR                      usbc_core_mask_intr = NULL;
+
+USBC_DUAL_OWNER_OPERATION usbc_dual_owner_init = NULL;
+USBC_DUAL_OWNER_OPERATION usbc_dual_owner_ilm_handle = NULL;
+USBC_DUAL_OWNER_OPERATION usbc_dual_owner_class_ctrl_request = NULL;
+USBC_DUAL_OWNER_OPERATION usbc_dual_owner_class_ctrl_complete = NULL;
+USBC_DUAL_OWNER_OPERATION usbc_dual_owner_send_feature_request = NULL;
+USBC_DUAL_OWNER_NOTIFY_EVENT usbc_dual_owner_notify_event = NULL;
+
+/*------------------------------------------------------------------------------
+ * Private implementation for normal mode HIF.
+ *----------------------------------------------------------------------------*/
+static void usbc_normal_hif_notify_usb_event(hifusb_notify_evt_e event, void *data)
+{
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    usbc_usb_state_e    state;
+    usbc_ind_t          ind_to_enqueue = {0};
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    switch ( event )
+    {
+        case HIFUSB_NOTIFY_EVT_ATTACH:
+        {
+            state = USBC_USB_STATE_ATTACHING;
+            usbc_trace_info(USBCORE_HIF_EVENT_ATTACH);
+            break;
+        }
+        case HIFUSB_NOTIFY_EVT_DETACH:
+        {
+            state = USBC_USB_STATE_DETACHING;
+            usbc_trace_info(USBCORE_HIF_EVENT_DETACH);
+            break;
+        }
+        case HIFUSB_NOTIFY_EVT_SUSPEND:
+        {
+            state = USBC_USB_STATE_SUSPENDING;
+            if (pUsbCore->usb_low_power_enable)
+            {
+                 usbc_core_mask_intr(KAL_TRUE);
+                 SleepDrv_LockSleep(SLEEP_CTL_USBCORE,SMP);
+             }
+            usbc_normal_hif_set_pwr_flag(KAL_TRUE);
+            usbc_trace_info(USBCORE_HIF_EVENT_SUSPEND);
+            break;
+        }
+        case HIFUSB_NOTIFY_EVT_RESUME:
+        {
+            state = USBC_USB_STATE_RESUME;
+            usbc_trace_info(USBCORE_HIF_EVENT_RESUME);
+            break;
+        }
+        case HIFUSB_NOTIFY_EVT_RESET:
+        {
+            usbc_usb_speed_e speed = *(usbc_usb_speed_e*)data;
+            pUsbCore->setup_status = USBC_CORE_SETUP_SM_INITIALIZE;
+
+            usbc_trace_info(USBCORE_HIF_EVENT_RESET);
+            usbc_trace_info(USBCORE_DUALIPC_INFO, dipc_mode, port_mode, pcie_status);
+
+            // Clean USB indication queue
+            usbc_empty_ind_queue();
+            /*clean USB enum request record*/
+            usbc_core_clear_enum_record();
+
+            if ((speed != pUsbCore->speed) || (pUsbCore->is_mode_switch)) {
+                usbc_trace_info(USBCORE_HIF_EVENT_SPEED_CHANGE, pUsbCore->speed, speed);
+
+                /*
+                 * Change USB link speed and related settings.
+                 */
+                usbc_core_speed_change(pUsbCore, speed);
+
+                /*
+                 * Enqueue USB speed change before USB reset event.
+                 * Note that, we assume underlying HIF driver has already configured itself
+                 * for new USB link speed.
+                 */
+                ind_to_enqueue.type = USBC_IND_SPEED_CHANGE;
+                ind_to_enqueue.ext = 0;
+                ind_to_enqueue.data = (kal_uint8)speed;
+                usbc_enqueue_ind(&ind_to_enqueue);
+            }
+            usbc_core_set_hif_configuration();
+
+            ind_to_enqueue.ext = (kal_uint8)speed;
+            state = USBC_USB_STATE_RESET;
+            break;
+        }
+        case HIFUSB_NOTIFY_EVT_WAKEUP:
+            usbc_trace_warn(USBCORE_SET_USB_WAKEUP_EVENT);            
+            if (!pUsbCore->usb_low_power_enable)
+                return;
+            if(pUsbCore->usbc_wait_wakeup_event == KAL_TRUE)
+            {
+                SleepDrv_LockSleep(SLEEP_CTL_USBCORE,SMP);
+                pUsbCore->usbc_wait_wakeup_event = KAL_FALSE;      
+
+                usbc_core_set_clock_cg(KAL_TRUE);            
+                usbc_core_mask_intr(KAL_FALSE);
+                usbc_trace_warn(USBCORE_SET_CG_ON);              
+                SleepDrv_UnlockSleep(SLEEP_CTL_USBCORE,SMP);
+            }
+            return;
+        default:
+        {
+            usbc_trace_error(USBCORE_HIF_EVENT_UNKNOWN);
+            EXT_ASSERT(0, USBCORE_LOC_DRV_NOTIFY_INVALID_EVENT, (kal_uint32)event, 0);
+            return;
+        }
+    }
+    pUsbCore->state_in_hisr = state;
+    /*
+     * Enqueue USB device state which will be handled in USB context later.
+     */
+    ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+    //ind_to_enqueue.ext = 0;
+    ind_to_enqueue.data = (kal_uint8)state;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    /*
+     * Wake up USBCORE task to process indications.
+     */
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+}
+
+static kal_bool usbc_normal_hif_indicate_control_setup_packet(kal_uint8 intf_idx, usbc_setup_packet_t *packet)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    usbc_ind_t      ind_to_enqueue;
+
+    pUsbCore->setup_indicated = KAL_TRUE; /* Indicate to USBCLASS */
+
+    ind_to_enqueue.type = USBC_IND_CTRL_SETUP;
+    ind_to_enqueue.ext = 0;
+    ind_to_enqueue.data = intf_idx;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    /*
+     * Wake up USBCORE task to process indications.
+     */
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+    return KAL_FALSE;
+}
+
+static void usbc_normal_hif_indicate_control_complete(kal_uint8 intf_idx)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    usbc_ind_t      ind_to_enqueue;
+
+    ASSERT(pUsbCore->setup_indicated); /* Only setup packet indicated case shall enqueue a control complet indication. */
+
+    ind_to_enqueue.type = USBC_IND_CTRL_CMPLT;
+    ind_to_enqueue.ext = 0;
+    ind_to_enqueue.data = intf_idx;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    /*
+     * Wake up USBCORE task to process indications.
+     */
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+}
+
+static void usbc_normal_hif_indicate_alternate_setting(kal_uint8 intf_idx, kal_uint8 alternate_setting)
+{
+    usbc_ind_t      ind_to_enqueue;
+
+    ind_to_enqueue.type = USBC_IND_ALT_SETTING;
+    ind_to_enqueue.ext = intf_idx;
+    ind_to_enqueue.data = alternate_setting;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    /*
+     * Wake up USBCORE task to process indications.
+     */
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+}
+
+static void usbc_normal_hif_indicate_stall(kal_bool is_tx, kal_uint8 queue_idx, kal_bool stall)
+{
+    usbc_ind_t      ind_to_enqueue;
+
+    ind_to_enqueue.type = USBC_IND_PIPE_STALL;
+    ind_to_enqueue.ext = ((KAL_TRUE == stall) ? 1 : 0);
+    ind_to_enqueue.data = ((KAL_TRUE == is_tx) ? 0x80 : 0x00) | (queue_idx & 0x7f);
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    /*
+     * Wake up USBCORE task to process indications.
+     */
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+}
+
+static kal_bool usbc_normal_hif_notify_control_setup_packet(hifusb_setup_packet_t *p_setup)
+{
+    usbc_core_t     *pUsbCore = usbc_core_get_instance();
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    USBC_CLASS_COMMON_SPIN_LOCK(pUsbCore->setup_packet_spinlock);
+    if(pUsbCore->setup_status != USBC_CORE_SETUP_SM_INITIALIZE)
+    {
+        usbc_trace_warn(USBCORE_RECEIVE_MULTI_SETUP_PACKET, pUsbCore->setup_status);
+        pUsbCore->setup_status = USBC_CORE_SETUP_SM_MULTI_SETUP;           
+        USBC_CLASS_COMMON_SPIN_UNLOCK(pUsbCore->setup_packet_spinlock);
+        return KAL_FALSE;
+    }
+    pUsbCore->setup_status = USBC_CORE_SETUP_SM_RECEIVED;
+    USBC_CLASS_COMMON_SPIN_UNLOCK(pUsbCore->setup_packet_spinlock);
+
+    return usbc_core_dispatch_control_setup_packet(pUsbCore, p_setup);
+}
+
+static void usbc_normal_hif_notify_control_complete(void)
+{
+    usbc_core_t     *pUsbCore = usbc_core_get_instance();
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    usbc_core_notify_control_complete(pUsbCore);
+}
+
+static kal_bool usbc_normal_hif_set_usb_address(kal_uint8 address)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_bool        result = KAL_TRUE;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    pUsbCore->usb_address = address;
+    usbc_core_set_usbhif_address(pUsbCore->usb_address);
+
+    return result;
+}
+
+void usbc_core_transfer_class_type_to_string(usb_class_type_e type, char *class_type)
+{
+    switch(type)
+    {
+#ifdef __USB_ACM_SUPPORT__
+        case USB_CLASS_ACM1:
+            sprintf(class_type, "CDC_ACM1");
+            break;
+        case USB_CLASS_ACM2:
+            sprintf(class_type, "CDC_ACM2");
+            break;
+        case USB_CLASS_ACM3:
+            sprintf(class_type, "CDC_ACM3");
+            break;
+#endif
+#ifdef __USB_RNDIS_SUPPORT__
+        case USB_CLASS_RNDIS:
+            sprintf(class_type, "RNDIS");
+            break;
+#endif
+#ifdef __USB_MBIM_SUPPORT__
+        case USB_CLASS_MBIM:
+            sprintf(class_type, "MBIM");
+            break;            
+#endif
+#ifdef __USB_ECM_SUPPORT__
+        case USB_CLASS_ECM:
+            sprintf(class_type, "CDC_ECM");
+            break;
+#endif
+#ifdef __USB_ADB_SUPPORT__
+        case USB_CLASS_ADB:
+            sprintf(class_type, "ADB");
+            break;
+#endif
+//#ifdef __USB_MSD_SUPPORT__
+        case USB_CLASS_MS:
+            sprintf(class_type, "MS");
+            break;
+//#endif
+        default:
+            sprintf(class_type, "UNKNOWN");
+            break;
+    }
+    return;
+}
+
+static void usbc_core_trace_configuration_port_info()
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();
+    kal_uint8 class_idx, q_idx, txep_start, txep_num, rxep_start, rxep_num;
+    char class_type[16] = {0};
+    kal_uint32 tx_q = 0;
+    kal_uint32 rx_q = 0;
+    kal_uint32 uartport_num;
+    usb_cfg_param_t *cfg = &(pUsbCore->dev_param->mode_param[pUsbCore->mode].cfg_param[pUsbCore->usb_configuration-1]);
+
+    for(class_idx = 0; class_idx < cfg->class_num; class_idx++)
+    {
+        usbc_current_param[class_idx].class_type = cfg->class_type[class_idx];
+        usbc_current_param[class_idx].bulk_fifo_n = (kal_uint32)(cfg->bulk_fifo_n[class_idx]);
+        usbc_current_param[class_idx].uart_port = (kal_uint32)(cfg->class_ctxt[class_idx] -uart_port_usb + 1);
+        usbc_current_param[class_idx].class_owner = cfg->class_owner[class_idx];
+    }
+
+    for(class_idx = 0; class_idx < pUsbCore->total_class_devices; class_idx++)
+    {
+        kal_mem_set(class_type, 0, sizeof(class_type));
+        usbc_core_transfer_class_type_to_string(pUsbCore->class_device[class_idx].class_type, class_type);
+        uartport_num = ((kal_uint32)(cfg->class_ctxt[class_idx]) - (kal_uint32)uart_port_usb) + 1;
+
+        usbc_trace_info(USBCORE_DEBUG_CONFIGURATION_PORT_INFO, class_idx, class_type, pUsbCore->class_device[class_idx].owner, uartport_num);
+        
+        txep_start = 0;
+        txep_num = 0;
+        for(q_idx = tx_q; q_idx < pUsbCore->total_tx_queues; q_idx++)
+        {
+            if(pUsbCore->tx_queue[q_idx].class_device_id == class_idx)
+            {
+                if(!txep_start)
+                    txep_start = q_idx+1;
+                txep_num++;
+            }
+            else
+            {
+                tx_q = q_idx;
+                break;
+            }
+        }
+        rxep_start = 0;
+        rxep_num = 0;
+        for(q_idx = rx_q; q_idx < pUsbCore->total_rx_queues; q_idx++)
+        {
+            if(pUsbCore->rx_queue[q_idx].class_device_id == class_idx)
+            {
+                if(!rxep_start)
+                    rxep_start = q_idx+1;
+                rxep_num++;
+            }
+            else
+            {
+                rx_q = q_idx;
+                break;
+            }
+        }
+        
+        usbc_trace_info(USBCORE_DEBUG_CONFIGURATION_PORT_EP_INFO, class_idx, txep_start, txep_num,rxep_start, rxep_num);
+    }
+}
+
+static kal_bool usbc_normal_hif_set_usb_configuration(kal_uint8 configuration)
+{
+    #define CFG_TO_INDEX(config)   (config-1)
+
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    kal_bool            result = KAL_TRUE;
+    kal_uint32          idx_class;
+    kal_uint32          idx_if;
+    kal_uint32          idx_ep;
+    usbc_class_set_config_func_t class_set_config_func;
+    usb_class_type_e    type;
+    usb_class_owner_e owner;
+    usb_cfg_param_t     cfg_param;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    usbc_trace_info(USBCORE_HIF_SET_CONFIG, configuration);
+
+    /* Check if configuration is changed */
+    if (pUsbCore->usb_configuration == configuration) {
+        usbc_trace_info(USBCORE_HIF_SET_CONFIG_UNCHANGED);
+    }
+	pUsbCore->usb_configuration = configuration;
+
+    /* Reinit usb classes of old configuration */
+    usbc_trace_info(USBCORE_HIF_SET_CONFIG_REINIT_START);
+    usbc_reinit_class();
+    usbc_trace_info(USBCORE_HIF_SET_CONFIG_REINIT_END);
+
+    if (configuration == 0)
+    {  /* Clear all class device / interface / tx_queue / rx_queue number */
+       pUsbCore->total_class_devices = 0;
+       pUsbCore->total_class_interfaces = 0;
+       pUsbCore->total_tx_queues = 0;
+       pUsbCore->total_rx_queues = 0;
+    } else
+    {
+        /* Fill class_device / interface / tx_queue / rx_queue */
+        pUsbCore->total_class_devices = pUsbCore->dev_param->mode_param[pUsbCore->mode].cfg_param[CFG_TO_INDEX(configuration)].class_num;
+        for (idx_class = 0; idx_class < pUsbCore->total_class_devices; idx_class ++)
+        {
+            type = pUsbCore->dev_param->mode_param[pUsbCore->mode].cfg_param[CFG_TO_INDEX(configuration)].class_type[idx_class];
+            owner = pUsbCore->dev_param->mode_param[pUsbCore->mode].cfg_param[CFG_TO_INDEX(configuration)].class_owner[idx_class];
+            pUsbCore->class_device[idx_class].state = USBC_CORE_CLASS_DEVICE_STATE_INITIATED;
+            pUsbCore->class_device[idx_class].class_type = type;
+            pUsbCore->class_device[idx_class].owner = owner;
+            pUsbCore->class_device[idx_class].total_pipes = 0;
+        }
+
+        pUsbCore->total_class_interfaces = pUsbCore->resource_interface_number[CFG_TO_INDEX(configuration)];
+        for (idx_if = 0; idx_if < pUsbCore->total_class_interfaces; idx_if ++)
+        {
+            kal_mem_cpy(&pUsbCore->class_interface[idx_if],
+                           &pUsbCore->if_info[CFG_TO_INDEX(configuration)][idx_if].class_interface,
+                           sizeof(usbc_core_class_interface_t));
+            pUsbCore->class_interface[idx_if].state = USBC_CORE_CLASS_INTERFACE_STATE_INITIATED;
+        }
+
+        pUsbCore->total_tx_queues = pUsbCore->resource_ep_tx_number[CFG_TO_INDEX(configuration)];
+        for (idx_ep = 0; idx_ep < pUsbCore->total_tx_queues; idx_ep ++)
+        {
+            kal_mem_cpy(&pUsbCore->tx_queue[idx_ep],
+                           &pUsbCore->ep_tx_info[CFG_TO_INDEX(configuration)][idx_ep].queue_info,
+                           sizeof(usbc_core_queue_t));
+            pUsbCore->tx_queue[idx_ep].state = USBC_CORE_QUEUE_STATE_INITIATED;
+            pUsbCore->class_device[pUsbCore->tx_queue[idx_ep].class_device_id].total_pipes ++;
+        }
+
+        pUsbCore->total_rx_queues = pUsbCore->resource_ep_rx_number[CFG_TO_INDEX(configuration)];
+        for (idx_ep = 0; idx_ep < pUsbCore->total_rx_queues; idx_ep ++)
+        {
+            kal_mem_cpy(&pUsbCore->rx_queue[idx_ep],
+                           &pUsbCore->ep_rx_info[CFG_TO_INDEX(configuration)][idx_ep].queue_info,
+                           sizeof(usbc_core_queue_t));
+            pUsbCore->rx_queue[idx_ep].state = USBC_CORE_QUEUE_STATE_INITIATED;
+            pUsbCore->class_device[pUsbCore->rx_queue[idx_ep].class_device_id].total_pipes ++;
+        }
+
+
+        /* Call Set config callback function to all usb class modules */
+    	for (idx_class = 0; idx_class < pUsbCore->total_class_devices; idx_class ++)
+        {
+            cfg_param = pUsbCore->dev_param->mode_param[pUsbCore->mode].cfg_param[CFG_TO_INDEX(configuration)];
+            type = cfg_param.class_type[idx_class];
+            class_set_config_func = usbc_get_class_set_config_func(type);
+            if (class_set_config_func) {
+                usbc_trace_info(USBCORE_HIF_SET_CONFIG_USBCLASS, type);
+                class_set_config_func(idx_class,
+                                   CFG_TO_INDEX(configuration),
+                                   cfg_param.class_ctxt[idx_class]);
+            } else {
+                EXT_ASSERT(0, USBCORE_LOC_DEVICE_SET_CONFIG_FUNC_NULL, (kal_uint32)usbcore_classid_to_module(idx_class), (kal_uint32)idx_class);
+            }
+        }
+    }
+
+    /* According to Ming's comment in 2013/4/24, we can still set old property to hif if usb_configuration is changed to 0 */
+	usbc_core_set_hif_configuration();
+
+    usbc_trace_info(USBCORE_HIF_SET_CONFIG_HIF, pUsbCore->usb_configuration);
+    usbc_core_set_usbhif_configuration(pUsbCore->usb_configuration);
+
+    if (pUsbCore->usb_configuration > 0) {
+        /* notify class driver that HOST enable this device */
+        usbc_trace_info(USBCORE_HIF_SET_CONFIG_CONF_STATE);
+        usbc_core_notify_state_attached();
+
+        usbc_core_trace_configuration_port_info();
+
+        if(usbc_dual_owner_notify_event != NULL)
+            usbc_dual_owner_notify_event(USBC_USB_STATE_ATTACHED, 0);
+    } else {
+        /* notify class driver that HOST disable this device */
+        usbc_trace_info(USBCORE_HIF_SET_CONFIG_ADDR_STATE);
+        usbc_core_notify_state_attaching(); /* According to usb spec, configuration 0 means device enter addressed state */
+    }
+
+    return result;
+}
+
+static void usbc_normal_hif_set_stall(kal_bool is_tx, kal_uint8 nEnd)
+{
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    hifusb_set_stall(is_tx, nEnd);
+}
+
+static void usbc_normal_hif_clear_stall(kal_bool is_tx, kal_uint8 nEnd)
+{
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    hifusb_clear_stall(is_tx, nEnd);
+}
+
+static void usbc_normal_hif_rst_ep(kal_bool is_tx, kal_uint8 nEnd)
+{
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    hifusb_rst_ep(is_tx, nEnd);
+}
+
+static kal_bool usbc_normal_hif_set_control_request(kal_uint8 *buffer, kal_uint32 length, usbc_control_request_type_e type)
+{
+    usbc_core_t                    *pUsbCore = usbc_core_get_instance();
+    hifusb_control_request_type_e   hif_type = HIFUSB_CONTROL_REQUEST_TYPE_SEND;
+    kal_bool ret = KAL_FALSE;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    
+    /*record set control requests */
+    usbc_set_request_record[usbc_set_control_index] = type;
+    usbc_set_control_index = (usbc_set_control_index + 1) % USBC_REQ_RECORD_MAX_NUM;
+
+    switch ( type ) {
+        case USBC_CONTROL_REQUEST_TYPE_SEND:
+            hif_type = HIFUSB_CONTROL_REQUEST_TYPE_SEND;
+            break;
+        case USBC_CONTROL_REQUEST_TYPE_RECEIVE:
+            hif_type = HIFUSB_CONTROL_REQUEST_TYPE_RECEIVE;
+            break;
+        case USBC_CONTROL_REQUEST_TYPE_STALL:
+            hif_type = HIFUSB_CONTROL_REQUEST_TYPE_STALL;
+            break;
+        default:
+            ASSERT(0);
+            break;
+    }
+    
+    if(pUsbCore->setup_status == USBC_CORE_SETUP_SM_RECEIVED)
+    {
+    	USBC_CLASS_COMMON_SPIN_LOCK(pUsbCore->setup_packet_spinlock);
+  		pUsbCore->setup_status = USBC_CORE_SETUP_SM_INITIALIZE;    
+ 	 	USBC_CLASS_COMMON_SPIN_UNLOCK(pUsbCore->setup_packet_spinlock);
+        if (pUsbCore->setup_indicated) {
+            hifusb_set_control_request_in_task(buffer, length, hif_type);
+        } else {
+            hifusb_set_control_request_in_hisr(buffer, length, hif_type);
+        }
+        ret = KAL_TRUE;
+    }
+    else if(pUsbCore->setup_status == USBC_CORE_SETUP_SM_MULTI_SETUP)
+    {
+        USBC_CLASS_COMMON_SPIN_LOCK(pUsbCore->setup_packet_spinlock);
+  		pUsbCore->setup_status = USBC_CORE_SETUP_SM_INITIALIZE;    
+ 	 	USBC_CLASS_COMMON_SPIN_UNLOCK(pUsbCore->setup_packet_spinlock);
+		usbc_trace_warn(USBCORE_MULTI_SETUP_PACKET_RETURN_STALL);
+		hifusb_set_control_request_in_task(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+    }
+    return ret;
+}
+
+static kal_bool usbc_normal_hif_chk_newpkt(kal_bool isTx, kal_uint8 q_no)
+{
+    kal_uint8 flag;
+
+    if (isTx) {
+        flag = (hifusbq_check_dl_newpkt() >> q_no) & 0x01;
+    }
+    else {
+        flag = (hifusbq_check_ul_newpkt() >> q_no) & 0x01;
+    }
+
+    return (flag == 0)? KAL_FALSE:KAL_TRUE;
+}
+
+static void usbc_normal_hif_start_dataq(kal_bool isTx, kal_uint8 q_no)
+{
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    if (isTx) {
+        hifusb_start_dlq(q_no);
+    } else {
+        hifusb_start_ulq(q_no);
+    }
+}
+
+void usbc_normal_hif_set_pwr_flag(kal_bool flag)
+{
+    usb_idle_set_clockGating(flag);   
+}
+
+void usbc_core_clear_enum_record()
+{
+    usbc_request_record_index = 0;
+    usbc_set_control_index = 0;
+    kal_mem_set(usbc_request_record, 0, sizeof(usbc_setup_packet_t)*USBC_REQ_RECORD_MAX_NUM);    
+    kal_mem_set(usbc_set_request_record, 0, sizeof(hifusb_control_request_type_e)*USBC_REQ_RECORD_MAX_NUM);
+}
+
+void usbc_core_trace_gpd_info(qbm_gpd* first_gpd, qbm_gpd* last_gpd, kal_uint8 q_no, kal_bool isTx, kal_bool flag)
+{
+    qbm_gpd* curr_gpd = NULL;
+    kal_uint32 data_length, bd_num;
+    void* curr_bd = NULL;
+    
+    curr_gpd = first_gpd;
+    do {
+        data_length = 0;
+        bd_num = 0;
+
+        if ( curr_gpd == NULL ) break;
+
+        if (QBM_DES_GET_BDP(curr_gpd))
+        {
+            curr_bd = QBM_DES_GET_DATAPTR(curr_gpd);
+        
+            while(curr_bd)
+            {
+                data_length += QBM_DES_GET_DATALEN(curr_bd) + QBM_DES_GET_EXTLEN(curr_bd);
+                bd_num++;
+                if ( QBM_DES_GET_EOL(curr_bd) ) break;
+                curr_bd = QBM_DES_GET_NEXT(curr_bd);
+            }
+        }
+        else
+            data_length = QBM_DES_GET_EXTLEN(curr_gpd) + QBM_DES_GET_DATALEN(curr_gpd);
+        
+        if(flag)
+        {
+            if(isTx)
+            {
+                usbc_trace_warn(USBCORE_CLASS_CHECK_SUBMIT_TX_GPD_KPI, q_no, (kal_uint32)curr_gpd, data_length, bd_num, QBM_DES_GET_BPS(curr_gpd));
+            }
+            else
+            {
+                usbc_trace_warn(USBCORE_CLASS_CHECK_SUBMIT_RX_GPD_KPI, q_no, (kal_uint32)curr_gpd, data_length, bd_num, QBM_DES_GET_BPS(curr_gpd));
+            }
+        }
+        else
+        {
+            if(isTx)
+            {
+                usbc_trace_warn(USBCORE_CLASS_CHECK_POLL_TX_GPD_KPI, q_no, (kal_uint32)curr_gpd, data_length, bd_num, QBM_DES_GET_BPS(curr_gpd));
+            }
+            else
+            {
+                usbc_trace_warn(USBCORE_CLASS_CHECK_POLL_RX_GPD_KPI, q_no, (kal_uint32)curr_gpd, data_length, bd_num, QBM_DES_GET_BPS(curr_gpd));
+            }
+        }
+        if ( curr_gpd == last_gpd ) break;
+        curr_gpd = QBM_DES_GET_NEXT(curr_gpd);
+
+    } while (1);
+}
+
+/*------------------------------------------------------------------------------
+ * USB Core HIF interface shared between normal mode and exception mode.
+ *----------------------------------------------------------------------------*/
+#ifdef __USBCORE_DEBUG__
+void usbc_core_dump_gpd_list(void* first_gpd, void* last_gpd)
+{
+    void* curr_gpd = NULL;
+
+    curr_gpd = first_gpd;
+    do {
+        void* curr_bd = NULL;
+
+        if ( curr_gpd == NULL ) break;
+
+        usbc_core_printf("[USBCORE] gpd[%x].CHKSUM   : %x \r\n", curr_gpd, QBM_DES_GET_CHKSUM(curr_gpd));
+        usbc_core_printf("[USBCORE] gpd[%x].IOC      : %d \r\n", curr_gpd, QBM_DES_GET_IOC(curr_gpd)?1:0);
+        usbc_core_printf("[USBCORE] gpd[%x].BDP      : %d \r\n", curr_gpd, QBM_DES_GET_BDP(curr_gpd)?1:0);
+        usbc_core_printf("[USBCORE] gpd[%x].HWO      : %d \r\n", curr_gpd, QBM_DES_GET_HWO(curr_gpd)?1:0);
+        usbc_core_printf("[USBCORE] gpd[%x].BPS      : %d \r\n", curr_gpd, QBM_DES_GET_BPS(curr_gpd)?1:0);
+        usbc_core_printf("[USBCORE] gpd[%x].NEXT     : %x \r\n", curr_gpd, QBM_DES_GET_NEXT(curr_gpd));
+        usbc_core_printf("[USBCORE] gpd[%x].DATAPTR  : %x \r\n", curr_gpd, QBM_DES_GET_DATAPTR(curr_gpd));
+        usbc_core_printf("[USBCORE] gpd[%x].DATALEN  : %d \r\n", curr_gpd, QBM_DES_GET_DATALEN(curr_gpd));
+        usbc_core_printf("[USBCORE] gpd[%x].ALLOWLEN : %d \r\n", curr_gpd, QBM_DES_GET_ALLOW_LEN(curr_gpd));
+        usbc_core_printf("[USBCORE] gpd[%x].EXTLEN   : %d \r\n", curr_gpd, QBM_DES_GET_EXTLEN(curr_gpd));
+        curr_bd = QBM_DES_GET_DATAPTR(curr_gpd);
+        do {
+            if ( !QBM_DES_GET_BDP(curr_gpd) )
+            {
+                break;
+            }
+
+            usbc_core_printf("[USBCORE]    bd[%x].CHKSUM   : %x \r\n", curr_bd, QBM_DES_GET_CHKSUM(curr_bd));
+            usbc_core_printf("[USBCORE]    bd[%x].EOL      : %d \r\n", curr_bd, QBM_DES_GET_EOL(curr_bd));
+            usbc_core_printf("[USBCORE]    bd[%x].NEXT     : %x \r\n", curr_bd, QBM_DES_GET_NEXT(curr_bd));
+            usbc_core_printf("[USBCORE]    bd[%x].DATAPTR  : %x \r\n", curr_bd, QBM_DES_GET_DATAPTR(curr_bd));
+            usbc_core_printf("[USBCORE]    bd[%x].DATALEN  : %d \r\n", curr_bd, QBM_DES_GET_DATALEN(curr_bd));
+            usbc_core_printf("[USBCORE]    bd[%x].ALLOWLEN : %d \r\n", curr_bd, QBM_DES_GET_ALLOW_LEN(curr_bd));
+            usbc_core_printf("[USBCORE]    bd[%x].EXTLEN   : %d \r\n", curr_bd, QBM_DES_GET_EXTLEN(curr_bd));
+
+            if ( QBM_DES_GET_EOL(curr_bd) ) break;
+
+            curr_bd =  QBM_DES_GET_NEXT(curr_bd);
+
+        } while (curr_bd != NULL);
+
+        if ( curr_gpd == last_gpd ) break;
+
+        curr_gpd = QBM_DES_GET_NEXT(curr_gpd);
+
+    } while (1);
+}
+#endif
+
+static void usbc_core_getGpdLength(void* first_gpd, void* last_gpd, kal_uint32* gpd_len, kal_uint32* bd_len, kal_uint32* spd_len)
+{
+    void* curr_gpd = first_gpd;
+    void* curr_bd = NULL;
+    qbm_spd_ext* p_spdext;
+    kal_uint16 ph_len, packet_num;
+    hif_spd_packet_header* p_spdph;
+
+    *gpd_len = *bd_len = *spd_len = 0;
+
+    while(curr_gpd)
+    {
+        // Onlu process non-bypass GPDs
+        if(0 == QBM_DES_GET_BPS(curr_gpd))
+        {
+            // Accumulate EXTLEN, BD/SPD data length, and packet header length
+            switch(QBM_DES_GET_PDT(curr_gpd))
+            {
+                case DES_FLAG_BIT_GPD:
+                    // Accumulate length of GPDs
+                    *gpd_len += QBM_DES_GET_DATALEN(curr_gpd) + QBM_DES_GET_EXTLEN(curr_gpd);
+
+                    // Accumulate extnesion length of BDs
+                    if (QBM_DES_GET_BDP(curr_gpd))
+                    {
+                        curr_bd = QBM_DES_GET_DATAPTR(curr_gpd);
+
+                        while(curr_bd)
+                        {
+                            *bd_len += QBM_DES_GET_DATALEN(curr_bd) + QBM_DES_GET_EXTLEN(curr_bd);
+    
+                            if ( QBM_DES_GET_EOL(curr_bd) ) break;
+                            curr_bd = QBM_DES_GET_NEXT(curr_bd);
+                        }
+                    }
+                    break;
+
+                case DES_FLAG_BIT_SPD1:
+                    p_spdext = (qbm_spd_ext*)QBM_SPD_GET_EXT((qbm_spd*)curr_gpd);
+                    packet_num = HIF_SPD_EXT_GET_PKTNUM((hif_spd_ext_header*)p_spdext);
+                    ph_len = HIF_SPD_EXT_GET_SPD1_HEADERLEN((hif_spd_ext_header*)p_spdext);
+
+                    // Accumulate SPD data and header size
+                    *spd_len += QBM_DES_GET_DATALEN(curr_gpd) + ph_len * packet_num;
+                    break;                        
+
+                case DES_FLAG_BIT_SPD2:
+                    // Accumulate SPD data size
+                    *spd_len += QBM_DES_GET_DATALEN(curr_gpd);
+
+                    // Accumulate header size of each available packet
+                    p_spdext = (qbm_spd_ext*)QBM_SPD_GET_EXT((qbm_spd*)curr_gpd);
+                    p_spdph = HIF_SPD_EXT_GET_FIRST_PH(p_spdext);
+                    ph_len = 0;
+                    while(p_spdph)
+                    {
+                        if( 0 == HIF_SPD_PH_GET_IGR(p_spdph) )
+                        {
+                            ph_len = HIF_SPD_PH_GET_SPD2_HEADERLEN(p_spdph);
+                            *spd_len += ph_len;
+                        }
+
+                        if( 0 != HIF_SPD_PH_GET_EOL(p_spdph) ) 
+                            break;
+
+                        p_spdph = HIF_SPD_PH_NEXT(p_spdph, ph_len);
+                    } 
+                    break;
+
+                default:
+                    ASSERT(0);
+                    break;
+            }            
+        }
+        
+        if(curr_gpd == last_gpd) break;
+        curr_gpd = QBM_DES_GET_NEXT(curr_gpd);
+    }
+
+    return;
+}
+
+kal_bool usbc_core_set_hif_configuration(void)
+{
+    static hifusb_property_t   property;
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    kal_bool            result = KAL_FALSE;
+    kal_uint8           i = 0;
+
+    kal_mem_set(&property, 0, sizeof(hifusb_property_t));
+    property.speed      = USBC_MAX_SPEED; /* set desired speed as max capable speed */
+    property.qmu_config = 0;
+    property.txq_num    = pUsbCore->total_tx_queues;
+    property.rxq_num    = pUsbCore->total_rx_queues;
+    for ( i=0; i<property.txq_num; i++) {
+        property.tx_que[i].ep_no            = pUsbCore->tx_queue[i].ep_no;
+        property.tx_que[i].que_no           = HIFUSB_EPNO_2_QNO(pUsbCore->tx_queue[i].ep_no);   
+        property.tx_que[i].type             = pUsbCore->tx_queue[i].xfer_type;
+        property.tx_que[i].max_packet_size  = pUsbCore->tx_queue[i].max_packet_size;
+        property.tx_que[i].u2_fifo_u3_burst = pUsbCore->tx_queue[i].fifo_n;
+        /* set config to 0 when queue is AP side, USBdriver will not enable this queue */
+        if(pUsbCore->tx_queue[i].owner != USB_CLASS_OWNER_MD){
+            property.tx_que[i].config = 0;
+        }
+        else{
+            property.tx_que[i].config = pUsbCore->tx_queue[i].config;
+        }
+    }
+    for ( i=0; i<property.rxq_num; i++) {
+        property.rx_que[i].ep_no            = pUsbCore->rx_queue[i].ep_no;
+        property.rx_que[i].que_no           = HIFUSB_EPNO_2_QNO(pUsbCore->rx_queue[i].ep_no);
+        property.rx_que[i].type             = pUsbCore->rx_queue[i].xfer_type;
+        property.rx_que[i].max_packet_size  = pUsbCore->rx_queue[i].max_packet_size;
+        property.rx_que[i].u2_fifo_u3_burst = pUsbCore->rx_queue[i].fifo_n;
+        /* set config to 0 when queue is AP side, USBdriver will not enable this queue */
+        if(pUsbCore->rx_queue[i].owner != USB_CLASS_OWNER_MD){
+            property.rx_que[i].config = 0;
+        }
+        else{
+            property.rx_que[i].config = pUsbCore->rx_queue[i].config;
+        }
+    }
+
+    property.notify_usb_evt                 = usbc_normal_hif_notify_usb_event;
+    property.notify_control_setup_packet    = usbc_normal_hif_notify_control_setup_packet;
+    property.notify_control_complete        = usbc_normal_hif_notify_control_complete;
+    property.notify_clock_gate_flag = usbc_normal_hif_set_pwr_flag;
+
+    result = usbc_core_set_property(&property);
+    ASSERT(result);
+
+    return result;
+}
+
+void usbc_core_trace_setup_packet(usbc_setup_packet_t *packet)
+{
+    if (USBC_IS_IN_EXCEPTION_MODE()) 
+    {    
+        kal_mem_cpy(&(usbc_except_request_record[usbc_except_request_record_index]), packet, sizeof(usbc_setup_packet_t));
+        usbc_except_request_record_index = (usbc_except_request_record_index + 1) % USBC_REQ_RECORD_MAX_NUM;
+    }
+    else
+    {    
+        kal_mem_cpy(&(usbc_request_record[usbc_request_record_index]), packet, sizeof(usbc_setup_packet_t));        
+        usbc_request_record_index = (usbc_request_record_index + 1) % USBC_REQ_RECORD_MAX_NUM;
+    }
+}
+
+kal_bool usbc_core_dispatch_control_setup_packet(usbc_core_t *pUsbCore, hifusb_setup_packet_t *p_setup)
+{
+    kal_bool    handled = KAL_TRUE;
+
+    pUsbCore->setup_packet.bmRequestType    = p_setup->bmRequestType;
+    pUsbCore->setup_packet.bRequest         = p_setup->bRequest;
+    pUsbCore->setup_packet.wValue           = USBC_EF16P((kal_uint8*)&p_setup->wValue);
+    pUsbCore->setup_packet.wIndex           = USBC_EF16P((kal_uint8*)&p_setup->wIndex);
+    pUsbCore->setup_packet.wLength          = USBC_EF16P((kal_uint8*)&p_setup->wLength);
+
+    pUsbCore->setup_indicated = KAL_FALSE; /* Default is handled in USBCORE. */
+
+    usbc_trace_info(USBCORE_DISPATCH_REQUEST, pUsbCore->setup_packet.bmRequestType);
+    
+    usbc_core_trace_setup_packet(&pUsbCore->setup_packet);
+
+    /* host detection filter before USB request handling */
+#ifdef __USB_OSD_SUPPORT__
+    if (osd_enable)
+    {
+        if (osd_setup())
+        {
+            return handled;
+        }
+    }
+#endif
+
+    if ((pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_TYPE_MASK) == USBC_REQUEST_TYPE_STANDARD) {
+        //usbc_core_printf("=========>usbcore_handle_standard_request\r\n");
+        handled = usbc_core_handle_standard_request();
+
+#ifdef __USB_OSD_SUPPORT__
+        /* Do OSD retry after set configuration finished */
+        osd_retry_require_check();
+#endif
+    } else if ((pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_TYPE_MASK) == USBC_REQUEST_TYPE_CLASS) {
+        if ((pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK) == USBC_REQUEST_RECIP_INTERFACE) {
+            kal_uint8 bInterface = pUsbCore->setup_packet.wIndex & 0xff;
+            kal_uint8 i;
+
+            usbc_core_printf("=========>usbcore_handle_class_request\r\n");
+
+            /* notify class driver by interface if exist */
+            for ( i=0; i<pUsbCore->total_class_interfaces; i++) {
+                if ( (pUsbCore->class_interface[i].interface_no == bInterface) &&
+                     (pUsbCore->class_interface[i].state == USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE) &&
+                     (pUsbCore->class_interface[i].notify_control_setup_packet != NULL)) {
+                    break;
+                }
+            }
+
+            if ( i == pUsbCore->total_class_interfaces ) {
+                /* incorrect reqeuset */
+                usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+            } else {
+                handled = usbc_core_indicate_control_setup_packet(i, &pUsbCore->setup_packet);
+            }
+        } else {
+            /* incorrect reqeuset */
+            usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+        }
+    } else if ((p_setup->bmRequestType & USBC_REQUEST_TYPE_MASK) == USBC_REQUEST_TYPE_VENDOR) {
+        usbc_core_printf("=========>usbcore_handle_vendor_request\r\n");
+        usbc_core_handle_vendor_request();
+    } else {
+        /* unknown reqeuset */
+        usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+    }
+
+    return handled;
+}
+
+void usbc_core_notify_control_complete(usbc_core_t *pUsbCore)
+{
+    if (((pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_TYPE_MASK) == USBC_REQUEST_TYPE_CLASS) ||
+        ((pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_TYPE_MASK) == USBC_REQUEST_TYPE_VENDOR)) {
+        if ((pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK) == USBC_REQUEST_RECIP_INTERFACE) {
+            kal_uint8 bInterface = pUsbCore->setup_packet.wIndex & 0xff;
+            kal_uint8 i;
+
+            /* notify class driver by interface if exist */
+            for ( i=0; i<pUsbCore->total_class_interfaces; i++) {
+                if ( (pUsbCore->class_interface[i].interface_no == bInterface) &&
+                     (pUsbCore->class_interface[i].state == USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE) &&
+                     (pUsbCore->class_interface[i].notify_control_complete != NULL) ) {
+                    break;
+                }
+            }
+
+            if ( i < pUsbCore->total_class_interfaces ) {
+                usbc_core_indicate_control_complete(i);
+            }
+        }
+    }
+}
+
+void usbc_core_speed_change(usbc_core_t *pUsbCore, usbc_usb_speed_e speed)
+{
+    pUsbCore->speed = speed;
+
+    usbc_core_descriptors_speed_change(pUsbCore, speed);
+}
+
+/*------------------------------------------------------------------------------
+ * USB Core internal implementation for HIF normal mode.
+ *----------------------------------------------------------------------------*/
+kal_bool usbc_normal_hif_init(void)
+{
+    kal_bool        result = KAL_FALSE;
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    result = hifusb_init(USBC_MAX_SPEED);
+    ASSERT(result);
+    return result;
+}
+
+kal_bool usbc_normal_hif_shutdown(void)
+{
+    kal_bool        result = KAL_FALSE;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    hifusb_shutdown();
+
+    return result;
+}
+
+kal_bool usbc_normal_hif_connect(void)
+{
+    kal_bool        result = KAL_FALSE;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    usbc_set_connect_flag = KAL_TRUE;
+    result = usbc_core_set_usbhif_connect();
+
+    return result;
+}
+
+kal_bool usbc_normal_hif_disconnect(void)
+{
+    kal_bool        result = KAL_FALSE;
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+    usbc_set_connect_flag = KAL_FALSE;
+    result = usbc_core_set_usbhif_disconnect();
+
+    return result;
+}
+
+kal_bool usbc_normal_hif_remote_wakeup(void)
+{
+    kal_bool        result = KAL_FALSE;
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+#if __USBC_TARGET_HIF_DRIVER_SUPPORT__ || ATEST_SYS_USBCORE
+    result = hifusb_remote_wakeup();
+    ASSERT(result);
+#endif
+
+    return result;
+}
+
+kal_bool usbc_normal_hif_ss_wk_notify(kal_uint8 nInterface)
+{
+    kal_bool        result = KAL_FALSE;
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+#if __USBC_TARGET_HIF_DRIVER_SUPPORT__ || ATEST_SYS_USBCORE
+    usbc_trace_info(USBCORE_REMOTE_WK_HIF_NOTIFY, nInterface);
+    result = hifusb_ss_func_wk_notify(nInterface);
+    ASSERT(result);
+#endif
+
+    return result;
+}
+
+void usbc_normal_hif_sc_stall(kal_uint8 queue_no, kal_bool stall, usb_class_owner_e* owner)
+{
+    kal_bool is_tx = (queue_no & 0x80)? KAL_TRUE : KAL_FALSE;
+    kal_uint8 queue_idx = queue_no & 0x7f;
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    usbc_core_queue_t   *pQueue;
+
+    if (is_tx) {
+        pQueue = &pUsbCore->tx_queue[queue_idx];
+    } else {
+        pQueue = &pUsbCore->rx_queue[queue_idx];
+    }
+
+    *owner = pQueue->owner;
+    if(pQueue->owner == USB_CLASS_OWNER_MD){
+        if(stall)
+            usbc_core_set_stall(is_tx, pQueue->ep_no);
+        else
+            usbc_core_clear_stall(is_tx, pQueue->ep_no);
+    }
+    
+    pQueue->state = (stall == KAL_TRUE)? USBC_CORE_QUEUE_STATE_STALL:USBC_CORE_QUEUE_STATE_ACTIVE;
+}
+
+void usbc_normal_hif_poll_queue_tx_gpd(kal_uint8 q_no)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    qbm_gpd        *first_gpd = NULL;
+    qbm_gpd        *last_gpd = NULL;
+    kal_uint32      num = 0;
+    hif_deq_info_t  deq_info;
+    usbc_io_request_t   *request;
+
+    // check Tx bitmap of the endpoint
+    if ( !usbc_core_check_new_packet(KAL_TRUE, HIFUSB_EPNO_2_QNO(pUsbCore->tx_queue[q_no].ep_no)) ) {
+        return;
+    }
+
+    kal_mem_set(&deq_info, 0, sizeof(hif_deq_info_t));
+    deq_info.q_type = HIFQ_TYPE_TX;
+    deq_info.que_no = HIFUSB_EPNO_2_QNO(pUsbCore->tx_queue[q_no].ep_no);
+    if ( pUsbCore->tx_queue[q_no].notify_complete == NULL ) {
+        deq_info.deq_type = HIFQ_FREEQ;
+    } else {
+        deq_info.deq_type = HIFQ_DEQ;
+    }
+
+    num = usbc_core_poll_hifusbq_gpd(deq_info, (void**)&first_gpd, (void**)&last_gpd);
+
+    if( num > 0 ) {
+#ifdef __USBCORE_DEBUG__
+        usbc_core_printf("[USBCORE] poll tx[%d] return %d first gpd %x last gpd %x\r\n", q_no, num, first_gpd, last_gpd);
+        //usbc_core_dump_gpd_list(first_gpd, last_gpd);
+#endif
+        if( num > 1 ) {
+            usbc_data_trace(MD_TRC_USBCORE_POLL_QUEUE_TX, q_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
+        } else {
+            usbc_data_trace(MD_TRC_USBCORE_POLL_QUEUE_TX_ONE, q_no, (kal_uint32)first_gpd);
+        }
+#ifdef __USBCORE_TARGET_DEBUG__
+        kal_uint32 gpd_len, bd_len, spd_len;
+        usbc_core_getGpdLength(first_gpd, last_gpd, &gpd_len, &bd_len, &spd_len);
+        usbc_core_trace_gpd_info(first_gpd, last_gpd, q_no, KAL_TRUE, 0);
+#endif
+        if( pUsbCore->tx_queue[q_no].notify_complete != NULL ) {
+            if ( first_gpd == NULL ) {
+                /* just indicate a notification */
+                pUsbCore->tx_queue[q_no].notify_complete(pUsbCore->tx_queue[q_no].class_device_id, NULL);
+            } else {
+                if(!pUsbCore->is_func_be_accessed[pUsbCore->tx_queue[q_no].class_device_id]) {
+                    USBC_CLASS_REMOTE_WK_LOCK(pUsbCore->usbc_class_func_access_mutex);
+                    pUsbCore->is_func_be_accessed[pUsbCore->tx_queue[q_no].class_device_id] = KAL_TRUE;
+                    USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_func_access_mutex);
+                }
+
+                request = (usbc_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(first_gpd);
+                request->next_request = NULL;
+                request->first_gpd = first_gpd;
+                request->last_gpd = last_gpd;
+                pUsbCore->tx_queue[q_no].notify_complete(pUsbCore->tx_queue[q_no].class_device_id, request);
+            }
+        }
+        
+#ifdef __USBCORE_TARGET_DEBUG__
+        usbc_data_trace(MD_TRC_USBCORE_POLL_QUEUE_LEN_TX, q_no, gpd_len, bd_len, spd_len);
+#endif
+        pUsbCore->usbc_q_polled_duration += USBC_POLLED_CHECK_DURATION * USBC_POLLED_CHECK_SHOW_ONLY_NO_DATA;
+    }
+}
+
+
+void usbc_normal_hif_poll_queue_rx_gpd(kal_uint8 q_no)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    qbm_gpd        *first_gpd = NULL;
+    qbm_gpd        *last_gpd = NULL;
+    kal_uint32      num = 0;
+    hif_deq_info_t  deq_info;
+    usbc_io_request_t   *request;
+
+    // check Rx bitmap of the endpoint
+    if ( !usbc_core_check_new_packet(KAL_FALSE, HIFUSB_EPNO_2_QNO(pUsbCore->rx_queue[q_no].ep_no)) ) {
+        return;
+    }
+
+    kal_mem_set(&deq_info, 0, sizeof( deq_info));
+    deq_info.q_type = HIFQ_TYPE_RX;
+    deq_info.que_no = HIFUSB_EPNO_2_QNO(pUsbCore->rx_queue[q_no].ep_no);
+    deq_info.deq_type = HIFQ_DEQ;
+
+    num = usbc_core_poll_hifusbq_gpd(deq_info, (void**)&first_gpd, (void**)&last_gpd);
+
+    if(num > 0) {
+#ifdef __USBCORE_DEBUG__
+        usbc_core_printf("[USBCORE] poll rx[%d] return %d first gpd %x last gpd %x\r\n", q_no, num, first_gpd, last_gpd);
+        //usbc_core_dump_gpd_list(first_gpd, last_gpd);
+#endif
+        if(num > 1 ) {
+            usbc_data_trace(MD_TRC_USBCORE_POLL_QUEUE_RX, q_no, num, (kal_uint32)first_gpd, (kal_uint32)last_gpd);
+        } else {
+            usbc_data_trace(MD_TRC_USBCORE_POLL_QUEUE_RX_ONE, q_no, (kal_uint32)first_gpd);
+        }
+#ifdef __USBCORE_TARGET_DEBUG__
+        kal_uint32 gpd_len, bd_len, spd_len;
+        usbc_core_getGpdLength(first_gpd, last_gpd, &gpd_len, &bd_len, &spd_len);        
+        usbc_core_trace_gpd_info(first_gpd, last_gpd, q_no, KAL_FALSE, 0);
+#endif
+
+        if ( pUsbCore->rx_queue[q_no].notify_complete != NULL ) {
+            if ( first_gpd == NULL ) {
+                /* has return number, but no return GPD */
+                EXT_ASSERT(0, USBCORE_LOC_POLLED_RX_NULL_GPD, (kal_uint32)num, (kal_uint32)q_no);
+            } else {
+                if(!pUsbCore->is_func_be_accessed[pUsbCore->rx_queue[q_no].class_device_id]) {
+                    USBC_CLASS_REMOTE_WK_LOCK(pUsbCore->usbc_class_func_access_mutex);
+                    pUsbCore->is_func_be_accessed[pUsbCore->rx_queue[q_no].class_device_id] = KAL_TRUE;
+                    USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_func_access_mutex);
+                }
+
+                request = (usbc_io_request_t*)QBM_DES_GET_SW_CTRL_FIELD(first_gpd);
+                request->next_request = NULL;
+                request->first_gpd = first_gpd;
+                request->last_gpd = last_gpd;
+                pUsbCore->rx_queue[q_no].notify_complete(pUsbCore->rx_queue[q_no].class_device_id, request);
+            }
+        } else {
+            EXT_ASSERT(0, USBCORE_LOC_DEVICE_RX_COMPLETE_FUNC_NULL, (kal_uint32)usbcore_classid_to_module(pUsbCore->rx_queue[q_no].class_device_id), (kal_uint32)q_no);
+        }
+
+#ifdef __USBCORE_TARGET_DEBUG__
+        usbc_data_trace(MD_TRC_USBCORE_POLL_QUEUE_LEN_RX, q_no, gpd_len, bd_len, spd_len);
+#endif
+        pUsbCore->usbc_q_polled_duration += USBC_POLLED_CHECK_DURATION * USBC_POLLED_CHECK_SHOW_ONLY_NO_DATA;
+    }
+}
+
+void usbc_normal_hif_poll_queue_drb(kal_uint8 q_no)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_uint32      num = 0;
+    kal_uint32      startIdx, endIdx;
+
+    // check Rx bitmap of the endpoint
+    if ( !usbc_core_check_new_packet(KAL_TRUE, HIFUSB_EPNO_2_QNO(pUsbCore->tx_queue[q_no].ep_no)) ) {
+        return;
+    }
+
+    num = ubm_drb_poll(HIFUSB_EPNO_2_QNO(pUsbCore->tx_queue[q_no].ep_no), &startIdx, &endIdx);
+
+    if(num > 0) {
+        usbc_data_trace(MD_TRC_USBCORE_POLL_QUEUE_DRB, q_no, num, startIdx, endIdx);
+
+        if( pUsbCore->tx_queue[q_no].notify_rb_complete != NULL ) {
+            if(!pUsbCore->is_func_be_accessed[pUsbCore->tx_queue[q_no].class_device_id]) {
+                USBC_CLASS_REMOTE_WK_LOCK(pUsbCore->usbc_class_func_access_mutex);
+                pUsbCore->is_func_be_accessed[pUsbCore->tx_queue[q_no].class_device_id] = KAL_TRUE;
+                USBC_CLASS_REMOTE_WK_UNLOCK(pUsbCore->usbc_class_func_access_mutex);
+            }
+
+            pUsbCore->tx_queue[q_no].notify_rb_complete(pUsbCore->tx_queue[q_no].class_device_id, startIdx, endIdx, 0);
+        }
+
+        ubm_drb_repay(HIFUSB_EPNO_2_QNO(pUsbCore->tx_queue[q_no].ep_no));    // check, copy stock DRB to common DRB, and re-submit
+        pUsbCore->usbc_q_polled_duration += USBC_POLLED_CHECK_DURATION * USBC_POLLED_CHECK_SHOW_ONLY_NO_DATA;
+    }
+}
+
+void usbc_normal_hif_poll_queue_xit(kal_uint8 q_no)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_uint32      num = 0;
+    kal_uint16      startIdx = 0, endIdx = 0, relIdx = 0;
+
+    // check Rx bitmap of the endpoint
+    if ( usbc_core_check_new_packet(KAL_FALSE, HIFUSB_EPNO_2_QNO(pUsbCore->rx_queue[q_no].ep_no)) ) {
+        /*
+         * Poll XIT
+         */
+        num = ubm_xit_poll(HIFUSB_EPNO_2_QNO(pUsbCore->rx_queue[q_no].ep_no), &startIdx, &endIdx, &relIdx);
+    }
+
+    /*
+     * Enqueue to LHIF UL queue
+     */
+    if (num > 0) {
+        usbc_data_trace(MD_TRC_USBCORE_POLL_QUEUE_XIT, q_no, num, startIdx, endIdx);
+        pUsbCore->usbc_q_polled_duration += USBC_POLLED_CHECK_DURATION * USBC_POLLED_CHECK_SHOW_ONLY_NO_DATA;
+    }
+
+    if (pUsbCore->rx_queue[q_no].notify_rb_complete) {
+        pUsbCore->rx_queue[q_no].notify_rb_complete(pUsbCore->rx_queue[q_no].class_device_id, startIdx, endIdx, relIdx);
+    } else {
+        EXT_ASSERT(0, USBCORE_LOC_DEVICE_RX_COMPLETE_FUNC_NULL, (kal_uint32)usbcore_classid_to_module(pUsbCore->rx_queue[q_no].class_device_id), (kal_uint32)q_no);
+    }
+}
+
+void usbc_normal_hif_poll_queue()
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_int8        i = 0;
+    kal_uint32 current_time;
+
+    current_time = ust_get_current_time();
+    if((usbc_last_polling_time != 0) && (current_time - usbc_last_polling_time > USBC_POLLED_CHECK_DURATION_TIME_MAX))
+    {
+        usbc_trace_warn(USBCORE_POLL_TICK_TIMEOUT, (current_time - usbc_last_polling_time));
+    }
+    usbc_last_polling_time = current_time;
+
+    /*
+     * USB Rx queue
+     */
+    HIF_SWLA_START("UUP");
+    for ( i=0; i<pUsbCore->total_rx_queues; i++ ) {
+        if ( pUsbCore->rx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED ) {
+#ifdef __MTK_MD_DIRECT_USB_SUPPORT__
+            if(pUsbCore->rx_queue[i].xfer_type != HIFUSB_EP_XFER_TYPE_BULK) {
+                continue;
+            }
+#endif
+            if(pUsbCore->rx_queue[i].owner != USB_CLASS_OWNER_MD){
+                continue;
+            }
+
+            if(pUsbCore->rx_queue[i].config & HIFUSB_QMU_RXQ_UL_PRB_XIT_EN) {
+                usbc_normal_hif_poll_queue_xit(i);      // Poll Rx XIT
+            } else {
+                usbc_normal_hif_poll_queue_rx_gpd(i);   // Poll Rx GPD
+            }
+
+            pUsbCore->usbc_rxq_polled_mask |= 0x1 << i;
+        }
+    }
+    HIF_SWLA_STOP("UUP");
+
+    /*
+     * USB Tx queue
+     */
+    HIF_SWLA_START("UDP");
+    for ( i=0; i<pUsbCore->total_tx_queues; i++ ) {
+        if ( pUsbCore->tx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED ) {
+#ifdef __MTK_MD_DIRECT_USB_SUPPORT__
+            if(pUsbCore->tx_queue[i].xfer_type != HIFUSB_EP_XFER_TYPE_BULK) {
+                continue;
+            }
+#endif
+            if(pUsbCore->tx_queue[i].owner != USB_CLASS_OWNER_MD){
+                continue;
+            }
+
+            if(pUsbCore->tx_queue[i].config & HIFUSB_QMU_TXQ_DL_DRB_EN) {
+                usbc_normal_hif_poll_queue_drb(i);      // Poll Tx DRB
+            } else {
+                usbc_normal_hif_poll_queue_tx_gpd(i);   // Poll Tx GPD/SPD
+            }
+
+            pUsbCore->usbc_txq_polled_mask |= 0x1 << i;
+        }
+    }
+    HIF_SWLA_STOP("UDP");
+
+	if (++pUsbCore->usbc_q_polled_duration == USBC_POLLED_CHECK_DURATION) {
+        usbc_data_trace(MD_TRC_USBCORE_POLL_QUEUE_E, pUsbCore->usbc_txq_polled_mask, pUsbCore->usbc_rxq_polled_mask);        
+        usbc_trace_warn(USBCORE_POLL_ALL_QUEUE_EMPTY, USBC_POLLED_CHECK_DURATION, pUsbCore->usbc_txq_polled_mask, pUsbCore->usbc_rxq_polled_mask);
+    }
+	if (pUsbCore->usbc_q_polled_duration >= USBC_POLLED_CHECK_DURATION) {
+        pUsbCore->usbc_q_polled_duration = pUsbCore->usbc_txq_polled_mask = pUsbCore->usbc_rxq_polled_mask = 0;
+    }
+}
+
+static kal_bool usbc_core_isConfigValid(kal_uint8 iConfig)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8* pDevConf = pUsbCore->descriptors.device;
+
+    if(iConfig <= pDevConf[17])
+    {
+        return KAL_TRUE;
+    }
+    else
+    {
+        usbc_trace_warn(USBCORE_CONF_INVALID, iConfig);
+        return KAL_FALSE;
+    }
+}
+void usbc_core_handle_device_wk_feature(usbc_func_state_e state)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_uint32 i;
+    kal_bool send_flag = KAL_FALSE;
+    kal_uint32 remote_wk_state;
+    
+    for( i=0; i<pUsbCore->total_class_devices; i++)
+    {
+        if ( NULL != pUsbCore->class_device[i].query_func_wk_status &&
+             pUsbCore->class_device[i].query_func_wk_status(i) & ((kal_uint8)0x01) )
+        {
+            remote_wk_state = (pUsbCore->class_device[i].query_func_wk_status(i))>>1;
+            if(pUsbCore->class_device[i].owner == USB_CLASS_OWNER_AP)
+            {
+                if((remote_wk_state == 1 && state == USBC_FUNC_WK_DISABLE) ||(remote_wk_state == 0 && state == USBC_FUNC_WK_ENABLE))
+                {
+                    /*only send request to AP when AP port wk state change*/
+                    send_flag = KAL_TRUE;
+                }
+            }
+            usbc_core_notify_func_wk_ability(i, (state == USBC_FUNC_WK_DISABLE? KAL_FALSE:KAL_TRUE));
+        }
+    }    
+    if(send_flag == KAL_TRUE && usbc_dual_owner_send_feature_request != NULL)    
+        usbc_dual_owner_send_feature_request();
+    
+    return;
+}
+
+
+void usbc_normal_hif_process_indications(void)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    usbc_core_class_interface_t *intf;
+    usbc_ind_t      ind_dequeued;
+    kal_uint8 class_device_id;
+    usb_class_owner_e owner;
+
+    USBC_CLASS_DEVICE_CONTEXT_CHECK();
+
+    while (!usbc_queue_empty_check()) {
+        if (pUsbCore->usb_low_power_enable && (pUsbCore->waiting_ap_clk_disable_flag == KAL_TRUE))
+        {
+            kal_sleep_task(1);
+            hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+            break;
+        }
+        
+        if (pUsbCore->ap_response_reset_evt_done == KAL_FALSE)
+        {
+            if((ust_get_current_time() - pUsbCore->ap_response_evt_time) > USBC_AP_EVT_DONE_TIMEOUT)
+            {              
+                usbc_trace_warn(USBCORE_WAIT_AP_RESET_DOWN_TIMEOUT);
+                pUsbCore->ap_response_reset_evt_done = KAL_TRUE;
+            }
+            else
+            {
+                kal_sleep_task(1);
+                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+                break;
+            }
+        }
+
+        if(!usbc_dequeue_ind(&ind_dequeued))
+            break;
+        switch (ind_dequeued.type) {
+        case USBC_IND_CTRL_SETUP:
+            ASSERT(pUsbCore->setup_indicated);
+            intf = &pUsbCore->class_interface[ind_dequeued.data];
+            class_device_id = pUsbCore->class_interface[ind_dequeued.data].class_device_id;
+
+            if (USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE == intf->state &&
+                NULL != intf->notify_control_setup_packet) {
+                if(pUsbCore->class_device[class_device_id].owner != USB_CLASS_OWNER_MD)
+                {
+                    /*send setup packet to AP over CCCI if interface is AP owner. block function*/
+                    if(usbc_dual_owner_class_ctrl_request != NULL)
+                        usbc_dual_owner_class_ctrl_request();
+                    break;
+                }
+                intf->notify_control_setup_packet(intf->class_device_id, &pUsbCore->setup_packet);
+            } else {
+                usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+            }
+            break;
+
+        case USBC_IND_CTRL_CMPLT:
+            intf = &pUsbCore->class_interface[ind_dequeued.data];
+            class_device_id = pUsbCore->class_interface[ind_dequeued.data].class_device_id;
+
+            if (USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE == intf->state &&
+                NULL != intf->notify_control_complete) {
+                /*send data to AP over CCCI, if interface is AP owner and direction is OUT.*/
+                /*do nothing when IN*/
+                if(pUsbCore->class_device[class_device_id].owner != USB_CLASS_OWNER_MD){
+                    if(usbc_dual_owner_class_ctrl_complete != NULL)
+                        usbc_dual_owner_class_ctrl_complete();
+                    break;
+                }
+                intf->notify_control_complete(intf->class_device_id);
+            }
+            break;
+
+        case USBC_IND_DEV_EVENT:
+            switch ((usbc_usb_state_e)ind_dequeued.data) {
+            case USBC_USB_STATE_ATTACHING:
+                usbc_core_notify_state_attaching();
+                break;
+            case USBC_USB_STATE_ATTACHED:
+                usbc_core_notify_state_attached();
+                break;
+            case USBC_USB_STATE_DETACHING:
+                usbc_core_notify_state_detaching();                
+                break;
+            case USBC_USB_STATE_SUSPENDING:
+                usbc_core_notify_state_suspending();
+                break;
+            case USBC_USB_STATE_RESUME:
+                usbc_core_notify_state_resume();
+                break;
+            case USBC_USB_STATE_RESET:
+                usbc_core_notify_state_reset();
+                pUsbCore->usb_configuration = 0;
+#ifndef __PRODUCTION_RELEASE__
+/* under construction !*/
+/* under construction !*/
+#endif
+                break;
+            default:
+                ASSERT(KAL_FALSE);
+                break;
+            }
+            /*send state to AP over CCCI, if state is attached, send all port infomation to AP in addition.*/
+            if(usbc_dual_owner_notify_event != NULL)
+                usbc_dual_owner_notify_event((usbc_usb_state_e)ind_dequeued.data, ind_dequeued.ext);
+            
+            break;
+
+        case USBC_IND_SPEED_CHANGE:
+            usbc_core_notify_speed_change((usbc_usb_speed_e)ind_dequeued.data);
+            break;
+
+        case USBC_IND_ALT_SETTING:
+            usbc_core_notify_alternate_setting(ind_dequeued.ext, ind_dequeued.data);
+            break;
+
+        case USBC_IND_PIPE_STALL:
+            usbc_normal_hif_sc_stall(ind_dequeued.data, (1 == ind_dequeued.ext) ? KAL_TRUE : KAL_FALSE, &owner);
+            usbc_core_notify_stall(
+                    ((ind_dequeued.data & 0x80) ? KAL_TRUE : KAL_FALSE), /* is_tx */
+                    (ind_dequeued.data & 0x7f), /* queue_idx */
+                    ((1 == ind_dequeued.ext) ? KAL_TRUE : KAL_FALSE)); /* stall */
+            
+            if(owner == USB_CLASS_OWNER_MD)
+                usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+            break;
+        case USBC_IND_MODE_SWITCH:
+            if (ind_dequeued.data < USB_MODE_NUM) {
+                usbc_mode_switch(ind_dequeued.data);
+            } else {
+                ASSERT(KAL_FALSE);
+            }
+            break;
+
+        case USBC_IND_FUNC_EVENT:
+            class_device_id = ind_dequeued.ext;
+
+            if((usbc_func_state_e)ind_dequeued.data == USBC_FUNC_WK_ENABLE ||(usbc_func_state_e)ind_dequeued.data == USBC_FUNC_WK_DISABLE )
+            {            
+                usbc_core_handle_device_wk_feature((usbc_func_state_e)ind_dequeued.data);
+            }
+            else if(pUsbCore->class_device[class_device_id].owner != USB_CLASS_OWNER_MD)
+            {            
+                /*If is not device remote wakeup enable setting, send request to AP*/
+                if(usbc_dual_owner_send_feature_request != NULL)
+                    usbc_dual_owner_send_feature_request();
+            }
+            switch((usbc_func_state_e)ind_dequeued.data)
+            {
+                case USBC_FUNC_WK_ENABLE:
+                     //usbc_core_notify_func_wk_ability(class_device_id, KAL_TRUE);                     
+                     usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    break;
+                case USBC_FUNC_WK_DISABLE:
+                    //usbc_core_notify_func_wk_ability(class_device_id, KAL_FALSE);                    
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    break;
+                case USBC_FUNC_STATE_SUSPENDING:
+                    usbc_core_notify_function_state_suspending(class_device_id);
+                    break;
+                case USBC_FUNC_STATE_RESUME:
+                    usbc_core_notify_function_state_resume(class_device_id);
+                    break;
+                case USBC_FUNC_WK_ENABLE_STATE_SUSPENDING:
+                    usbc_core_notify_func_wk_ability(class_device_id, KAL_TRUE);
+                    usbc_core_notify_function_state_suspending(class_device_id);
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    break;
+                case USBC_FUNC_WK_ENABLE_STATE_RESUME:
+                    usbc_core_notify_function_state_resume(class_device_id);
+                    usbc_core_notify_func_wk_ability(class_device_id, KAL_TRUE);
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    break;
+                case USBC_FUNC_WK_DISABLE_STATE_SUSPENDING:
+                    usbc_core_notify_func_wk_ability(class_device_id, KAL_FALSE);
+                    usbc_core_notify_function_state_suspending(class_device_id);
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    break;
+                case USBC_FUNC_WK_DISABLE_STATE_RESUME:
+                    usbc_core_notify_function_state_resume(class_device_id);
+                    usbc_core_notify_func_wk_ability(class_device_id, KAL_FALSE);
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    break;
+                case USBC_FUNC_SET_FEATURE_ERROR:
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_STALL);
+                    break;
+                default:
+                    ASSERT(KAL_FALSE);
+                    break;
+            }
+            break;
+        case USBC_IND_SET_CONFIG:
+            if(usbc_core_isConfigValid(ind_dequeued.data))
+            {
+                usbc_core_set_usb_configuration(ind_dequeued.data);
+                if(!pUsbCore->config_has_ap_port)
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+            }
+            else
+            {
+                usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_STALL);
+            }
+            break;
+
+        case USBC_IND_UFPM_POLL:
+            break;
+        case USBC_IND_IP_PWRDOWN:
+            //set USB powerdown for lowpower
+            usbc_core_power_down();
+            if(usbc_dual_owner_notify_event != NULL)
+                usbc_dual_owner_notify_event(USBC_USB_STATE_PWRDOWN, 0);
+            pUsbCore->state = USBC_USB_STATE_PWRDOWN;
+            break;
+        default:
+            EXT_ASSERT(0, USBCORE_LOC_TASK_INVALID_ITEM, (kal_uint32)ind_dequeued.type, 0);
+            break;
+        }
+    }
+}
+
+
+static kal_bool usbc_normal_hif_hw_usbq_set_gpd(hif_queue_type_e q_type, kal_uint8 queue_no, qbm_gpd* first_gpd, qbm_gpd* last_gpd)
+{
+    kal_bool        result = KAL_FALSE;
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    if (first_gpd != last_gpd) {
+        usbc_data_trace(MD_TRC_USBCORE_CLASS_SUBMIT_IO_REQUEST_HWQ, ((q_type << 8) | (queue_no & 0xFF)), (kal_uint32)first_gpd, (kal_uint32)last_gpd);
+    } else {
+        usbc_data_trace(MD_TRC_USBCORE_CLASS_SUBMIT_IO_REQUEST_HWQ_ONE, ((q_type << 8) | (queue_no & 0xFF)), (kal_uint32)first_gpd);
+    }
+    result = hifusbq_set_gpd(q_type, queue_no, first_gpd, last_gpd);
+
+    return result;
+}
+
+static kal_bool usbc_normal_hif_sw_usbq_set_gpd(hif_queue_type_e q_type, kal_uint8 queue_no, qbm_gpd* first_gpd, qbm_gpd* last_gpd)
+{
+    kal_bool        result = KAL_FALSE;
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    USBC_CLASS_COMMON_LOCK(pUsbCore->usbc_class_resume_mutex);
+    if (first_gpd != last_gpd) {
+        usbc_data_trace(MD_TRC_USBCORE_CLASS_SUBMIT_IO_REQUEST_SWQ, ((q_type << 8) | (queue_no & 0xFF)), (kal_uint32)first_gpd, (kal_uint32)last_gpd);
+    } else {
+        usbc_data_trace(MD_TRC_USBCORE_CLASS_SUBMIT_IO_REQUEST_SWQ_ONE, ((q_type << 8) | (queue_no & 0xFF)), (kal_uint32)first_gpd);
+    }
+    result = hifusbq_pwrsave_buffer_gpd(q_type, queue_no, first_gpd, last_gpd);
+
+    if (result == KAL_TRUE && usbc_core_get_instance()->state != USBC_USB_STATE_SUSPENDED) {
+        if (q_type == HIFQ_TYPE_TX) {
+            usbc_data_trace(MD_TRC_USBCORE_RESTORE_TX_GPD_SWQ2HWQ, (HIFQ_TYPE_TX << 8) | (queue_no & 0xFF) );
+        }
+        else if (q_type == HIFQ_TYPE_RX) {
+            usbc_data_trace(MD_TRC_USBCORE_RESTORE_RX_GPD_SWQ2HWQ, (HIFQ_TYPE_RX << 8) | (queue_no & 0xFF) );
+        }
+
+        result = hifusbq_pwrsave_restore_gpd(q_type, queue_no);
+    }
+    USBC_CLASS_COMMON_UNLOCK(pUsbCore->usbc_class_resume_mutex);
+
+    return result;
+}
+
+static kal_bool usbc_normal_hif_usbq_chk_empty(hif_queue_type_e core_queue_hif_type, kal_uint8 q_num)
+{
+    kal_bool isTx = ((core_queue_hif_type == HIFQ_TYPE_RX) || (core_queue_hif_type == HIFQ_TYPE_RX_W_BPS))? KAL_FALSE:KAL_TRUE;
+    return hifusb_chk_que_empty(isTx, q_num);
+}
+
+void usbc_normal_hif_factory(void)
+{
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    usbc_core_indicate_control_setup_packet = usbc_normal_hif_indicate_control_setup_packet;
+    usbc_core_indicate_control_complete = usbc_normal_hif_indicate_control_complete;
+    usbc_core_indicate_alternate_setting = usbc_normal_hif_indicate_alternate_setting;
+    usbc_core_indicate_stall = usbc_normal_hif_indicate_stall;
+    usbc_core_set_control_request = usbc_normal_hif_set_control_request;
+    usbc_core_set_property = hifusb_set_property;
+    usbc_core_set_usb_address = usbc_normal_hif_set_usb_address;
+    usbc_core_set_usb_configuration = usbc_normal_hif_set_usb_configuration;
+    usbc_core_set_stall = usbc_normal_hif_set_stall;
+    usbc_core_clear_stall = usbc_normal_hif_clear_stall;
+	usbc_core_rst_ep = usbc_normal_hif_rst_ep;
+    usbc_core_set_usb_testmode = hifusb_set_usb_testmode;
+#if __USBC_TARGET_HIF_DRIVER_SUPPORT__
+    usbc_core_set_ss_dev_init_u1_en = hifusb_ss_dev_init_u1_en;
+    usbc_core_set_ss_dev_init_u2_en = hifusb_ss_dev_init_u2_en;
+#endif
+    usbc_core_set_usbhif_address = hifusb_set_usb_address;
+    usbc_core_set_usbhif_configuration = hifusb_set_usb_configuration;
+    usbc_core_set_usbhif_connect = hifusb_set_connect;
+    usbc_core_set_usbhif_disconnect = hifusb_set_disconnect;
+    usbc_core_set_usbhifq_gpd = usbc_normal_hif_hw_usbq_set_gpd;
+    usbc_core_poll_hifusbq_gpd = hifusbq_poll_queue;
+    usbc_core_check_hifusbq_empty = usbc_normal_hif_usbq_chk_empty;
+    usbc_core_flush_hifusbq_gpd = hifusbq_flush_gpd;
+    usbc_core_flush_sw_hifusbq_gpd = hifusbq_pwrsave_flush_gpd;
+    usbc_core_check_new_packet = usbc_normal_hif_chk_newpkt;
+#ifdef __MTK_MD_DIRECT_USB_SUPPORT__
+    usbc_core_check_hifusbq_empty = usbc_direct_hif_usbq_chk_empty;
+    usbc_core_set_usbhif_address = usbc_direct_hifusb_set_usb_address_emulate;
+    usbc_core_set_usbhif_connect = usbc_direct_hifusb_set_usbhif_connect_disconnect;
+    usbc_core_set_usbhif_disconnect = usbc_direct_hifusb_set_usbhif_connect_disconnect;
+#endif
+    usbc_core_start_dataq = usbc_normal_hif_start_dataq;
+    usbc_core_power_down = hifusb_ip_pwrdn;
+    usbc_core_set_clock_cg = hifusb_set_clock_cg;
+    usbc_core_mask_wakeup_event = hifusb_mask_usb_wakeup_event;
+    usbc_core_mask_intr = hifusb_mask_mac_intr;
+}
+
+void usbc_meta_hif_factory(void)
+{
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    usbc_core_set_property = hifusb_set_property_emulate;
+    usbc_core_set_usbhif_address = hifusb_set_usb_address_emulate;
+    usbc_core_set_usbhif_configuration = hifusb_set_usb_configuration_emulate;
+}
+
+void usbc_suspended_hif_factory(void)
+{
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    // Update function pointer for buffering GPDs in DRAM
+    usbc_core_set_usbhifq_gpd = usbc_normal_hif_sw_usbq_set_gpd;
+}
+
+
+#ifdef ATEST_SYS_USBCORE
+void usbc_fake_hif_factory(void)
+{
+    usbc_core_set_control_request = usbc_ut_fake_set_control_request;
+}
+#endif
+
+void usbc_normal_hif_meta_attach(void)
+{
+    usbc_core_t        *pUsbCore = usbc_core_get_instance();
+    hifusb_boot_info_t usb_boot_info;
+
+    /* get USB HW info */
+    hifusb_get_boot_info(&usb_boot_info);
+
+    /* emulate driver connection */
+    usbc_core_notify_state_attaching();
+
+    /* emulate HIFUSB_NOTIFY_EVT_RESET */
+    hifusb_reset_isr_emulate();
+    usbc_core_speed_change(pUsbCore, (usbc_usb_speed_e)usb_boot_info.usb_speed);    // emulate speed change notify
+    usbc_meta_hif_factory();
+
+    /* emulate SetAddress */
+    usbc_core_set_usb_address(usb_boot_info.usb_addr & 0x7f);     // set USB address
+
+    /* emulate SetConfig */
+    usbc_core_set_usb_configuration(1);   //set USB configuration, assume there is only one configuration in META mode
+    usbc_core_notify_state_attached();
+
+    /* restore function pointers of USB driver to normal state*/
+    usbc_normal_hif_factory();
+
+    // Clean USB indication queue
+    usbc_empty_ind_queue();
+}
+
+kal_bool usbc_normal_hif_is_meta_reused(void)
+{
+    hifusb_boot_info_t usb_boot_info;
+
+    /* get USB HW info */
+    hifusb_get_boot_info(&usb_boot_info);
+
+#if defined(__MTK_TARGET__) && defined(__MULTI_BOOT__)
+    return ((INT_BootMode() == MTK_FACTORY_MODE) && (usb_boot_info.boot_type == HIFUSB_BOOT_SUSPEND))? KAL_TRUE:KAL_FALSE;
+#else
+    return KAL_FALSE;
+#endif
+}
+
+kal_bool usbc_normal_hif_restore_gpd_pwrsave()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 queue_no;
+    kal_bool result;
+
+
+    USBC_NON_EXCEPTION_MODE_CHECK();
+
+    // Restore Tx GPDs
+    for(queue_no = 0; queue_no < pUsbCore->total_tx_queues; queue_no++)
+    {
+        if(pUsbCore->tx_queue[queue_no].owner != USB_CLASS_OWNER_MD){
+            continue;
+        }
+        usbc_data_trace(MD_TRC_USBCORE_RESTORE_TX_GPD_SWQ2HWQ, (HIFQ_TYPE_TX << 8) | (queue_no & 0xFF) );
+        result = hifusbq_pwrsave_restore_gpd(HIFQ_TYPE_TX, queue_no);
+        ASSERT(result);
+    }
+
+    // Restore Rx GPDs
+    for(queue_no = 0; queue_no < pUsbCore->total_rx_queues; queue_no++)
+    {
+        if(pUsbCore->rx_queue[queue_no].owner != USB_CLASS_OWNER_MD){
+            continue;
+        }
+        usbc_data_trace(MD_TRC_USBCORE_RESTORE_RX_GPD_SWQ2HWQ, (HIFQ_TYPE_RX << 8) | (queue_no & 0xFF) );
+        result = hifusbq_pwrsave_restore_gpd(HIFQ_TYPE_RX, queue_no);
+        ASSERT(result);
+    }
+
+    return KAL_TRUE;
+}
+
+/*------------------------------------------------------------------------------
+ * USB Core internal implementation for HIF direct mode.
+ *----------------------------------------------------------------------------*/
+#ifdef __MTK_MD_DIRECT_USB_SUPPORT__ 
+void usbc_direct_hif_factory(void)
+{
+    usbc_normal_hif_factory();
+    usbc_core_check_hifusbq_empty = usbc_direct_hif_usbq_chk_empty;
+    usbc_core_set_usbhif_address = usbc_direct_hifusb_set_usb_address_emulate;
+    usbc_core_set_usbhif_connect = usbc_direct_hifusb_set_usbhif_connect_disconnect;
+    usbc_core_set_usbhif_disconnect = usbc_direct_hifusb_set_usbhif_connect_disconnect;
+}
+#endif
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_ind_q.c b/mcu/middleware/hif/usbcore/src/usbcore_ind_q.c
new file mode 100644
index 0000000..cfe6193
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_ind_q.c
@@ -0,0 +1,434 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   usbcore_ind_q.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   USB Core indication queue operations.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#include "kal_public_api.h"
+#include "intrCtrl.h"
+#include "usbcore_debug.h"
+#include "usbcore_ind_q.h"
+
+#define USBC_UT_IND 0
+
+#define USBC_MAX_IND_QUEUE_LEN          128 /* Maximal number of indication in queue. It got to be 2's power and must larger than 6. */
+#define USBC_MAX_IND_QUEUE_LEN_MASK     (USBC_MAX_IND_QUEUE_LEN - 1)
+
+
+static kal_uint32   usbc_ind_queue_head_s = 0;
+static kal_uint32   usbc_ind_queue_len_s = 0;
+static usbc_ind_t   usbc_ind_queue_s[USBC_MAX_IND_QUEUE_LEN];
+static kal_spinlockid usbc_ind_q_spinlock = NULL;
+
+/*------------------------------------------------------------------------------
+ * Private implementation 
+ *----------------------------------------------------------------------------*/ 
+#define USBC_IND_QUEUE_LOCK(_stack_var) \
+            _stack_var = SaveAndSetIRQMask()
+
+#define USBC_IND_QUEUE_UNLOCK(_stack_var) \
+            RestoreIRQMask(_stack_var)
+
+#define USBC_IND_QUEUE_TAKE_SPINLOCK()   \
+            kal_take_spinlock(usbc_ind_q_spinlock, KAL_INFINITE_WAIT)
+
+#define USBC_IND_QUEUE_GIVE_SPINLOCK()   \
+            kal_give_spinlock(usbc_ind_q_spinlock)
+
+#define USBC_IS_IND_QUEUE_FULL() \
+            (USBC_MAX_IND_QUEUE_LEN == usbc_ind_queue_len_s)
+
+#define USBC_IS_IND_QUEUE_EMPTY() \
+            (0 == usbc_ind_queue_len_s)
+
+#define USBC_GET_IND_QUEUE_INDEX(_index) \
+            ((_index) & USBC_MAX_IND_QUEUE_LEN_MASK)
+
+#define USBC_COPY_IND(_dst_ind, _src_ind) \
+            kal_mem_cpy((_dst_ind), (_src_ind), sizeof(usbc_ind_t))
+
+#if !USBC_UT_IND
+    #define USBC_IND_QUEUE_FULL_ASSERT(expr, e1, e2, e3) EXT_ASSERT(expr, e1, e2, e3)
+#else
+    #define USBC_IND_QUEUE_FULL_ASSERT(expr, e1, e2, e3)
+#endif
+/*------------------------------------------------------------------------------
+ * Public interface
+ *----------------------------------------------------------------------------*/
+kal_bool usbc_ind_queue_spinlock_init()
+{
+    kal_char usbc_class_mutex_name[50];
+
+    sprintf(usbc_class_mutex_name, "USBC_IND_Q_SPINLOCK");
+    usbc_ind_q_spinlock = kal_create_spinlock(usbc_class_mutex_name);
+
+    return (NULL != usbc_ind_q_spinlock)? KAL_TRUE:KAL_FALSE;
+}
+
+void usbc_empty_ind_queue()
+{
+    USBC_IND_QUEUE_TAKE_SPINLOCK();
+
+    if (!USBC_IS_IND_QUEUE_EMPTY()) 
+    {
+        usbc_ind_queue_head_s = usbc_ind_queue_len_s = 0;
+    }
+
+    USBC_IND_QUEUE_GIVE_SPINLOCK();
+
+    return;
+}
+
+void usbc_enqueue_ind(usbc_ind_t *indication)
+{
+    kal_uint32  new_tail;
+    kal_uint32  next_one;
+
+    USBC_IND_QUEUE_TAKE_SPINLOCK();
+
+    if (!USBC_IS_IND_QUEUE_FULL()) {
+        new_tail = USBC_GET_IND_QUEUE_INDEX(usbc_ind_queue_head_s + usbc_ind_queue_len_s);
+        usbc_ind_queue_len_s++;
+    } else {
+        /*
+         * If queue is full, we discard OLDEST NON-control request indication.
+         * Since HIF driver guarantees at most one control transfer is on-going,
+         * there are at most 1 CTRL_CMPLT and 1 SETUP_CMPLT in queue.
+         */
+        new_tail = usbc_ind_queue_head_s;
+        usbc_ind_queue_head_s = USBC_GET_IND_QUEUE_INDEX(usbc_ind_queue_head_s + 1);
+        if (USBC_IND_CTRL_SETUP == usbc_ind_queue_s[new_tail].type || 
+            USBC_IND_CTRL_CMPLT == usbc_ind_queue_s[new_tail].type) {
+
+            USBC_IND_QUEUE_FULL_ASSERT(0, USBCORE_LOC_TASK_QUE_FULL, 0, 0);
+            if (USBC_IND_CTRL_SETUP == usbc_ind_queue_s[usbc_ind_queue_head_s].type ||
+                USBC_IND_CTRL_CMPLT == usbc_ind_queue_s[usbc_ind_queue_head_s].type) {
+
+                next_one = USBC_GET_IND_QUEUE_INDEX(usbc_ind_queue_head_s + 1);
+                USBC_COPY_IND(&usbc_ind_queue_s[next_one], &usbc_ind_queue_s[usbc_ind_queue_head_s]);
+            }
+            USBC_COPY_IND(&usbc_ind_queue_s[usbc_ind_queue_head_s], &usbc_ind_queue_s[new_tail]);
+        }
+    }
+
+    USBC_COPY_IND(&usbc_ind_queue_s[new_tail], indication);
+
+    USBC_IND_QUEUE_GIVE_SPINLOCK();
+}
+
+kal_bool usbc_dequeue_ind(usbc_ind_t *indication)
+{
+    kal_bool    succeeded;
+
+    USBC_IND_QUEUE_TAKE_SPINLOCK();
+
+    if (USBC_IS_IND_QUEUE_EMPTY()) {
+        succeeded = KAL_FALSE;
+    } else {
+        succeeded = KAL_TRUE;
+        USBC_COPY_IND(indication, &usbc_ind_queue_s[usbc_ind_queue_head_s]);
+        usbc_ind_queue_head_s = USBC_GET_IND_QUEUE_INDEX(usbc_ind_queue_head_s + 1);
+        usbc_ind_queue_len_s--;
+    }
+
+    USBC_IND_QUEUE_GIVE_SPINLOCK();
+
+    return succeeded;
+}
+
+kal_bool usbc_queue_empty_check()
+{
+    return USBC_IS_IND_QUEUE_EMPTY();
+}
+
+#if USBC_UT_IND
+
+#define USBC_IND_UT_TYPE_MASK       0x3
+#define USBC_IND_UT_DATA_MASK       0x3f
+
+void usbc_ut_ind(void)
+{
+    kal_uint32  burst_len;
+    kal_uint32  idx;
+    kal_uint32  start_pos;
+    usbc_ind_t  ind_to_enqueue;
+    usbc_ind_t  ind_dequeued;
+
+    for (burst_len = 1; burst_len <= USBC_MAX_IND_QUEUE_LEN; burst_len++) {
+        for (start_pos = 0; start_pos < USBC_MAX_IND_QUEUE_LEN; start_pos++) {
+            /*
+             * Change queue head index.
+             */
+            USBC_IND_QUEUE_TAKE_SPINLOCK();
+            ASSERT(USBC_IS_IND_QUEUE_EMPTY());
+            usbc_ind_queue_head_s = start_pos;
+            USBC_IND_QUEUE_TAKE_SPINLOCK();
+
+            /*
+             * Enqueue burst of indications.
+             */
+            for (idx = 0; idx < burst_len; idx++) {
+                ind_to_enqueue.type = (idx & USBC_IND_UT_TYPE_MASK);
+                ind_to_enqueue.data = (idx & USBC_IND_UT_DATA_MASK);
+    
+                usbc_enqueue_ind(&ind_to_enqueue);
+            }
+
+            /*
+             * Dequeue burst of indications and check the correctness.
+             */   
+            for (idx = 0; idx < burst_len; idx++) {
+                if (!usbc_dequeue_ind(&ind_dequeued)) {
+                    ASSERT(KAL_FALSE);
+                }
+                if ((idx & USBC_IND_UT_TYPE_MASK) != ind_dequeued.type) {
+                    ASSERT(KAL_FALSE);
+                }
+                if ((idx & USBC_IND_UT_DATA_MASK) != ind_dequeued.data) {
+                    ASSERT(KAL_FALSE);
+                }
+            }
+    
+            /*
+             * Check dequeue at empty queue condition.
+             */
+            if (usbc_dequeue_ind(&ind_dequeued)) {
+                ASSERT(KAL_FALSE);
+            }
+        }
+    }
+
+    /*
+     * Check enqueue at queue full with last indication is a device event.
+     */
+    ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+    ind_to_enqueue.data = 0x23;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    for (idx = 1; idx < USBC_MAX_IND_QUEUE_LEN; idx++) {
+        ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+        ind_to_enqueue.data = (idx & USBC_IND_UT_DATA_MASK);
+        usbc_enqueue_ind(&ind_to_enqueue);
+    }
+
+    ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+    ind_to_enqueue.data = 0x18;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    for (idx = 1; idx < USBC_MAX_IND_QUEUE_LEN; idx++) {
+        if (!usbc_dequeue_ind(&ind_dequeued)) {
+            ASSERT(KAL_FALSE);
+        }
+        if (USBC_IND_DEV_EVENT != ind_dequeued.type) {
+            ASSERT(KAL_FALSE);
+        }
+        if ((idx & USBC_IND_UT_DATA_MASK) != ind_dequeued.data) {
+            ASSERT(KAL_FALSE);
+        }
+    }
+
+    if (!usbc_dequeue_ind(&ind_dequeued)) {
+        ASSERT(KAL_FALSE);
+    }
+    if (USBC_IND_DEV_EVENT != ind_dequeued.type) {
+        ASSERT(KAL_FALSE);
+    }
+    if (0x18 != ind_dequeued.data) {
+        ASSERT(KAL_FALSE);
+    }
+
+    /*
+     * Check enqueue at queue full with last indication is a control transfer.
+     */
+    ind_to_enqueue.type = USBC_IND_CTRL_SETUP;
+    ind_to_enqueue.data = 0x23;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    for (idx = 1; idx < USBC_MAX_IND_QUEUE_LEN; idx++) {
+        ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+        ind_to_enqueue.data = (idx & USBC_IND_UT_DATA_MASK);
+        usbc_enqueue_ind(&ind_to_enqueue);
+    }
+
+    ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+    ind_to_enqueue.data = 0x18;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    if (!usbc_dequeue_ind(&ind_dequeued)) {
+        ASSERT(KAL_FALSE);
+    }
+    if (USBC_IND_CTRL_SETUP != ind_dequeued.type) {
+        ASSERT(KAL_FALSE);
+    }
+    if (0x23 != ind_dequeued.data) {
+        ASSERT(KAL_FALSE);
+    }
+
+    for (idx = 2; idx < USBC_MAX_IND_QUEUE_LEN; idx++) {
+        if (!usbc_dequeue_ind(&ind_dequeued)) {
+            ASSERT(KAL_FALSE);
+        }
+        if (USBC_IND_DEV_EVENT != ind_dequeued.type) {
+            ASSERT(KAL_FALSE);
+        }
+        if ((idx & USBC_IND_UT_DATA_MASK) != ind_dequeued.data) {
+            ASSERT(KAL_FALSE);
+        }
+    }
+
+    if (!usbc_dequeue_ind(&ind_dequeued)) {
+        ASSERT(KAL_FALSE);
+    }
+    if (USBC_IND_DEV_EVENT != ind_dequeued.type) {
+        ASSERT(KAL_FALSE);
+    }
+    if (0x18 != ind_dequeued.data) {
+        ASSERT(KAL_FALSE);
+    }
+
+    /*
+     * Check enqueue at queue full with last two indications are control transfer related.
+     */
+    ind_to_enqueue.type = USBC_IND_CTRL_SETUP;
+    ind_to_enqueue.data = 0x23;
+    usbc_enqueue_ind(&ind_to_enqueue);
+    ind_to_enqueue.type = USBC_IND_CTRL_SETUP;
+    ind_to_enqueue.data = 0x33;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+
+    for (idx = 2; idx < USBC_MAX_IND_QUEUE_LEN; idx++) {
+        ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+        ind_to_enqueue.data = (idx & USBC_IND_UT_DATA_MASK);
+        usbc_enqueue_ind(&ind_to_enqueue);
+    }
+
+    ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+    ind_to_enqueue.data = 0x18;
+    usbc_enqueue_ind(&ind_to_enqueue);
+
+    if (!usbc_dequeue_ind(&ind_dequeued)) {
+        ASSERT(KAL_FALSE);
+    }
+    if (USBC_IND_CTRL_SETUP != ind_dequeued.type) {
+        ASSERT(KAL_FALSE);
+    }
+    if (0x23 != ind_dequeued.data) {
+        ASSERT(KAL_FALSE);
+    }
+    if (!usbc_dequeue_ind(&ind_dequeued)) {
+        ASSERT(KAL_FALSE);
+    }
+    if (USBC_IND_CTRL_SETUP != ind_dequeued.type) {
+        ASSERT(KAL_FALSE);
+    }
+    if (0x33 != ind_dequeued.data) {
+        ASSERT(KAL_FALSE);
+    }
+
+    for (idx = 3; idx < USBC_MAX_IND_QUEUE_LEN; idx++) {
+        if (!usbc_dequeue_ind(&ind_dequeued)) {
+            ASSERT(KAL_FALSE);
+        }
+        if (USBC_IND_DEV_EVENT != ind_dequeued.type) {
+            ASSERT(KAL_FALSE);
+        }
+        if ((idx & USBC_IND_UT_DATA_MASK) != ind_dequeued.data) {
+            ASSERT(KAL_FALSE);
+        }
+    }
+
+    if (!usbc_dequeue_ind(&ind_dequeued)) {
+        ASSERT(KAL_FALSE);
+    }
+    if (USBC_IND_DEV_EVENT != ind_dequeued.type) {
+        ASSERT(KAL_FALSE);
+    }
+    if (0x18 != ind_dequeued.data) {
+        ASSERT(KAL_FALSE);
+    }
+}
+#endif
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_notify_event.c b/mcu/middleware/hif/usbcore/src/usbcore_notify_event.c
new file mode 100644
index 0000000..724157a
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_notify_event.c
@@ -0,0 +1,466 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   usbcore_notify_event.c
+ *
+ * Project:
+ * --------
+ *   TATAKA
+ *
+ * Description:
+ * ------------
+ *   Helper routine to notify USBCLASS changes.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *                 HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "usbcore_main.h"
+#include "usbcore_hif.h"
+#include "usbcore_class_device.h"
+#include "usbc_custom.h"
+#include "hif_ior.h"
+#include "hif_mw_msgid.h"
+#include "usbidle_if.h"
+#include "usbcore_debug.h"
+#include "hmu_conf_data.h"
+#include "usbcore_dual_owner.h"
+/*------------------------------------------------------------------------------
+ * Private implementation.
+ *----------------------------------------------------------------------------*/
+static void usbc_core_indicate_state(usbc_usb_state_e state)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_uint8       idx;
+
+    pUsbCore->state = state;
+
+    for (idx = 0; idx < pUsbCore->total_class_devices; idx++) {
+        if ( USBC_CORE_CLASS_DEVICE_STATE_REGISTERED == pUsbCore->class_device[idx].state &&
+             NULL != pUsbCore->class_device[idx].notify_usb_state )
+        {   
+            if ( (state == USBC_USB_STATE_SUSPENDING || state == USBC_USB_STATE_SUSPENDED) &&
+                 pUsbCore->class_device[idx].is_func_suspend )
+            {
+                // do not suspend the class device again if it has been in function suspend state
+            }
+            else if ( state == USBC_USB_STATE_RESUME && pUsbCore->class_device[idx].is_func_suspend )
+            {
+                // do not resume the class device which was function suspended while device resuming
+                // the class device will be resumed later while function resuming
+            }
+            else
+            {
+                usbc_trace_info(USBCORE_NOTIFY_CLASS_START, pUsbCore->class_device[idx].class_type, state);
+                pUsbCore->class_device[idx].notify_usb_state(idx,state);
+                usbc_trace_info(USBCORE_NOTIFY_CLASS_END, pUsbCore->class_device[idx].class_type, state);
+            }
+        } 
+    }
+}
+
+
+/*!
+ *  @brief This function is used to notify function suspend or function resume to a specific class device
+ */
+void usbc_core_indicate_function_state(kal_uint8 class_device_id, usbc_usb_state_e state)
+{
+    usbc_core_t *pUsbCore = usbc_core_get_instance();    
+
+    if ( USBC_CORE_CLASS_DEVICE_STATE_REGISTERED == pUsbCore->class_device[class_device_id].state &&
+         NULL != pUsbCore->class_device[class_device_id].notify_usb_state )
+    {
+        usbc_trace_info(USBCORE_NOTIFY_CLASS_START, pUsbCore->class_device[class_device_id].class_type, state);
+        pUsbCore->class_device[class_device_id].notify_usb_state(class_device_id, state);
+        usbc_trace_info(USBCORE_NOTIFY_CLASS_END, pUsbCore->class_device[class_device_id].class_type, state);
+
+    }
+}
+
+/*------------------------------------------------------------------------------
+ * Public interface.
+ *----------------------------------------------------------------------------*/
+void usbc_core_notify_state_attaching()
+{
+    usbc_core_indicate_state(USBC_USB_STATE_ATTACHING);
+}
+
+
+void usbc_core_notify_state_attached()
+{
+    usbc_core_indicate_state(USBC_USB_STATE_ATTACHED);
+}
+
+
+void usbc_core_notify_state_detaching()
+{
+    usbc_core_indicate_state(USBC_USB_STATE_DETACHING);
+    usbc_core_indicate_state(USBC_USB_STATE_DETACHED);
+}
+
+
+void usbc_core_notify_state_suspending()
+{
+    kal_uint16 func_list;
+    usbcore_usbidle_l4_power_saving_req_struct *rsp_msg_p;
+
+    // notify USBCLASS of USB suspended
+    usbc_core_indicate_state(USBC_USB_STATE_SUSPENDING);
+    usbc_core_indicate_state(USBC_USB_STATE_SUSPENDED);
+
+    if( USBC_IS_IN_EXCEPTION_MODE() )
+    {
+        return;
+    }	    
+
+    // Updatea function pointer for setting GPDs in DRAM buffer
+    usbc_trace_info(USBCORE_UPDATE_API_BUFF_GPD, 1);
+    usbc_suspended_hif_factory();
+
+    // Ask USBIDLE to notify L4 to turn RF power off or go to fast dormancy
+    func_list = usbc_core_get_function_remote_wk_list();
+    rsp_msg_p = (usbcore_usbidle_l4_power_saving_req_struct*)construct_local_para(sizeof(usbcore_usbidle_l4_power_saving_req_struct), TD_RESET);
+    ASSERT(rsp_msg_p);
+    rsp_msg_p->notify_suspend = KAL_TRUE;
+    rsp_msg_p->notify_suspend_with_remote_wk = (func_list==0)? KAL_FALSE:KAL_TRUE;
+    usbc_trace_info(USBCORE_DEV_SUSPEND_L4, 1, 1, 1, (rsp_msg_p->notify_suspend_with_remote_wk? 1:0));
+    usb_idle_set_l4_power_saving(KAL_TRUE);
+    msg_send6(MOD_USBCORE,  // src module
+              MOD_USBIDLE,  // dst module
+              0,       // sap id
+              MSG_ID_USBCORE_IDLE_NOTIFY_TO_L4,
+              (local_para_struct*)rsp_msg_p,
+              0); //msg id
+}
+
+
+void usbc_core_notify_state_resume()
+{
+    kal_bool remote_wakeup_enabled = (usbc_core_get_function_remote_wk_list()==0)? KAL_FALSE:KAL_TRUE;
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+
+    if( USBC_IS_IN_EXCEPTION_MODE() )
+    {
+        usbc_core_indicate_state(USBC_USB_STATE_RESUME);
+        return;
+    }
+
+
+    // nofity USBIDLE that it does not have to gate the clock of USB IP
+    usbc_trace_info(USBCORE_DEV_SUSPEND_CLOCK, 0, 0);
+    usb_idle_set_clockGating(KAL_FALSE);
+
+    USBC_CLASS_COMMON_LOCK(pUsbCore->usbc_class_resume_mutex);
+    // Notify USB resume event to USB classes
+    usbc_core_indicate_state(USBC_USB_STATE_RESUME);
+
+    // Set GPDs that are buffered in DRAM to hardware
+    usbc_normal_hif_restore_gpd_pwrsave();
+
+    // Update function pointer for set GPDs to hardware normally
+    usbc_trace_info(USBCORE_UPDATE_API_BUFF_GPD, 0);
+    usbc_normal_hif_factory();
+    USBC_CLASS_COMMON_UNLOCK(pUsbCore->usbc_class_resume_mutex);
+
+    // Set USBCORE task to wait for both indication events and tick events
+    usbc_trace_info(USBCORE_SUSPEND_START_POLL);
+    usbc_core_get_instance()->hmu_indication = HIF_DRV_EG_HIF_TICK_EVENT | HIF_DRV_EG_USBC_IND_EVENT;
+
+    // Ask USBIDLE to notify L4 to turn RF power on or go back to normal operation state
+    usbc_trace_info(USBCORE_DEV_SUSPEND_L4, 0, 0, 0, (remote_wakeup_enabled? 1:0));
+    usb_idle_set_l4_power_saving(KAL_FALSE);
+    usb_idle_event_notify_to_l4(KAL_FALSE, remote_wakeup_enabled);
+}
+
+
+void usbc_core_notify_state_reset()
+{
+    kal_bool remote_wakeup_enabled = (usbc_core_get_function_remote_wk_list()==0)? KAL_FALSE:KAL_TRUE;
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+
+    if( USBC_IS_IN_EXCEPTION_MODE() )
+    {
+        usbc_core_indicate_state(USBC_USB_STATE_RESET);
+        usbc_core_clear_status();
+        return;
+    }
+
+    // nofity USBIDLE that it does not have to gate the clock of USB IP
+    usbc_trace_info(USBCORE_DEV_SUSPEND_CLOCK, 0, 0);
+    usb_idle_set_clockGating(KAL_FALSE);
+
+    USBC_CLASS_COMMON_LOCK(pUsbCore->usbc_class_resume_mutex);
+
+    // Set GPDs that are buffered in DRAM to hardware
+    usbc_normal_hif_restore_gpd_pwrsave();
+    
+    usbc_trace_info(USBCORE_UPDATE_API_BUFF_GPD, 0);
+    // Update function pointer for set GPDs to hardware normally
+    usbc_normal_hif_factory();
+    
+    pUsbCore->state = USBC_USB_STATE_RESET;
+    USBC_CLASS_COMMON_UNLOCK(pUsbCore->usbc_class_resume_mutex);
+    
+    // Notify USB reset event to USB classes
+    usbc_core_indicate_state(USBC_USB_STATE_RESET);
+
+    // Clear USB status
+    usbc_core_clear_status();
+
+    // Ask USBIDLE to notify L4 to turn RF power on or go back to normal operation state
+    usbc_trace_info(USBCORE_DEV_SUSPEND_L4, 0, 0, 0, (remote_wakeup_enabled? 1:0));
+    usb_idle_set_l4_power_saving(KAL_FALSE);
+    usb_idle_event_notify_to_l4(KAL_FALSE, remote_wakeup_enabled);
+}
+
+
+void usbc_core_notify_speed_change(usbc_usb_speed_e speed)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_uint8       idx = 0;
+
+    for (idx = 0; idx < pUsbCore->total_class_devices; idx++) {
+        if (USBC_CORE_CLASS_DEVICE_STATE_REGISTERED == pUsbCore->class_device[idx].state &&
+            NULL != pUsbCore->class_device[idx].notify_usb_speed) {
+            pUsbCore->class_device[idx].notify_usb_speed(idx, speed);
+        }
+    }
+}
+
+void usbc_core_notify_alternate_setting(kal_uint8 intf_idx, kal_uint8 alternate_setting)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    usbc_core_class_interface_t *intf = &pUsbCore->class_interface[intf_idx];
+#if 0                                                                                                                                                                                                   
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+    if (USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE == intf->state &&
+        NULL != intf->notify_alternate_setting) {
+        intf->notify_alternate_setting(
+                    intf->class_device_id,
+                    intf->interface_type,
+                    intf->alternate_setting);
+    }
+}
+
+void usbc_core_notify_stall(kal_bool is_tx, kal_uint8 queue_idx, kal_bool stall)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    usbc_core_queue_t   *pQueue;
+
+    if (is_tx) {
+        pQueue = &pUsbCore->tx_queue[queue_idx];
+    } else {
+        pQueue = &pUsbCore->rx_queue[queue_idx];
+    }
+    
+    /*send stall info to AP over CCCI if this endpoint is AP owner, return after send.*/
+    if(pQueue->owner != USB_CLASS_OWNER_MD && usbc_dual_owner_send_feature_request != NULL)
+    {
+        usbc_dual_owner_send_feature_request();
+    }
+    if (pQueue->state > USBC_CORE_QUEUE_STATE_INITIATED &&
+        NULL != pQueue->notify_stall) {
+        pQueue->notify_stall(pQueue->class_device_id, stall);
+    }
+}
+
+void usbc_core_notify_function_state_suspending(kal_uint8 class_device_id)
+{
+    kal_uint16 func_suspend_list;
+    kal_uint16 func_wk_list = usbc_core_get_function_remote_wk_list();
+    usbc_core_t *pUsbCore = usbc_core_get_instance();
+    usbcore_usbidle_l4_power_saving_req_struct *rsp_msg_p;
+
+    // Notify the specific function of USB suspended
+    if ( !pUsbCore->class_device[class_device_id].is_func_suspend )
+    {
+        usbc_core_indicate_function_state(class_device_id, USBC_USB_STATE_SUSPENDING);
+        usbc_core_indicate_function_state(class_device_id, USBC_USB_STATE_SUSPENDED);
+        pUsbCore->class_device[class_device_id].is_func_suspend = KAL_TRUE;
+    }
+
+    // If all functions of the device are suspended, we notify L4 to do power saving
+    func_suspend_list = usbc_core_get_function_suspend_list();
+    if( !USBC_IS_IN_EXCEPTION_MODE() &&
+        func_suspend_list == ((0x01 << pUsbCore->total_class_devices)-1) )
+    {
+        rsp_msg_p = (usbcore_usbidle_l4_power_saving_req_struct*)construct_local_para(sizeof(usbcore_usbidle_l4_power_saving_req_struct), TD_RESET);
+        ASSERT(rsp_msg_p);
+        rsp_msg_p->notify_suspend = KAL_TRUE;
+        rsp_msg_p->notify_suspend_with_remote_wk = (func_wk_list==0)? KAL_FALSE:KAL_TRUE;
+        usbc_trace_info(USBCORE_DEV_SUSPEND_L4, 1, 1, 1, (rsp_msg_p->notify_suspend_with_remote_wk? 0:1));
+        usb_idle_set_l4_power_saving(KAL_TRUE);
+        msg_send6(MOD_USBCORE,  // src module
+                  MOD_USBIDLE,  // dst module
+                  0,       // sap id
+                  MSG_ID_USBCORE_IDLE_NOTIFY_TO_L4,
+                  (local_para_struct*)rsp_msg_p,
+                  0); //msg id
+    }
+}
+
+void usbc_core_notify_function_state_resume(kal_uint8 class_device_id)
+{
+    kal_uint16 func_suspend_list = usbc_core_get_function_suspend_list();
+    kal_bool remote_wakeup_enabled = (usbc_core_get_function_remote_wk_list()==0)? KAL_FALSE:KAL_TRUE;
+
+    usbc_core_t *pUsbCore = usbc_core_get_instance();
+
+    // Notify the specific function of USB resuming
+    if ( pUsbCore->class_device[class_device_id].is_func_suspend )
+    {
+        usbc_core_indicate_function_state(class_device_id, USBC_USB_STATE_RESUME);
+        pUsbCore->class_device[class_device_id].is_func_suspend = KAL_FALSE;
+    }
+
+    // Notify L4 to go back to normal operation states if function resumes from the status that all functions are suspended before
+    if( !USBC_IS_IN_EXCEPTION_MODE() &&
+        func_suspend_list == ((0x01 << pUsbCore->total_class_devices)-1) )
+    {
+        usbc_trace_info(USBCORE_DEV_SUSPEND_L4, 0, 0, 0, (remote_wakeup_enabled? 0:1));
+        usb_idle_set_l4_power_saving(KAL_FALSE);
+        usb_idle_event_notify_to_l4(KAL_FALSE, remote_wakeup_enabled);
+    }
+}
+
+void usbc_core_notify_func_wk_ability(kal_uint8 class_device_id, kal_bool ability)
+{
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_bool isCapableWk = KAL_FALSE;
+
+    // check the capability of the class device
+    if ( NULL != pUsbCore->class_device[class_device_id].query_func_wk_status)
+    {
+        isCapableWk = ((pUsbCore->class_device[class_device_id].query_func_wk_status(class_device_id) & (kal_uint8)0x01) == 0x01)? KAL_TRUE:KAL_FALSE;
+    }
+    if( ability && !isCapableWk )
+    {
+        usbc_trace_error(USBCORE_NOTIFY_WK_ABILITY_INVALID, pUsbCore->class_device[class_device_id].class_type);
+        ASSERT(0);
+        return;
+    }
+
+    if ( USBC_CORE_CLASS_DEVICE_STATE_REGISTERED == pUsbCore->class_device[class_device_id].state &&
+         NULL != pUsbCore->class_device[class_device_id].notify_func_wk_ability )
+    {
+        usbc_trace_info(USBCORE_NOTIFY_WK_ABILITY_START, pUsbCore->class_device[class_device_id].class_type);
+        pUsbCore->class_device[class_device_id].notify_func_wk_ability(class_device_id, ability);
+        usbc_trace_info(USBCORE_NOTIFY_WK_ABILITY_END, pUsbCore->class_device[class_device_id].class_type);
+    }
+}
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_resource.c b/mcu/middleware/hif/usbcore/src/usbcore_resource.c
new file mode 100644
index 0000000..d1755d1
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_resource.c
@@ -0,0 +1,136 @@
+/*!
+ *  @file usbcore_resource.c
+ *  @author HaoRen Kao
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides usb resource management function
+ */
+
+#include <stdlib.h>
+#include "usbcore_main.h"
+
+void
+usbc_resource_reset(void)
+{
+    usbc_core_t* usbc_inst = usbc_core_get_instance();
+    kal_uint8 idx;
+
+    for (idx = 0; idx < MAX_USBCORE_CONFIG_NUM; idx++)
+    {
+         usbc_inst->resource_interface_number[idx] = 0;
+         usbc_inst->resource_iad_number[idx] = 0;
+         usbc_inst->resource_ep_tx_number[idx] = 0;
+         usbc_inst->resource_ep_rx_number[idx] = 0;
+    }
+    usbc_inst->resource_string_number = 0;
+}
+
+usbc_interface_info_t*
+usbc_get_interface_number(kal_uint8 config_num, kal_uint8 *if_num_p)
+{
+    usbc_core_t* usbc_inst = usbc_core_get_instance();
+
+    ASSERT(config_num < MAX_USBCORE_CONFIG_NUM);
+    ASSERT(usbc_inst->resource_interface_number[config_num] < MAX_USBCORE_INTERFACE_NUM);
+
+    usbc_inst->resource_interface_number[config_num]++;
+    if (if_num_p) {
+        *if_num_p = usbc_inst->resource_interface_number[config_num] - 1;
+    }
+    return (&usbc_inst->if_info[config_num][usbc_inst->resource_interface_number[config_num] - 1]);
+}
+
+kal_uint8
+usbc_get_string_number(void *string)
+{
+    usbc_core_t* usbc_inst = usbc_core_get_instance();
+    usbc_string_descriptor_t* string_dscr;
+
+    ASSERT(string);
+    ASSERT(usbc_inst->resource_string_number < MAX_USBCORE_STRING_DESCRIPTOR_NUM);
+
+	string_dscr = (usbc_string_descriptor_t*)string;
+
+    usbc_inst->resource_string_number++;
+    usbc_inst->string_descriptor[usbc_inst->resource_string_number - 1] = string_dscr;
+    return (usbc_inst->resource_string_number - 1);
+}
+
+usbc_interface_association_descriptor_t*
+usbc_get_iad_number(kal_uint8 config_num, kal_uint8 *iad_num_p)
+{
+    usbc_core_t* usbc_inst = usbc_core_get_instance();
+
+    ASSERT(config_num < MAX_USBCORE_CONFIG_NUM);
+    ASSERT(usbc_inst->resource_iad_number[config_num] < MAX_USBCORE_IAD_NUM);
+
+    usbc_inst->resource_iad_number[config_num]++;
+    if (iad_num_p) {
+        *iad_num_p = usbc_inst->resource_iad_number[config_num] - 1;
+    }
+    return (&usbc_inst->iad_descriptor[config_num][usbc_inst->resource_iad_number[config_num] - 1]);
+}
+
+usbc_endpoint_info_t*
+usbc_get_endpoint_tx_number(kal_uint8 config_num, kal_uint8 *tx_ep_num_p)
+{
+    usbc_core_t* usbc_inst = usbc_core_get_instance();
+
+    ASSERT(config_num < MAX_USBCORE_CONFIG_NUM);
+    ASSERT(usbc_inst->resource_ep_tx_number[config_num] < MAX_USBCORE_QUEUE_NUM);
+
+    usbc_inst->resource_ep_tx_number[config_num]++;
+    if (tx_ep_num_p) {
+        *tx_ep_num_p = usbc_inst->resource_ep_tx_number[config_num];
+    }
+    return (&usbc_inst->ep_tx_info[config_num][usbc_inst->resource_ep_tx_number[config_num] - 1]);
+}
+
+usbc_endpoint_info_t*
+usbc_get_endpoint_rx_number(kal_uint8 config_num, kal_uint8 *rx_ep_num_p)
+{
+    usbc_core_t* usbc_inst = usbc_core_get_instance();
+
+    ASSERT(config_num < MAX_USBCORE_CONFIG_NUM);
+    ASSERT(usbc_inst->resource_ep_rx_number[config_num] < MAX_USBCORE_QUEUE_NUM);
+
+    usbc_inst->resource_ep_rx_number[config_num]++;
+    if (rx_ep_num_p) {
+        *rx_ep_num_p = usbc_inst->resource_ep_rx_number[config_num];
+    }
+    return (&usbc_inst->ep_rx_info[config_num][usbc_inst->resource_ep_rx_number[config_num] - 1]);
+}
+
+
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_stack.c b/mcu/middleware/hif/usbcore/src/usbcore_stack.c
new file mode 100644
index 0000000..42b2054
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_stack.c
@@ -0,0 +1,747 @@
+/*!
+ *  @file usbcore_stack.c
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides interactive functions of usbcore and HMU
+ */
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "usbcore_main.h"
+#include "usbcore_hif.h"
+#include "usbc_custom.h"
+#include "usbcore_debug.h"
+#ifdef __MULTI_BOOT__
+#include "multiboot_config.h"
+#endif /* __MULTI_BOOT__ */
+#include "usbcore_ind_q.h"
+#include "hmu_conf_data.h"
+#include "hmu.h"
+#ifdef __MTK_MD_DIRECT_USB_SUPPORT__
+#include "usbcore_direct.h"
+#endif
+#include "usb_nvram_def.h" 
+#include "dcl.h"
+#ifdef __HIF_CCCI_SUPPORT__
+#include "ccci_if.h"
+#endif
+
+#ifndef __MAUI_BASIC__
+extern kal_uint8 custom_em_get_usb_cdrom_config(void);
+#else
+    #define custom_em_get_usb_cdrom_config(...) 0x00
+#endif
+extern kal_uint16 INT_BootMode(void);
+extern kal_uint32 usb_mode_register_index;
+
+/*------------------------------------------------------------------------------
+ * USB stack initialization.
+ *----------------------------------------------------------------------------*/
+/*
+ * USB stack configuration.
+ */
+
+/*
+ * Bitmap of check-in nodes.
+ */
+static kal_uint32 usbc_stack_nodes_s = 0;
+
+/*
+ * Node registration information.
+ *    0 ~ (USB_FUNC_NUM-1) : USB function node
+ *    USB_FUNC_NUM         : USB Core node
+ */
+#define USBC_NODE_COUNT       USB_CLASS_NUM+1
+static usbc_node_reg_entry_t *usbc_stack_nodes_reg_table_s[USBC_NODE_COUNT];
+
+/*
+ * USB stack helper routines.
+ */
+#define _NODE_TO_BIT(_node) \
+    ( (kal_uint32)1 << (kal_uint32)(_node) )
+
+#define _GET_NODE_VALUE() \
+    usbc_stack_nodes_s
+
+#define _SET_NODE_VALUE(_val) \
+    usbc_stack_nodes_s = (_val)
+
+#define _GET_NODE_REG_TABLE(_node) \
+    usbc_stack_nodes_reg_table_s[(_node)]
+
+#define _SET_NODE_REG_TABLE(_node, _reg_table) \
+    usbc_stack_nodes_reg_table_s[(_node)] = (_reg_table)
+
+#define _CHECKIN_NODE(_node, _reg_table) \
+    (usbc_stack_nodes_s) |= _NODE_TO_BIT(_node); \
+    _SET_NODE_REG_TABLE(_node, _reg_table)
+
+#define _ALL_NODES_CHECKIN() \
+    ( (usbc_stack_nodes_s) == (_NODE_TO_BIT(USBC_NODE_COUNT) - 1) )
+
+
+#define INDEX_TO_CFG(index)   (index+1)
+
+/*
+ * USB language string
+ */
+static const kal_uint16 usb_language_string[] =
+{
+    0x0304,
+    0x0409
+};
+
+/*
+ * Default device descriptor
+ */
+static usbc_device_descriptor_t usbc_default_device_descriptor =
+{
+    /* Device Descriptor */
+    0x12,                           /* bLength              */
+    USBC_DT_DEVICE,                 /* DEVICE               */
+    0x0200,                         /* bcdUSB: USB 2.0      */
+    0xEF,                           /* CLASS                */
+    0x02,                           /* Subclass             */
+    0x01,                           /* Protocol             */
+    0x40,                           /* bMaxPktSize0         */
+    0x0E8D,                         /* idVendor             */
+    0x1234,                         /* idProduct            */
+    0x0001,                         /* bcdDevice            */
+    0x00,                           /* iManufacturer        */
+    0x00,                           /* iProduct             */
+    0x00,                           /* iSerial Number       */
+    0x01                            /* One configuration    */
+};
+
+/*
+ * Default configuration descriptor
+ */
+static usbc_configuration_descriptor_t usbc_default_configuration_descriptor =
+{
+    0x09,                       /* bLength              */
+    0x02,                       /* CONFIGURATION        */
+    0x0000,                     /* length               */
+    0x00,                       /* bNumInterfaces       */
+    0x00,                       /* bConfigurationValue  */
+    0x00,                       /* iConfiguration       */
+    0x80,                       /* bmAttributes (required + self-powered) */
+    0xFA                        /* power                */
+};
+
+void usbc_stack_reset()
+{
+    usbc_stack_nodes_s = 0;
+    kal_mem_set(usbc_stack_nodes_reg_table_s, 0, sizeof(usbc_stack_nodes_reg_table_s));
+}
+
+static usbc_class_init_func_t _get_class_init_func(usb_class_type_e type)
+{
+    usbc_node_reg_entry_t  *curr_entry;
+
+    curr_entry = _GET_NODE_REG_TABLE(type);
+
+    if (curr_entry && curr_entry->init_func) {
+        return (usbc_class_init_func_t)(curr_entry->init_func);
+    } else {
+        return NULL;
+    }
+}
+
+static usbc_class_reinit_func_t _get_class_reinit_func(usb_class_type_e type)
+{
+    usbc_node_reg_entry_t  *curr_entry;
+
+    curr_entry = _GET_NODE_REG_TABLE(type);
+
+    if (curr_entry && curr_entry->reinit_func) {
+        return (usbc_class_reinit_func_t)(curr_entry->reinit_func);
+    } else {
+        return NULL;
+    }
+}
+
+usbc_class_set_config_func_t usbc_get_class_set_config_func(usb_class_type_e type)
+{
+    usbc_node_reg_entry_t  *curr_entry;
+
+    curr_entry = _GET_NODE_REG_TABLE(type);
+
+    if (curr_entry && curr_entry->set_config_func) {
+        return (usbc_class_set_config_func_t)(curr_entry->set_config_func);
+    } else {
+        return NULL;
+    }
+}
+
+static usbc_class_query_func_wk_capability_func_t usbc_get_class_query_func_wk_capability_func(usb_class_type_e type)
+{
+    usbc_node_reg_entry_t  *curr_entry;
+
+    curr_entry = _GET_NODE_REG_TABLE(type);
+
+    if (curr_entry && curr_entry->query_func_wk_capability)
+    {
+        return (usbc_class_query_func_wk_capability_func_t)(curr_entry->query_func_wk_capability);
+    }
+    else
+    {
+        return NULL;
+    }
+}
+
+static void _usbc_construct_config_descriptor(usbc_core_t *usbc_p)
+{
+    kal_uint32    idx_cfg, idx_if, idx_ep, idx_iad, idx_class;
+    kal_uint32    config_index;
+    usb_cfg_param_t *cfg_param;
+    kal_uint8     *conf;
+    usbc_configuration_descriptor_t  *config_desc_p;
+    usbc_class_query_func_wk_capability_func_t class_query;
+
+    // check for valid USB mode
+    if (usbc_p->mode >= USB_MODE_NUM)
+    {
+        ASSERT(0);
+        return;
+    }
+
+    // assign bMaxPower for USB 3.0 configurations
+    usbc_p->u3ConfMaxPower = (U3_CONF_BMAXPOWER / USBC_USB30_POWER_DESC_UINT);
+
+    // construct configuration descriptors
+    for (idx_cfg = 0; idx_cfg < usbc_p->dev_param->mode_param[usbc_p->mode].cfg_num; idx_cfg ++)
+    {
+        config_index = 0;
+        conf = usbc_p->descriptors.configuration[idx_cfg];
+
+        /* configuration descriptor */
+        kal_mem_cpy(conf + config_index,
+                       &usbc_default_configuration_descriptor,
+                       USBC_CONFIGURATION_DESC_SIZE);
+        config_index += USBC_CONFIGURATION_DESC_SIZE;
+
+        /* interface/iad/endpoint descriptors */
+        for (idx_if = 0; idx_if < usbc_p->resource_interface_number[idx_cfg]; idx_if ++)
+        {
+            /* IAD */
+            for (idx_iad = 0; idx_iad < usbc_p->resource_iad_number[idx_cfg]; idx_iad ++) {
+                if (idx_if == usbc_p->iad_descriptor[idx_cfg][idx_iad].bFirstInterface) {
+                    break;
+                }
+            }
+            if (idx_iad != usbc_p->resource_iad_number[idx_cfg])
+            {  /* This interface is the first interface of the IAD */
+                kal_mem_cpy(conf + config_index,
+                               &usbc_p->iad_descriptor[idx_cfg][idx_iad],
+                               sizeof(usbc_interface_association_descriptor_t));
+                config_index += sizeof(usbc_interface_association_descriptor_t);
+            }
+
+            /* Interface */
+            kal_mem_cpy(conf + config_index,
+                           &usbc_p->if_info[idx_cfg][idx_if].ifdscr.stdif,
+                           usbc_p->if_info[idx_cfg][idx_if].ifdscr_size);
+            config_index += usbc_p->if_info[idx_cfg][idx_if].ifdscr_size;
+
+            /* Endpoints */
+            for (idx_ep = 0; idx_ep < usbc_p->if_info[idx_cfg][idx_if].ifdscr.stdif.bNumEndpoints; idx_ep ++)
+            {
+                kal_mem_cpy(conf + config_index,
+                               &usbc_p->if_info[idx_cfg][idx_if].ep_info[idx_ep]->epdscr.stdep,
+                               usbc_p->if_info[idx_cfg][idx_if].ep_info[idx_ep]->epdscr_size);
+                config_index += usbc_p->if_info[idx_cfg][idx_if].ep_info[idx_ep]->epdscr_size;
+            }
+
+            /* alternate setting */
+            if (usbc_p->if_info[idx_cfg][idx_if].altn_surpport)
+            {
+                kal_mem_cpy(conf + config_index,
+                               &usbc_p->if_info[idx_cfg][idx_if].altn_if_info.ifdscr.stdif,
+                               usbc_p->if_info[idx_cfg][idx_if].altn_if_info.ifdscr_size);
+                config_index += usbc_p->if_info[idx_cfg][idx_if].altn_if_info.ifdscr_size;
+                for (idx_ep = 0; idx_ep < usbc_p->if_info[idx_cfg][idx_if].altn_if_info.ifdscr.stdif.bNumEndpoints; idx_ep ++)
+                {
+                    kal_mem_cpy(conf + config_index,
+                                   &usbc_p->if_info[idx_cfg][idx_if].altn_if_info.ep_info[idx_ep]->epdscr.stdep,
+                                   usbc_p->if_info[idx_cfg][idx_if].altn_if_info.ep_info[idx_ep]->epdscr_size);
+                    config_index += usbc_p->if_info[idx_cfg][idx_if].altn_if_info.ep_info[idx_ep]->epdscr_size;
+                }
+            }
+        }
+
+        ASSERT(config_index <= USBC_MAX_CONF_SIZE);
+
+        /* Fill in some members of configuration descriptor */
+        config_desc_p = (usbc_configuration_descriptor_t*)conf;
+        config_desc_p->wTotalLength = config_index;
+        config_desc_p->bNumInterfaces = usbc_p->resource_interface_number[idx_cfg];
+        config_desc_p->bConfigurationValue = INDEX_TO_CFG(idx_cfg); // configuration value must start with 1
+
+        // update remote wakeup attribute in configuration descriptor by qeuring each class in this config
+        cfg_param = &usbc_p->dev_param->mode_param[usbc_p->mode].cfg_param[idx_cfg];
+        for (idx_class = 0; idx_class < cfg_param->class_num; idx_class++)
+        {
+            class_query = usbc_get_class_query_func_wk_capability_func(cfg_param->class_type[idx_class]);
+            if ( class_query &&
+                 (class_query() & 0x0001) )
+            {
+                config_desc_p->bmAttributes |= 0x20;
+                break;
+            }
+        }
+    }
+
+}
+
+void usbc_set_ep_owner(kal_uint8 cfg, kal_uint8 class_device_id, kal_uint8 owner)
+{
+    kal_uint32 idx_ep;
+    usbc_core_t *usbc_inst;
+    
+    usbc_inst = usbc_core_get_instance();
+    for(idx_ep = 0; idx_ep <  (usbc_inst->resource_ep_tx_number[cfg]); idx_ep++){
+        if(usbc_inst->ep_tx_info[cfg][idx_ep].queue_info.class_device_id == class_device_id){
+            usbc_inst->ep_tx_info[cfg][idx_ep].queue_info.owner = owner;
+        }
+    }
+    for(idx_ep = 0; idx_ep <  (usbc_inst->resource_ep_rx_number[cfg]); idx_ep++){
+        if(usbc_inst->ep_rx_info[cfg][idx_ep].queue_info.class_device_id == class_device_id){
+            usbc_inst->ep_rx_info[cfg][idx_ep].queue_info.owner = owner;
+        }
+    }
+    return ;
+}
+
+kal_bool usbc_get_boot_factory_mode()
+{
+    kal_bool factory_mode = KAL_FALSE;
+
+    /*if project do not support factory mode, return FALSE*/
+    if(!usb_get_factory_mode_support())
+        return KAL_FALSE;
+    
+#ifdef __HIF_CCCI_SUPPORT__
+    /*get factory mode*/
+    CCCI_RUNTIME_BOOT_INFO_FORMAT_T boot_info;
+    CCCI_RUNTIME_FEATURE_SUPPORT_T feature_support;
+
+    feature_support = ccci_runtime_data_query(AP_CCCI_RUNTIME_BOOT_INFO, &boot_info, sizeof(CCCI_RUNTIME_BOOT_INFO_FORMAT_T));
+    if(feature_support.support_mask != CCCI_RUNTIME_FEATURE_MUST_SUPPORT)
+        EXT_ASSERT(0, USBCORE_LOC_CCCI_NO_SUPPORT_RUNTIME_FEATURE, (kal_uint32)feature_support.support_mask, (kal_uint32)boot_info.BootingStartID);
+    usbc_trace_warn(USBCORE_FACTORY_MODE_INFO, boot_info.BootingStartID);
+
+    if(CCCI_META_BOOT == (boot_info.BootingStartID & 0x000000FF))
+    {
+        factory_mode = KAL_TRUE;        
+        usbc_set_op_mode(USBC_OP_MODE_FACTORY);
+    }
+#endif
+
+    return factory_mode;
+}
+
+kal_bool usbc_core_get_mode_from_nvram()
+{
+    kal_uint8 *pBuffer = NULL;
+    kal_uint16 record, size;
+    kal_uint8 owner = 0;
+    kal_uint8 index = 0;
+    usbc_core_t  *usbc_inst = usbc_core_get_instance();
+    kal_uint8 mode_idx;
+    kal_bool ret = KAL_FALSE;
+
+    /* check for valid ID for NVRAM */
+    if( NVRAM_ERRNO_SUCCESS != nvram_get_info(NVRAM_EF_USB_MODE_LID, &record, &size) )
+    {
+        EXT_ASSERT(0, USBCORE_LOC_GET_MODE_LID_INFO_FOR_ENUM_FAIL, (kal_uint32)NVRAM_EF_USB_MODE_LID, 0);
+        return 0;
+    }
+    pBuffer = (kal_uint8*)get_ctrl_buffer(size * record);
+
+    if ( nvram_external_read_data(NVRAM_EF_USB_MODE_LID, 1, pBuffer, (kal_uint32)size) )
+    {
+        owner = *((kal_uint8*)pBuffer);
+        index = *((kal_uint8*)(pBuffer + sizeof(kal_uint8)));
+
+        for(mode_idx = 0; mode_idx < usb_mode_register_index; mode_idx++)
+        {
+            
+            if(usbc_inst->dev_param->mode_param[mode_idx].mode_owner == owner && usbc_inst->dev_param->mode_param[mode_idx].mode_index == index)
+            {
+                usbc_inst->mode = mode_idx;
+                break;
+            }
+        }
+        if(mode_idx >= usb_mode_register_index)
+        {
+            /*mode or index invalid*/
+            usbc_inst->mode = 0;
+        }
+        else
+            ret = KAL_TRUE;
+    }
+    else
+    {
+        EXT_ASSERT(0, USBCORE_LOC_GET_MODE_LID_VALUE_FAIL, (kal_uint32)NVRAM_EF_USB_MODE_LID, (kal_uint32)size);
+    }
+
+    free_ctrl_buffer(pBuffer);
+    usbc_trace_info(USBCORE_MODE_NVRAM_SELECT, owner, index, usbc_inst->mode, ret);
+    return ret;
+}
+
+usb_network_class_type_e usbc_get_network_type()
+{
+    usbc_core_t  *usbc_inst = usbc_core_get_instance();
+    usb_mode_e mode = usbc_inst->mode;
+    kal_int8 idx_cfg, idx_class;    
+    usb_cfg_param_t  *cfg_param;
+    kal_uint8 cfg_num = usbc_inst->dev_param->mode_param[mode].cfg_num;
+    usb_network_class_type_e net_type = USB_NETWORK_CLASS_RNDIS;
+    for (idx_cfg = 0; idx_cfg < cfg_num; idx_cfg++)
+    {
+        cfg_param = &usbc_inst->dev_param->mode_param[mode].cfg_param[idx_cfg];
+        for(idx_class = 0; idx_class < cfg_param->class_num; idx_class++)
+        {
+#ifdef __USB_RNDIS_SUPPORT__
+            if(cfg_param->class_type[idx_class] == USB_CLASS_RNDIS)
+                net_type = USB_NETWORK_CLASS_RNDIS;
+#endif
+#ifdef __USB_MBIM_SUPPORT__
+            if(cfg_param->class_type[idx_class] == USB_CLASS_MBIM)
+                net_type = USB_NETWORK_CLASS_MBIM;
+#endif
+#ifdef __USB_ECM_SUPPORT__
+            if(cfg_param->class_type[idx_class] == USB_CLASS_ECM)
+                net_type = USB_NETWORK_CLASS_ECM;
+#endif
+        }
+    }
+    
+    usbc_trace_warn(USBCORE_GET_NETWORK_TYPE, net_type);
+    return net_type;
+}
+
+
+void usbc_core_modify_custom_port()
+{
+    usbc_core_t  *usbc_inst = usbc_core_get_instance();
+    usbc_op_mode_e op_mode = usbc_get_op_mode();
+    usb_mode_e mode = usbc_inst->mode;
+    kal_int8 idx_cfg, idx_class;
+    usb_cfg_param_t  *cfg_param;
+    usb_cfg_param_t temp_param = {0};
+    kal_uint8 cfg_num = usbc_inst->dev_param->mode_param[mode].cfg_num;
+    
+    usbc_inst = usbc_core_get_instance();
+    
+    if(op_mode == USBC_OP_MODE_NORMAL)
+        return;
+    else if(op_mode == USBC_OP_MODE_UNUSED)
+    {
+        ASSERT(0);
+        return;
+    }
+    else if(op_mode == USBC_OP_MODE_METADEBUG)
+    {
+        usb_mode_replace_metadbg_mode(mode);
+        return ;
+    }
+
+    for (idx_cfg = 0; idx_cfg < cfg_num; idx_cfg++)
+    {
+        kal_mem_set(&temp_param, 0, sizeof(usb_cfg_param_t));
+        cfg_param = &usbc_inst->dev_param->mode_param[mode].cfg_param[idx_cfg];
+        for(idx_class = 0; idx_class < cfg_param->class_num; idx_class++)
+        {
+            if((op_mode == USBC_OP_MODE_MDONLY) && (cfg_param->class_owner[idx_class] == USB_CLASS_OWNER_AP))
+            {
+                continue;
+            }
+            else if((op_mode == USBC_OP_MODE_NOLOGGING) && (cfg_param->class_ctxt[idx_class] == (void*)uart_port_usb2))
+            {
+                continue;
+            }
+
+            temp_param.class_type[temp_param.class_num] = cfg_param->class_type[idx_class];
+            temp_param.class_ctxt[temp_param.class_num] = cfg_param->class_ctxt[idx_class];
+            temp_param.bulk_fifo_n[temp_param.class_num] = cfg_param->bulk_fifo_n[idx_class];
+            temp_param.class_owner[temp_param.class_num] = cfg_param->class_owner[idx_class];
+            temp_param.class_num++;
+        }
+        kal_mem_cpy(cfg_param, &temp_param, sizeof(usb_cfg_param_t));
+    }
+    return;
+}
+
+/*
+   usbcore:        usbc_stack_checkin(USB_CLASS_NUM, NULL);
+   usbclass:   ex. usbc_stack_checkin(USB_CLASS_ACM1, XXX);
+ */
+void usbc_stack_checkin(usb_class_type_e class_type, usbc_node_reg_entry_t *reg_table)
+{
+    usbc_class_init_func_t  class_init;
+    kal_uint32              idx_cfg, idx_class;
+    kal_uint32              cfg_num;
+    usb_cfg_param_t        *cfg_param;
+    usbc_device_descriptor_t *dev_desc;
+    usbc_device_qualifier_descriptor_t *dev_qual_desc;
+    usbc_configuration_descriptor_t  *config_desc_p;
+    usbc_core_t            *usbc_inst;
+
+    _CHECKIN_NODE(class_type, reg_table);
+
+    if (_ALL_NODES_CHECKIN())
+    {
+        usbc_trace_info(USBCORE_ALL_NODE_CHECKIN);
+
+        usbc_inst = usbc_core_get_instance();
+
+        /* 1. hif init */
+        #ifdef __MTK_MD_DIRECT_USB_SUPPORT__
+        usbc_direct_hif_factory();
+        usbc_direct_hif_init();
+        #else
+        usbc_normal_hif_init();
+        #endif
+        ubm_init();     // UBM init
+
+        // Check for META mode
+        usbc_inst->is_mode_meta = usbc_inst->is_mode_meta_reused = KAL_FALSE;
+
+        /* 2. Reset usbcore resources/structures */
+        usbc_resource_reset();
+        usbc_core_clear_register();
+        usbc_core_clear_status();
+
+        /*
+           3. Select a mode for MD USB enumeration.
+        */
+        usbc_inst->dev_param = (usb_dev_param_t*)usb_get_custom_func()->get_device_param_func();
+
+        /*Get whether current boot is factory mode*/
+        if(usbc_get_boot_factory_mode())
+        {
+            usb_mode_factory_register();
+            usbc_inst->mode = 0;
+        }
+
+        if(usbc_get_op_mode() != USBC_OP_MODE_FACTORY)
+        {
+#ifdef __USB_PORT_CUSTOMIZATION__
+            /*Register customized mode and set a mode which is read from NVRAM*/
+            usb_mode_customization_register();
+            usbc_core_get_mode_from_nvram();
+#else
+            /*Register all normal mode*/
+            usb_mode_base_register();
+            usb_mode_ufpm_register();
+            usb_mode_inusj_register();
+            usb_mode_qeznk_register();
+
+            #if defined (BTT_STANDALONE_MODE)
+                usbc_inst->mode = USB_MODE_BTT_STANDALONE;
+            #elif defined(__MODIS_USB_TAP_ACCESS__)
+                usbc_inst->mode = USB_MODE_1R3C;
+            #elif defined(__MTK_MD_DIRECT_USB_SUPPORT__)
+                usbc_inst->mode = USB_MODE_UFPM;
+            #elif defined(__DUMMY_L1_ON_TARGET_4G5G__)
+                usbc_inst->mode = USBMODE_KS_IODT_1R3C_ENUM;
+            #else
+                usbc_inst->mode = USB_MODE_DEFAULT;
+            #endif
+            
+            usbc_trace_info(USBCORE_MODE_DEFAULT_CFG_SELECT, usbc_inst->mode);
+#endif
+            /*Change port for DUALIPC*/
+            usbc_core_modify_custom_port();
+            usbc_core_check_mass_strorage_onoff();
+        }   
+        cfg_num = usbc_inst->dev_param->mode_param[usbc_inst->mode].cfg_num;
+        usbc_core_check_low_power_enable();
+
+        /* 4. Set device_descriptor */
+        dev_desc = (usbc_device_descriptor_t *)usbc_inst->descriptors.device;
+        kal_mem_cpy(dev_desc, &usbc_default_device_descriptor, USBC_DEVICE_DESC_SIZE);
+        dev_desc->bDeviceClass = usbc_inst->dev_param->mode_param[usbc_inst->mode].device_class;
+        dev_desc->bDeviceSubClass = usbc_inst->dev_param->mode_param[usbc_inst->mode].device_sub_class;
+        dev_desc->bDeviceProtocol = usbc_inst->dev_param->mode_param[usbc_inst->mode].device_protocol;
+        dev_desc->idVendor = usbc_inst->dev_param->mode_param[usbc_inst->mode].vendor_id;
+        dev_desc->idProduct = usbc_inst->dev_param->mode_param[usbc_inst->mode].product_id;
+        dev_desc->bcdDevice = usbc_inst->dev_param->bcd_device;
+        dev_desc->bNumConfigurations = usbc_inst->dev_param->mode_param[usbc_inst->mode].cfg_num;
+
+        dev_qual_desc = &usbc_inst->device_qualifier_descriptor;
+        dev_qual_desc->bLength = 0x0A;
+        dev_qual_desc->bDescriptorType = USBC_DT_DEVICE_QUALIFIER;
+        dev_qual_desc->bcdUSB = dev_desc->bcdUSB;
+        dev_qual_desc->bDeviceClass = dev_desc->bDeviceClass;
+        dev_qual_desc->bDeviceSubClass = dev_desc->bDeviceSubClass;
+        dev_qual_desc->bDeviceProtocol = dev_desc->bDeviceProtocol;
+        dev_qual_desc->bMaxPacketSize0 = dev_desc->bMaxPacketSize0;
+        dev_qual_desc->bNumConfigurations = dev_desc->bNumConfigurations;
+
+        /* 5. Store device string - language/manufacturere/product/serialnum */
+        usbc_get_string_number((void*)usb_language_string);
+        dev_desc->iManufacturer = usbc_get_string_number((void*)usbc_inst->dev_param->manufacture_string);
+        dev_desc->iProduct = usbc_get_string_number((void*)usbc_inst->dev_param->product_string);
+        // Update serial number by reading the IMEI from NVRAM
+#ifdef __PRODUCTION_RELEASE__
+        dev_desc->iSerialNumber = usbc_core_set_serial_number()? usbc_get_string_number((void*)usbc_inst->dev_param->serial_number):0x00;
+#else
+/* under construction !*/
+#endif
+
+        /* 6. Call init function of each usb class for all configurations */
+        for (idx_cfg = 0; idx_cfg < cfg_num; idx_cfg++)
+        {
+            cfg_param = &usbc_inst->dev_param->mode_param[usbc_inst->mode].cfg_param[idx_cfg];
+            for (idx_class = 0; idx_class < cfg_param->class_num; idx_class++)
+            {
+                class_init = _get_class_init_func(cfg_param->class_type[idx_class]);
+                if (class_init) {
+                    usbc_trace_info(USBCORE_ALL_NODE_CHECKIN_INIT_CLASS_START, cfg_param->class_type[idx_class]);
+                    class_init( idx_class,
+                                usbc_inst->mode,
+                                idx_cfg,
+                                cfg_param->class_ctxt[idx_class],
+                                cfg_param->bulk_fifo_n[idx_class]);
+                    usbc_trace_info(USBCORE_ALL_NODE_CHECKIN_INIT_CLASS_END, cfg_param->class_type[idx_class]);
+                    /* Set EP owner*/
+                    usbc_set_ep_owner(idx_cfg, idx_class, cfg_param->class_owner[idx_class]);
+                } else {
+                    EXT_ASSERT(KAL_FALSE, 1, 0, 0);
+                }
+            }
+        }
+
+
+        if( !usbc_inst->is_mode_meta_reused )
+        {
+            /* 7. Construct configuration descriptor */
+            _usbc_construct_config_descriptor(usbc_inst);
+
+            #ifndef __MTK_MD_DIRECT_USB_SUPPORT__
+            /* 8. Set hif configuration, and connect to hif later in task main */
+            usbc_normal_hif_disconnect();
+            usbc_core_set_hif_configuration();
+            #else
+            /* Init UFPM global variables */
+            ufpm_init();
+            #endif
+        }
+        else
+        {
+            /* 7. Construct configuration descriptor */
+            usbc_inst->resource_iad_number[0] = 0;          // Discard IAD if it is in META mode
+            _usbc_construct_config_descriptor(usbc_inst);   // construct configuration descriptor
+
+            /* 8. Update descriptors for META */
+            dev_desc->iSerialNumber = 0x00;     // no serial number in BootROM/pre-loader's COM
+            config_desc_p = (usbc_configuration_descriptor_t*)usbc_inst->descriptors.configuration[0];   // only one configuration in META mode
+            config_desc_p->bmAttributes &= 0xdf;   // the remote wakeup is not capable in BootROM/Pre-loader COM
+            config_desc_p->bMaxPower = 0xc8;       // the max power of BootROM/Preloader COM's confiuration is 400mA
+            usbc_inst->u3ConfMaxPower = (U3_CONF_BMAXPOWER_META / USBC_USB30_POWER_DESC_UINT); // the max power is 400mA in USB 3.0
+
+            /* 9. Enqueue and prepare for fake enumeration */
+            usbc_meta_hif_factory();            // set function pointers of USB driver to META state
+            usbc_core_set_hif_configuration();
+            usbc_normal_hif_meta_attach();
+        }
+    }
+}
+
+void usbc_reinit_class(void)
+{
+    kal_uint32   idx;
+    usbc_class_reinit_func_t  class_reinit;
+
+    for (idx = 0; idx < USB_CLASS_NUM; idx++) {
+        class_reinit = _get_class_reinit_func(idx);
+        if (class_reinit) {
+            usbc_trace_info(USBCORE_ALL_NODE_CHECKIN_REINIT_CLASS_START, idx);
+            class_reinit(KAL_FALSE);
+            usbc_trace_info(USBCORE_ALL_NODE_CHECKIN_REINIT_CLASS_END, idx);
+        } else {
+            //EXT_ASSERT(KAL_FALSE, 2, 0, 0);
+            continue;
+        }
+    }
+}
+
+void usbc_mode_switch(usb_mode_e mode){
+	kal_uint32   idx;
+	usbc_core_t* usbc_inst = usbc_core_get_instance();
+	usbc_class_reinit_func_t  class_reinit;
+	usbc_ind_t      ind_to_enqueue;    // Do mode switch immediately if it is not in HISR, or enqueue a mode switch event for USBCORE task
+	if (!kal_if_hisr()) {
+#if 1
+		if (mode == USB_MODE_MSD_OSDRTY){
+		/* wait 3 second for OSD known issue */
+			kal_sleep_task(600);
+		}
+#endif
+		/* 1. set disconnect */
+		hifusb_set_disconnect();
+        usbc_empty_ind_queue();
+
+		/* 2. Set switch mode */
+		usbc_inst->is_mode_switch = KAL_TRUE;
+		usbc_inst->mode = mode;
+
+		/* 3. Send re-init callback to all usb class */
+		_SET_NODE_VALUE(0);
+		usbc_stack_checkin(USB_CLASS_NUM, NULL);
+		for (idx = 0; idx < USB_CLASS_NUM; idx++) {
+			class_reinit = _get_class_reinit_func(idx);
+			_SET_NODE_REG_TABLE(idx, NULL);
+			if (class_reinit) {
+				usbc_trace_info(USBCORE_ALL_NODE_CHECKIN_REINIT_CLASS_START, idx);
+				class_reinit(KAL_TRUE);
+				usbc_trace_info(USBCORE_ALL_NODE_CHECKIN_REINIT_CLASS_END, idx);
+			} else {
+					EXT_ASSERT(KAL_FALSE, 2, 0, 0);
+			}
+		}
+	} else {
+		ind_to_enqueue.type = USBC_IND_MODE_SWITCH;
+		ind_to_enqueue.ext = 0;
+		ind_to_enqueue.data = (kal_uint8)mode;
+		usbc_enqueue_ind(&ind_to_enqueue);
+		hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+	}
+}
+
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_stdreq.c b/mcu/middleware/hif/usbcore/src/usbcore_stdreq.c
new file mode 100644
index 0000000..b7046ae
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_stdreq.c
@@ -0,0 +1,1305 @@
+/*!
+ *  @file usbcore_usbstd.c
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides usb standard request handler function
+ */
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "usbcore_usbstd.h"
+#include "usbcore_main.h"
+#include "usbcore_hif.h"
+#include "hmu.h"
+#include "hmu_conf_data.h"
+#include "usbcore_ind_q.h"
+#include "usbcore_debug.h"
+#ifdef __USB_OSD_SUPPORT__
+#include "usbosd.h"
+#endif /* __USB_OSD_SUPPORT__ */
+
+#ifdef ATEST_SYS_USBCORE
+#include "usbcore_ut.h"
+#endif
+
+#define _USB30_DEVICE_REMOTE_WK_SUPPORT_ 1
+
+static kal_uint8 usbc_bos_s[USBC_MAX_BOS_SIZE] = {
+    /*BOS standard descriptor*/
+    0x05,                        /*bLength*/
+    0x0F,                        /*bDescriptorType*/
+    0x16, 0x00, //0x0016,        /*wTotalLength*/
+    0x02,                        /*bNumDeviceCaps*/
+
+    /*USB2.0 Extension Device Capability Descriptor*/
+    0x07,                        /*bLength*/
+    0x10,                        /*bDescriptorType*/
+    0x02,                        /*bDevCapabilityType*/
+    /*Link Power Management : YES*/
+    0x02, 0x00, 0x00, 0x00, //0x00000002 /*bmAttributes*/
+
+    /*SuperSpeed Device Capability Descriptor*/
+    0x0A,                        /*bLength*/
+    0x10,                        /*bDescritorType*/
+    0x03,                        /*bDevCapabilityType*/
+    0x00,                        /*bmAttributes*/
+    /*bit-map : support FS/HS/5Gbs*/
+    0x0E, 0x00, //0x000E,        /*wSpeedsSupport*/ /* 3: 5Gbps, 2: high 1: full, 0: low */
+    0x01,                        /*bFunctionalitySupport*/ /* lowest speed supported */
+    0x0A,                        /*bU1DevExitLat*/ /* Less than 0x0a us */
+    0x20, 0x00 //0x0020,         /*bU2DevExitLat*/ /* Less than 0x20 us */
+};
+
+/*
+ *  Define Microsoft OS string descriptor
+ */
+#define USBC_MS_OS_STRING_INDEX             0xEE
+#define USBC_MAX_OS_STRING_LENGTH           18
+static const kal_uint16 usbc_os_string[] = {'M', 'S', 'F', 'T', '1', '0', '0'};
+static usbc_os_string_descriptor_t usbc_os_string_desc;
+static kal_uint8 pOtherSpeedDescript[256];
+
+static kal_bool usbc_core_handle_set_address()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint16 wValue = pUsbCore->setup_packet.wValue;
+
+    usbc_core_printf("=========>usbcore_handle_set_address\r\n");
+    usbc_trace_info(USBCORE_SET_ADDRESS, (wValue & 0x7f));
+
+    usbc_core_set_usb_address(wValue & 0x7f);
+    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+    return KAL_TRUE;
+}
+
+
+static kal_bool usbc_core_handle_get_status()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    usbc_control_request_type_e type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    kal_uint8 bRecip = pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK;
+    //kal_uint16 wIndex = pUsbCore->setup_packet.wIndex;
+    kal_uint8* pBuffer = pUsbCore->control_request_buffer;
+    kal_uint32 length = 0;
+
+    usbc_core_printf("=========>usbcore_handle_get_status\r\n");
+    usbc_trace_info(USBCORE_GET_STATUS, bRecip);
+
+    if ( bRecip == USBC_REQUEST_RECIP_DEVICE )
+    {
+        kal_uint8 i;
+
+        /* D0: Self Powered, D1: Remote Wakeup */
+        pBuffer[0] = 0;     //Bus Power
+        pBuffer[1] = 0;     //No Remote Wakeup
+        length = 2;
+        type = USBC_CONTROL_REQUEST_TYPE_SEND;
+
+        // report remote wakeup status in USB 1.1 and USB 2.0 (0 in USB 3.0)
+        if( pUsbCore->speed != USBC_USB_SPEED_USB30 )
+        {
+            for( i=0; i<pUsbCore->total_class_devices; i++)
+            {
+                if ( NULL != pUsbCore->class_device[i].query_func_wk_status &&
+                     pUsbCore->class_device[i].query_func_wk_status(i) & 0x0002 )
+                {
+                    pBuffer[0] |= ((kal_uint8)0x01 << 1);
+                    break;
+                }
+            }
+        }
+		else
+		{
+            // USB 3.0 U1 enable status (0 in USB 2.0)
+            if ( pUsbCore->is_device_u1_enable )
+            {
+                pBuffer[0] |= ((kal_uint8)0x01 << 2);
+            }
+
+            // USB 3.0 U2 enable status ( 0 in USB 3.0)
+            if( pUsbCore->is_device_u2_enable )
+            {
+                pBuffer[0] |= ((kal_uint8)0x01 << 3);
+            }
+
+            // USB 3.0 LTM enable status ( 0 in USB 3.0)
+            if( pUsbCore->is_device_ltm_enable )
+            {
+                pBuffer[0] |= ((kal_uint8)0x01 << 4);
+            }
+		}
+
+    } else
+    if ( bRecip == USBC_REQUEST_RECIP_INTERFACE )
+    {
+        kal_uint8 nInterface = (kal_uint8)pUsbCore->setup_packet.wIndex;
+        kal_uint8 class_device_id = pUsbCore->class_interface[nInterface].class_device_id;
+
+        /* return two bytes of 0x00, 0x00.
+           Both bytes are reserved for future use
+         */
+        pBuffer[0] = 0;
+        pBuffer[1] = 0;
+        length = 2;
+        type = USBC_CONTROL_REQUEST_TYPE_SEND;
+
+        if ( pUsbCore->speed == USBC_USB_SPEED_USB30 &&
+             usbc_core_is_1st_interface(nInterface)  &&
+             NULL !=  pUsbCore->class_device[class_device_id].query_func_wk_status )
+        {
+            /* if the requested interface is the first one of a function,
+               report the function remote wakeup capability and state
+             */
+            pBuffer[0] = pUsbCore->class_device[class_device_id].query_func_wk_status(class_device_id) & ((kal_uint8)0xFF);
+        }
+
+    } else
+    if ( bRecip == USBC_REQUEST_RECIP_ENDPOINT )
+    {
+        /* D0: HALT, D1: Reserve */
+        kal_uint8 nEnd = pUsbCore->setup_packet.wIndex & USBC_EP_ADDR_NUM_MASK; /* TODO: It's error-prone to use en_no instead of endpoint address. */
+        usbc_core_queue_t* pQueue = NULL;
+        kal_uint8 i = 0;
+
+        if ( (pUsbCore->setup_packet.wIndex & USBC_EP_ADDR_DIR_IN) )
+        {
+            for ( i=0; i<MAX_USBCORE_QUEUE_NUM; i++ )
+            {
+                if ( (pUsbCore->tx_queue[i].ep_no == nEnd) &&
+                     (pUsbCore->tx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED) )
+                {
+                    pQueue = &pUsbCore->tx_queue[i];
+                    break;
+                }
+            }
+        } else {
+            for ( i=0; i<MAX_USBCORE_QUEUE_NUM; i++ )
+            {
+                if ( (pUsbCore->rx_queue[i].ep_no == nEnd) &&
+                     (pUsbCore->rx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED) )
+                {
+                    pQueue = &pUsbCore->rx_queue[i];
+                    break;
+                }
+            }
+        }
+
+        /* D0: HALT, D1: Reserve */
+        if ( pQueue == NULL )
+        {
+            length = 0;
+            type = USBC_CONTROL_REQUEST_TYPE_STALL;
+
+            if( nEnd == 0)
+            {
+                pBuffer[0] = 0;
+                pBuffer[1] = 0;
+                length = 2;
+                type = USBC_CONTROL_REQUEST_TYPE_SEND;
+            }
+
+        } else {
+            switch (pQueue->state)
+            {
+                case USBC_CORE_QUEUE_STATE_ACTIVE:
+                {
+                    pBuffer[0] = 0;
+                    pBuffer[1] = 0;
+                    length = 2;
+                    type = USBC_CONTROL_REQUEST_TYPE_SEND;
+                    break;
+                }
+                case USBC_CORE_QUEUE_STATE_STALL:
+                {
+                    pBuffer[0] = 1;
+                    pBuffer[1] = 0;
+                    length = 2;
+                    type = USBC_CONTROL_REQUEST_TYPE_SEND;
+                    break;
+                }
+                default:
+                {
+                    EXT_ASSERT(0, USBCORE_LOC_GET_STATUS_EP_STATUS_INVALID, (kal_uint32)pQueue->state, (kal_uint32)nEnd);
+                    length = 0;
+                    type = USBC_CONTROL_REQUEST_TYPE_STALL;
+                    break;
+                }
+            }
+        }
+    } else {
+        EXT_ASSERT(0, USBCORE_LOC_GET_STATUS_INVALID_RECIP, (kal_uint32)bRecip, 0);
+        type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    }
+
+    usbc_core_set_control_request(pBuffer, length, type);
+    return KAL_TRUE;
+}
+
+
+static kal_bool usbc_core_handle_set_feature()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    usbc_control_request_type_e type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    kal_uint8 bRecip = pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK;
+    kal_uint16 wIndex = pUsbCore->setup_packet.wIndex;
+    kal_uint16 wValue = pUsbCore->setup_packet.wValue;
+    kal_bool is_tx = KAL_TRUE;
+
+    usbc_core_printf("=========>usbcore_handle_set_feature\r\n");
+    usbc_trace_info(USBCORE_SET_FEATURE, bRecip, wIndex, wValue);
+
+    if ( bRecip == USBC_REQUEST_RECIP_DEVICE )
+    {
+        usbc_ind_t          ind_to_enqueue;
+        usbc_func_state_e   state;
+
+        if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+        {
+            if ( pUsbCore->state <= USBC_USB_STATE_ATTACHING )
+            {
+                type = USBC_CONTROL_REQUEST_TYPE_STALL;
+            } else
+            if ( wValue == USBC_FEATURE_U1_ENABLE )
+            {
+                pUsbCore->is_device_u1_enable = KAL_TRUE;
+                usbc_core_set_ss_dev_init_u1_en(KAL_TRUE);
+                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
+            } else
+            if ( wValue == USBC_FEATURE_U2_ENABLE )
+            {
+                pUsbCore->is_device_u2_enable = KAL_TRUE;
+                usbc_core_set_ss_dev_init_u2_en(KAL_TRUE);
+                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
+            } else
+            if ( wValue == USBC_FEATURE_LTM_ENABLE )
+            {
+                pUsbCore->is_device_ltm_enable = KAL_TRUE;
+                // TODO: set LTM enabled if support
+                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
+            }
+#if _USB30_DEVICE_REMOTE_WK_SUPPORT_
+            else if ( wValue == USBC_FEATURE_DEVICE_REMOTE_WAKEUP )
+            {
+                // enable function remote wakeup for capable functions in enabling device remote wakeup
+                state = USBC_FUNC_WK_ENABLE;
+                ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
+                ind_to_enqueue.ext = 0;
+                ind_to_enqueue.data = (kal_uint8)state;
+                usbc_enqueue_ind(&ind_to_enqueue);
+                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);                
+                if(USBC_IS_IN_EXCEPTION_MODE())
+                {
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    return KAL_TRUE;
+                }
+                
+                pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+                return KAL_FALSE;
+            }
+#endif
+            else
+            {
+                 type = USBC_CONTROL_REQUEST_TYPE_STALL;
+            }
+        }
+        else
+        {
+            if ( wValue == USBC_FEATURE_DEVICE_REMOTE_WAKEUP )
+            {
+                // enable function remote wakeup for capable functions in enabling device remote wakeup
+                state = USBC_FUNC_WK_ENABLE;
+                ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
+                ind_to_enqueue.ext = 0;
+                ind_to_enqueue.data = (kal_uint8)state;
+                usbc_enqueue_ind(&ind_to_enqueue);
+                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);                
+                if(USBC_IS_IN_EXCEPTION_MODE())
+                {
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    return KAL_TRUE;
+                }
+                pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+                return KAL_FALSE;
+            } else
+            if ( wValue == USBC_FEATURE_TEST_MODE )
+            {
+                usbc_core_set_usb_testmode((hifusb_test_mode_e)(wIndex >> 8));
+                type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
+            }
+            else
+            {
+                 type = USBC_CONTROL_REQUEST_TYPE_STALL;
+            }
+        }
+
+    } else
+    if ( bRecip == USBC_REQUEST_RECIP_INTERFACE )
+    {
+        kal_uint8 nInterface = (kal_uint8)wIndex & 0xFF;
+        kal_uint8 suspendOpt = wIndex >> 8;
+        usbc_ind_t          ind_to_enqueue;
+        kal_uint8 class_device_id = pUsbCore->class_interface[nInterface].class_device_id;
+        usbc_func_state_e    state;
+
+        //specifies no interface features
+        type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
+
+        if( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+        {
+            if ( pUsbCore->state > USBC_USB_STATE_ATTACHING &&
+                 wValue == USBC_FEATURE_FUNCTION_SUSPEND &&
+                 usbc_core_is_1st_interface(nInterface) )
+            {
+                if ( suspendOpt & 0x02 )
+                {
+                    state = (suspendOpt & 0x01)? USBC_FUNC_WK_ENABLE_STATE_SUSPENDING:USBC_FUNC_WK_ENABLE_STATE_RESUME;
+                }
+                else
+                {
+                    state = (suspendOpt & 0x01)? USBC_FUNC_WK_DISABLE_STATE_SUSPENDING:USBC_FUNC_WK_DISABLE_STATE_RESUME;
+                }
+                ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
+                ind_to_enqueue.ext = class_device_id;
+                ind_to_enqueue.data = (kal_uint8)state;
+                usbc_enqueue_ind(&ind_to_enqueue);
+
+                // Wake up USBCORE task to process indications.
+                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+
+                if(USBC_IS_IN_EXCEPTION_MODE())
+                {
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);                    
+                    return KAL_TRUE;
+                }
+            }
+            else
+            {
+                ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
+                ind_to_enqueue.ext = class_device_id;
+                ind_to_enqueue.data = (kal_uint8)USBC_FUNC_SET_FEATURE_ERROR;
+                usbc_enqueue_ind(&ind_to_enqueue);
+
+                // Wake up USBCORE task to process indications.
+                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+
+                if(USBC_IS_IN_EXCEPTION_MODE())
+                {
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_STALL);                    
+                    return KAL_TRUE;
+                }
+            }
+            // Return USB 3.0 SetFeature of interfaces here, because the state is reported after finishing indications.
+            pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+            return KAL_FALSE;
+        }
+
+    } else
+    if ( bRecip == USBC_REQUEST_RECIP_ENDPOINT )
+    {
+        kal_uint8 nEnd = pUsbCore->setup_packet.wIndex & USBC_EP_ADDR_NUM_MASK; /* TODO: It's error-prone to use en_no instead of endpoint address. */
+        usbc_core_queue_t* pQueue = NULL;
+        kal_uint8 i = 0;
+
+        if ( (pUsbCore->setup_packet.wIndex & USBC_EP_ADDR_DIR_IN) )
+        {
+            is_tx = KAL_TRUE;
+            for ( i=0; i<MAX_USBCORE_QUEUE_NUM; i++ )
+            {
+                if ( (pUsbCore->tx_queue[i].ep_no == nEnd) &&
+                     (pUsbCore->tx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED) )
+                {
+                    pQueue = &pUsbCore->tx_queue[i];
+                    break;
+                }
+            }
+        } else {
+            is_tx = KAL_FALSE;
+            for ( i=0; i<MAX_USBCORE_QUEUE_NUM; i++ )
+            {
+                if ( (pUsbCore->rx_queue[i].ep_no == nEnd) &&
+                     (pUsbCore->rx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED) )
+                {
+                    pQueue = &pUsbCore->rx_queue[i];
+                    break;
+                }
+            }
+        }
+
+        if ( pQueue == NULL )
+        {
+            type = USBC_CONTROL_REQUEST_TYPE_STALL;
+        } else {
+            /* notify class driver that this queue is set stall, class has to set EP stall to driver */
+            usbc_core_indicate_stall(is_tx, i, KAL_TRUE);
+            if(USBC_IS_IN_EXCEPTION_MODE())
+            {
+                pQueue->state = USBC_CORE_QUEUE_STATE_STALL;
+                usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);                    
+                return KAL_TRUE;
+            }
+            pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+            return KAL_FALSE;
+        }
+    } else {
+        type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    }
+
+    usbc_core_set_control_request(NULL, 0, type);    
+    return KAL_TRUE;
+}
+
+
+static kal_bool usbc_core_handle_clear_feature()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    usbc_control_request_type_e type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    kal_uint8 bRecip = pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK;
+    kal_uint16 wIndex = pUsbCore->setup_packet.wIndex;
+    kal_uint16 wValue = pUsbCore->setup_packet.wValue;
+    kal_bool is_tx = KAL_TRUE;
+
+    usbc_core_printf("=========>usbcore_handle_clear_feature\r\n");
+    usbc_trace_info(USBCORE_CLEAR_FEATURE, bRecip, wIndex, wValue);
+
+    if ( bRecip == USBC_REQUEST_RECIP_DEVICE )
+    {
+        if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+        {
+            type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
+
+            if ( wValue == USBC_FEATURE_U1_ENABLE )
+            {
+                pUsbCore->is_device_u1_enable = KAL_FALSE;
+                usbc_core_set_ss_dev_init_u1_en(KAL_FALSE);
+            } else
+            if ( wValue == USBC_FEATURE_U2_ENABLE )
+            {
+                pUsbCore->is_device_u2_enable = KAL_FALSE;
+                usbc_core_set_ss_dev_init_u2_en(KAL_FALSE);
+            } else
+            if ( wValue == USBC_FEATURE_LTM_ENABLE )
+            {
+                pUsbCore->is_device_ltm_enable = KAL_FALSE;
+                //TODO: clear LTM capability if support
+            }
+#if _USB30_DEVICE_REMOTE_WK_SUPPORT_
+            else if ( wValue == USBC_FEATURE_DEVICE_REMOTE_WAKEUP )
+            {
+                usbc_func_state_e   state;
+                usbc_ind_t          ind_to_enqueue;
+
+                // disable function remote wakeup for capable functions while disabling device remote wakeup
+                state = USBC_FUNC_WK_DISABLE;
+                ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
+                ind_to_enqueue.ext = 0;
+                ind_to_enqueue.data = (kal_uint8)state;
+                usbc_enqueue_ind(&ind_to_enqueue);
+                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+                if(USBC_IS_IN_EXCEPTION_MODE())
+                {
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    return KAL_TRUE;
+                }
+                pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+                return KAL_FALSE;
+            }
+#endif
+            else {
+                type = USBC_CONTROL_REQUEST_TYPE_STALL;
+            }
+        }
+        else
+        {
+            if ( wValue == USBC_FEATURE_DEVICE_REMOTE_WAKEUP )
+            {
+                usbc_func_state_e   state;
+                usbc_ind_t          ind_to_enqueue;
+
+                // disable function remote wakeup for capable functions while disabling device remote wakeup
+                state = USBC_FUNC_WK_DISABLE;
+                ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
+                ind_to_enqueue.ext = 0;
+                ind_to_enqueue.data = (kal_uint8)state;
+                usbc_enqueue_ind(&ind_to_enqueue);
+                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+                if(USBC_IS_IN_EXCEPTION_MODE())
+                {
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    return KAL_TRUE;
+                }
+                pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+                return KAL_FALSE;
+            }
+            else {
+                type = USBC_CONTROL_REQUEST_TYPE_STALL;
+            }
+        }
+
+    } else
+    if ( bRecip == USBC_REQUEST_RECIP_INTERFACE )
+    {
+        kal_uint8 nInterface = (kal_uint8)pUsbCore->setup_packet.wIndex;
+        usbc_ind_t          ind_to_enqueue;
+        kal_uint8 class_device_id = pUsbCore->class_interface[nInterface].class_device_id;
+        usbc_func_state_e    state;
+
+        //specifies no interface features
+        type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
+
+        if( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+        {
+            if ( wValue == USBC_FEATURE_FUNCTION_SUSPEND && usbc_core_is_1st_interface(nInterface) )
+            {
+                state = USBC_FUNC_WK_DISABLE_STATE_RESUME;
+                ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
+                ind_to_enqueue.ext = class_device_id;
+                ind_to_enqueue.data = (kal_uint8)state;
+                usbc_enqueue_ind(&ind_to_enqueue);
+
+                // Wake up USBCORE task to process indications.
+                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+
+                if(USBC_IS_IN_EXCEPTION_MODE())
+                {
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                    return KAL_TRUE;
+                }
+            }
+            else
+            {
+                ind_to_enqueue.type = USBC_IND_FUNC_EVENT;
+                ind_to_enqueue.ext = class_device_id;
+                ind_to_enqueue.data = (kal_uint8)USBC_FUNC_SET_FEATURE_ERROR;
+                usbc_enqueue_ind(&ind_to_enqueue);
+
+                // Wake up USBCORE task to process indications.
+                hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+
+                if(USBC_IS_IN_EXCEPTION_MODE())
+                {
+                    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_STALL);                    
+                    return KAL_TRUE;
+                }
+            }
+            // Return USB 3.0 SetFeature of interfaces here, because the state is reported after finishing indications.
+            pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+            return KAL_FALSE;
+        }
+
+    } else
+    if ( bRecip == USBC_REQUEST_RECIP_ENDPOINT )
+    {
+        kal_uint8 nEnd = pUsbCore->setup_packet.wIndex & USBC_EP_ADDR_NUM_MASK; /* TODO: It's error-prone to use en_no instead of endpoint address. */
+        usbc_core_queue_t* pQueue = NULL;
+        kal_uint8 i = 0;
+
+        if ( (pUsbCore->setup_packet.wIndex & USBC_EP_ADDR_DIR_IN) )
+        {
+            is_tx = KAL_TRUE;
+            for ( i=0; i<MAX_USBCORE_QUEUE_NUM; i++ )
+            {
+                if ( (pUsbCore->tx_queue[i].ep_no == nEnd) &&
+                     (pUsbCore->tx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED) )
+                {
+                    pQueue = &pUsbCore->tx_queue[i];
+                    break;
+                }
+            }
+        } else {
+            is_tx = KAL_FALSE;
+            for ( i=0; i<MAX_USBCORE_QUEUE_NUM; i++ )
+            {
+                if ( (pUsbCore->rx_queue[i].ep_no == nEnd) &&
+                     (pUsbCore->rx_queue[i].state > USBC_CORE_QUEUE_STATE_INITIATED) )
+                {
+                    pQueue = &pUsbCore->rx_queue[i];
+                    break;
+                }
+            }
+        }
+
+        if ( pQueue == NULL )
+        {
+            type = USBC_CONTROL_REQUEST_TYPE_STALL;
+        } else {
+            /* notify class driver that this queue is clear stall, class has to clr stall to driver */
+            usbc_core_indicate_stall(is_tx, i, KAL_FALSE);                
+            if(USBC_IS_IN_EXCEPTION_MODE())
+            {
+                pQueue->state = USBC_CORE_QUEUE_STATE_ACTIVE;
+                usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+                return KAL_TRUE;
+            }
+            pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+            return KAL_FALSE;
+        }
+    } else {
+        type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    }
+
+    usbc_core_set_control_request(NULL, 0, type);
+    return KAL_TRUE;
+}
+
+static kal_bool usbc_core_update_dt_other_speed(kal_uint8 *pDescript, kal_uint8 idx_config)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8* pConfig = (kal_uint8*)pUsbCore->descriptors.configuration[idx_config];
+    kal_uint16 totalLength = pConfig[2] + (pConfig[3] << 8);
+    kal_uint8 *ptr = NULL;
+    kal_uint16 i = 0;
+    kal_uint8 currLength, type;
+
+    // copy the configuration descriptor as the default other speeed descriptor
+    kal_mem_cpy(pDescript, pConfig, totalLength);
+
+    // set the descriptor type as other speed configuration;
+    pDescript[1] = USBC_DT_OTHER_SPEED;
+
+    // update the maximum packet size of each bulk endpoint descriptor
+    ptr = pDescript;
+    while(i < totalLength)
+    {
+        currLength = ptr[0];
+        type = ptr[1];
+
+        if( USBC_DT_ENDPOINT == type &&
+            USBC_BULK_TRANSFER == (ptr[3] & 0x03))
+        {
+            if (USBC_USB_SPEED_USB20 == pUsbCore->speed)
+            {
+                ptr[4] = USBC_USB11_MAX_PACKET_SIZE & 0x00FF;
+                ptr[5] = (USBC_USB11_MAX_PACKET_SIZE >> 8) & 0x07;
+            }
+            else if(USBC_USB_SPEED_USB11 == pUsbCore->speed)
+            {
+                ptr[4] = USBC_USB20_MAX_PACKET_SIZE & 0x00FF;
+                ptr[5] = (USBC_USB20_MAX_PACKET_SIZE >> 8) & 0x07;
+            }
+        }
+
+        ptr += currLength;
+        i += currLength;
+    }
+
+    return KAL_TRUE;
+}
+
+static kal_bool usbc_core_handle_get_descriptor()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    usbc_control_request_type_e type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    kal_uint8 bRecip = pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK;
+    //kal_uint16 wIndex = pUsbCore->setup_packet.wIndex;
+    kal_uint16 wValue = pUsbCore->setup_packet.wValue;
+    kal_uint16 wLength = pUsbCore->setup_packet.wLength;
+    kal_uint8* pBuffer = NULL;
+    kal_uint32 length = 0;
+
+    usbc_trace_info(USBCORE_GET_DESCRIPTOR, bRecip, (wValue >> 8));
+
+    if ( bRecip == USBC_REQUEST_RECIP_DEVICE )
+    {
+        kal_uint8 bDscrType = wValue >> 8;
+
+        switch ( bDscrType )
+        {
+            case USBC_DT_DEVICE:
+            {
+                usbc_core_printf("=========>usbcore_handle_get_descriptor: Device\r\n");
+                /* Device Descriptor Type */
+                if ( USBC_GET_DESC_LENGTH(pUsbCore->descriptors.device) > wLength )
+                {
+                    length = wLength;
+                } else {
+                    length = USBC_GET_DESC_LENGTH(pUsbCore->descriptors.device);
+                }
+                pBuffer = pUsbCore->descriptors.device;
+                type = USBC_CONTROL_REQUEST_TYPE_SEND;
+                break;
+            }
+            case USBC_DT_CONFIG:
+            {
+                kal_uint8 config_idx = wValue & 0xff; /* configuration index */
+
+                usbc_core_printf("=========>usbcore_handle_get_descriptor: Configuration\r\n");
+                /* Configuration Descriptor Type */
+                if ( USBC_GET_CONF_TOTAL_LENGTH(pUsbCore->descriptors.configuration[config_idx]) > wLength )
+                {
+                    length = wLength;
+                } else {
+                    length = USBC_GET_CONF_TOTAL_LENGTH(pUsbCore->descriptors.configuration[config_idx]);
+                }
+                pBuffer = pUsbCore->descriptors.configuration[config_idx];
+                type = USBC_CONTROL_REQUEST_TYPE_SEND;
+                break;
+            }
+            case USBC_DT_DEVICE_QUALIFIER:
+            {
+                usbc_core_printf("=========>usbcore_handle_get_descriptor: Qualifier\r\n");
+
+                if ( USBC_USB_SPEED_USB30 == pUsbCore->speed ) {
+                    type = USBC_CONTROL_REQUEST_TYPE_STALL;
+                    break;
+                }
+
+                /* Device Qualifier Type */
+                if ( pUsbCore->device_qualifier_descriptor.bLength > wLength )
+                {
+                    length = wLength;
+                } else {
+                    length = pUsbCore->device_qualifier_descriptor.bLength;
+                }
+                pBuffer = (kal_uint8*)&pUsbCore->device_qualifier_descriptor;
+                type = USBC_CONTROL_REQUEST_TYPE_SEND;
+                break;
+            }
+            case USBC_DT_STRING:
+            {
+                kal_uint8 bStrIdx = wValue & 0xff; /* String Type */
+
+                usbc_core_printf("=========>usbcore_handle_get_descriptor: String\r\n");
+
+                if (bStrIdx == USBC_MS_OS_STRING_INDEX)
+                {   /* MOD string descriptor */
+                    if ( !pUsbCore->morphing_enable || pUsbCore->state == USBC_USB_STATE_ATTACHED )
+                    {
+                        pBuffer = NULL;
+                        length = 0;
+                        type = USBC_CONTROL_REQUEST_TYPE_STALL;
+//                        dbg_print("[OSD] MOD 0xEE not handled by standard handler.\r\n");
+                        break;
+                    }
+                    usbc_os_string_desc.bLength = USBC_MAX_OS_STRING_LENGTH;
+                    usbc_os_string_desc.bDescriptorType = USBC_DT_STRING;
+                    kal_mem_cpy(usbc_os_string_desc.qwSignature, (kal_uint8*)usbc_os_string, 14);
+                    usbc_os_string_desc.bMS_VendorCode = USBC_REQ_GET_MS_DESCRIPTOR;
+                    usbc_os_string_desc.bPad = 0x00;
+
+					if (USBC_MAX_OS_STRING_LENGTH > wLength) {
+						length = wLength;
+					} else {
+						length = USBC_MAX_OS_STRING_LENGTH;
+					}
+					pBuffer = (kal_uint8*)&usbc_os_string_desc;
+					type = USBC_CONTROL_REQUEST_TYPE_SEND;
+                } else
+                {
+                    if (bStrIdx < pUsbCore->resource_string_number && pUsbCore->string_descriptor[bStrIdx] != NULL)
+                    {
+                        if (pUsbCore->string_descriptor[bStrIdx]->bLength > wLength) {
+                            length = wLength;
+                        } else {
+                            length = pUsbCore->string_descriptor[bStrIdx]->bLength;
+                        }
+                        pBuffer = (kal_uint8*)pUsbCore->string_descriptor[bStrIdx];
+                        type = USBC_CONTROL_REQUEST_TYPE_SEND;
+                    } else
+                    {
+                        pBuffer = NULL;
+                        length = 0;
+                        type = USBC_CONTROL_REQUEST_TYPE_STALL;
+                    }
+                }
+                break;
+            }
+            case USBC_DT_BOS:
+            {
+                usbc_core_printf("=========>usbcore_handle_get_descriptor: BOS\r\n");
+
+                /*if ( USBC_USB_SPEED_USB30 != pUsbCore->speed ) {
+                    type = USBC_CONTROL_REQUEST_TYPE_STALL;
+                    break;
+                }*/
+
+                /* Binary Device Object Store (BOS) Type */
+                pBuffer = usbc_bos_s;
+                if ( USBC_GET_BOS_TOTAL_LENGTH(pBuffer) > wLength ) {
+                    length = wLength;
+                } else {
+                    length = USBC_GET_BOS_TOTAL_LENGTH(pBuffer);
+                }
+                type = USBC_CONTROL_REQUEST_TYPE_SEND;
+                break;
+            }
+            case USBC_DT_OTHER_SPEED:
+            {
+                kal_uint8 config_idx = wValue & 0xff; /* configuration index */
+
+                usbc_core_printf("=========>usbcore_handle_get_descriptor: Other_Speed_Configuration\r\n");
+                /* Configuration Descriptor Type */
+
+                if ( USBC_USB_SPEED_USB30 == pUsbCore->speed ) {
+                    type = USBC_CONTROL_REQUEST_TYPE_STALL;
+                    break;
+                }
+
+                if ( USBC_GET_CONF_TOTAL_LENGTH(pUsbCore->descriptors.configuration[config_idx]) > wLength )
+                {
+                    length = wLength;
+                }
+                else
+                {
+                    length = USBC_GET_CONF_TOTAL_LENGTH(pUsbCore->descriptors.configuration[config_idx]);
+                }
+
+                // struct other speed configuration
+                usbc_core_update_dt_other_speed(pOtherSpeedDescript, config_idx);
+
+                pBuffer = pOtherSpeedDescript;
+                type = USBC_CONTROL_REQUEST_TYPE_SEND;
+                break;
+            }
+            default:
+            {
+                pBuffer = NULL;
+                length = 0;
+                type = USBC_CONTROL_REQUEST_TYPE_STALL;
+                break;
+            }
+        }
+    } else {
+        pBuffer = NULL;
+        length = 0;
+        type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    }
+
+    usbc_core_set_control_request(pBuffer, length, type);
+    return KAL_TRUE;
+}
+
+
+static kal_bool usbc_core_handle_set_configuration()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint16 wValue = pUsbCore->setup_packet.wValue;
+    usbc_ind_t ind_to_enqueue;
+
+#ifdef __USB_OSD_SUPPORT__
+    /* Quentin Li:
+     * Win 8 always set 2 configuration if morphing enabled
+     */
+    if ((wValue & 0xff) == pUsbCore->dev_param->morphing_sub_id) {
+		update_host_os_type(OSD_WIN_8);
+    }
+#endif
+
+    usbc_core_printf("=========>usbcore_handle_set_configuration\r\n");
+    usbc_trace_info(USBCORE_SET_CONFIG, wValue & 0xff);
+
+    if (USBC_IS_IN_EXCEPTION_MODE()) {
+        usbc_core_set_usb_configuration(wValue & 0xff);
+        usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+        return KAL_TRUE;
+    } else {
+        ind_to_enqueue.type = USBC_IND_SET_CONFIG;
+        ind_to_enqueue.ext = 0;
+        ind_to_enqueue.data = (kal_uint8)(wValue & 0xff);
+        usbc_enqueue_ind(&ind_to_enqueue);
+        hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+        
+        pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+        return KAL_FALSE;
+    }
+}
+
+
+static kal_bool usbc_core_handle_get_configuration()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8* pBuffer = pUsbCore->control_request_buffer;
+    kal_uint32 length = 0;
+
+    usbc_core_printf("=========>usbcore_handle_get_configuration\r\n");
+    usbc_trace_info(USBCORE_GET_CONFIG, pUsbCore->usb_configuration);
+
+    pBuffer[0] = pUsbCore->usb_configuration;
+    length = 1;
+
+    usbc_core_set_control_request(pBuffer, length, USBC_CONTROL_REQUEST_TYPE_SEND);    
+    return KAL_TRUE;
+}
+
+
+static kal_bool usbc_core_handle_set_interface()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    usbc_control_request_type_e type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    kal_uint8 bInterface = pUsbCore->setup_packet.wIndex & 0xff;
+    kal_uint16 wValue = pUsbCore->setup_packet.wValue;
+    kal_uint8 i;
+
+    usbc_core_printf("=========>usbcore_handle_set_interface\r\n");
+    usbc_trace_info(USBCORE_SET_INFX, bInterface, wValue);
+
+    do {
+        for ( i=0; i<pUsbCore->total_class_interfaces; i++ )
+        {
+            if ( (pUsbCore->class_interface[i].interface_no == bInterface) &&
+                 (pUsbCore->class_interface[i].state == USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE) )
+            {
+                break;
+            }
+        }
+
+        if ( i == pUsbCore->total_class_interfaces )
+        {
+            type = USBC_CONTROL_REQUEST_TYPE_STALL;
+            break;
+        }
+
+        pUsbCore->class_interface[i].alternate_setting = wValue & 0xff;
+
+        if ( pUsbCore->class_interface[i].notify_alternate_setting != NULL )
+        {
+            //type = USBC_CONTROL_REQUEST_TYPE_RECEIVE;
+            usbc_core_indicate_alternate_setting(i, pUsbCore->class_interface[i].alternate_setting);
+            pUsbCore->setup_indicated = KAL_TRUE; // set control request in task
+            return KAL_FALSE;
+        }
+        else
+        {
+            type = USBC_CONTROL_REQUEST_TYPE_STALL;
+        }
+    } while (0);
+
+    usbc_core_set_control_request(NULL, 0, type);    
+    return KAL_TRUE;
+
+}
+
+
+static kal_bool usbc_core_handle_get_interface()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    usbc_control_request_type_e type = USBC_CONTROL_REQUEST_TYPE_STALL;
+    kal_uint8 bInterface = pUsbCore->setup_packet.wIndex & 0xff;
+    //kal_uint16 wValue = pUsbCore->setup_packet.wValue;
+    kal_uint8* pBuffer = pUsbCore->control_request_buffer;
+    kal_uint32 length = 0;
+    kal_uint8 i;
+
+    usbc_core_printf("=========>usbcore_handle_get_interface\r\n");
+    usbc_trace_info(USBCORE_GET_INFX, bInterface);
+
+    do {
+        for ( i=0; i<pUsbCore->total_class_interfaces; i++ )
+        {
+            if ( (pUsbCore->class_interface[i].interface_no == bInterface) &&
+                 (pUsbCore->class_interface[i].state == USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE) )
+            {
+                break;
+            }
+        }
+
+        if ( i == pUsbCore->total_class_interfaces )
+        {
+            type = USBC_CONTROL_REQUEST_TYPE_STALL;
+            length = 0;
+            break;
+        }
+
+        pBuffer[0] = pUsbCore->class_interface[i].alternate_setting;
+        length = 1;
+        type = USBC_CONTROL_REQUEST_TYPE_SEND;
+
+    } while (0);
+
+    usbc_core_set_control_request(pBuffer, length, type);    
+    return KAL_TRUE;
+}
+
+static kal_bool usbc_core_handle_set_sel()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8* pBuffer = pUsbCore->control_request_buffer;
+    kal_uint32 length = 6;
+
+    usbc_core_printf("=========>usbcore_handle_set_sel\r\n");
+    // TODO: set exit latency value if support, do nothing currently
+    usbc_core_set_control_request(pBuffer, length, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+    
+    return KAL_TRUE;
+}
+
+static kal_bool usbc_core_handle_set_isochro_delay()
+{
+    usbc_core_printf("=========>usbcore_handle_isochro_delay\r\n");
+    // TODO: set isochronous delay value if support, do nothing currently
+    usbc_core_set_control_request(NULL, 0, USBC_CONTROL_REQUEST_TYPE_RECEIVE);
+    
+    return KAL_TRUE;
+}
+
+static void usbc_core_device_descriptor_speed_change(usbc_device_descriptor_t *desc, usbc_usb_speed_e speed)
+{
+    switch (speed) {
+        case USBC_USB_SPEED_USB30:
+            desc->bcdUSB = 0x0300;
+            desc->bMaxPacketSize0 = USBC_USB30_EP0_PACKET_SIZE;
+            break;
+
+        default:
+#ifdef __MTK_TARGET__
+	    desc->bcdUSB = 0x0210;
+#else
+	    desc->bcdUSB = 0x0200;
+#endif
+            desc->bMaxPacketSize0 = 64;
+            break;
+    }
+}
+
+static void usbc_core_compile_ep_companion(usbc_core_t *pUsbCore, kal_uint32 idx_cfg, kal_uint8 *dst_desc, kal_uint8 transfer_type, kal_uint8 ep_addr)
+{
+    kal_uint8 fifo_n = 1;
+
+    USBC_SET_DESC_LENGTH(dst_desc, USBC_ENDPOINT_COMPANION_DESC_SIZE);
+    USBC_SET_DESC_TYPE(dst_desc, USBC_DT_ENDPOINT_COMPANION);
+    USBC_SET_EPC_ATTRIBUTES(dst_desc, 0);
+    if (ep_addr & 0x80) {
+        fifo_n = pUsbCore->ep_tx_info[idx_cfg][HIFUSB_EPNO_2_QNO((ep_addr & 0xf))].queue_info.fifo_n;
+    }
+    else {
+        fifo_n = pUsbCore->ep_rx_info[idx_cfg][HIFUSB_EPNO_2_QNO((ep_addr & 0xf))].queue_info.fifo_n;
+    }
+
+    if (USBC_BULK_TRANSFER == transfer_type) {
+        USBC_SET_EPC_MAX_BURST(dst_desc, fifo_n - 1);
+        USBC_SET_EPC_BYTES_PER_INTERVAL(dst_desc, 0);
+    } else {
+        USBC_SET_EPC_MAX_BURST(dst_desc, 0);
+        USBC_SET_EPC_BYTES_PER_INTERVAL(dst_desc, 0x40);
+    }
+}
+
+static void usbc_core_configuration_speed_change(usbc_core_t *pUsbCore, usbc_usb_speed_e speed)
+{
+    kal_uint32 total_len;
+    kal_uint32 bytes_read;
+    kal_uint32 bytes_written;
+    kal_uint8 *desc_read;
+    kal_uint8 *desc_to_write;
+    kal_uint32 desc_len;
+    kal_uint32 idx_cfg;
+    kal_uint32 idx_ep;
+    kal_uint8  conf[USBC_MAX_CONF_SIZE];
+
+    for (idx_cfg = 0; idx_cfg < pUsbCore->dev_param->mode_param[pUsbCore->mode].cfg_num; idx_cfg++)
+    {
+        kal_mem_cpy(conf, pUsbCore->descriptors.configuration[idx_cfg], USBC_MAX_CONF_SIZE);
+        bytes_read = 0;
+        bytes_written = 0;
+        total_len = USBC_GET_CONF_TOTAL_LENGTH(conf);
+
+        while (bytes_read < total_len)
+        {
+            desc_read = conf + bytes_read;
+            desc_to_write = pUsbCore->descriptors.configuration[idx_cfg] + bytes_written;
+            desc_len = USBC_GET_DESC_LENGTH(desc_read);
+
+            kal_mem_cpy(desc_to_write, desc_read, desc_len);
+            bytes_written += desc_len;
+
+            switch (USBC_GET_DESC_TYPE(desc_read))
+            {
+                case USBC_DT_ENDPOINT:
+                {
+                    if (USBC_BULK_TRANSFER == USBC_GET_EP_TRANSFER_TYPE(desc_to_write))
+                    {
+                        switch (speed) {
+                            case USBC_USB_SPEED_USB11:
+                            {
+                                USBC_SET_EP_MAX_PACKET_SIZE(desc_to_write, USBC_USB11_MAX_PACKET_SIZE);
+                                break;
+                            }
+                            case USBC_USB_SPEED_USB20:
+                            {
+                                USBC_SET_EP_MAX_PACKET_SIZE(desc_to_write, USBC_USB20_MAX_PACKET_SIZE);
+                                break;
+                            }
+                            case USBC_USB_SPEED_USB30:
+                            {
+                                USBC_SET_EP_MAX_PACKET_SIZE(desc_to_write, USBC_USB30_MAX_PACKET_SIZE);
+                                break;
+                            }
+                            default:
+                            {
+                                ASSERT(0);
+                                break;
+                            }
+                        }
+                    }
+                    if (speed == USBC_USB_SPEED_USB30) {
+                        if (bytes_written + USBC_ENDPOINT_COMPANION_DESC_SIZE <= USBC_MAX_CONF_SIZE) {
+                            usbc_core_compile_ep_companion(pUsbCore, idx_cfg, desc_to_write + desc_len, USBC_GET_EP_TRANSFER_TYPE(desc_to_write), USBC_GET_EP_ADDR(desc_to_write));
+                            bytes_written += USBC_ENDPOINT_COMPANION_DESC_SIZE;
+                            /*if EP companion descriptors exsit, just update value, do not insert new one .*/
+                            if(USBC_GET_DESC_TYPE(desc_read + desc_len) == USBC_DT_ENDPOINT_COMPANION) {
+                                bytes_read += USBC_ENDPOINT_COMPANION_DESC_SIZE;
+                            }
+                        } else {
+                            EXT_ASSERT(0, USBCORE_LOC_MODIFY_CONFIG_DESC_OVERSIZE_FOR_U3_EP_COMP, (kal_uint32)speed, 0);
+                        }
+                    }
+                    break;
+                }
+
+                default:
+                   break;
+            }
+            bytes_read += desc_len;
+        }
+
+        /*
+         * Patch configuration descriptor.
+         */
+        EXT_ASSERT(bytes_written <= USBC_MAX_CONF_SIZE, USBCORE_LOC_MODIFY_CONFIG_DESC_OVERSIZE, (kal_uint32)bytes_written, 0);
+        if (speed == USBC_USB_SPEED_USB30) {
+            USBC_SET_CONF_MAX_POWER(pUsbCore->descriptors.configuration[idx_cfg], pUsbCore->u3ConfMaxPower);
+        }
+        USBC_SET_CONF_TOTAL_LENGTH(pUsbCore->descriptors.configuration[idx_cfg], bytes_written);
+
+        /*
+         * Modify max packet size in tx/rx endpoint queue info
+         */
+        for (idx_ep = 0; idx_ep < pUsbCore->resource_ep_tx_number[idx_cfg]; idx_ep ++)
+        {
+            if (pUsbCore->ep_tx_info[idx_cfg][idx_ep].queue_info.xfer_type == HIFUSB_EP_XFER_TYPE_BULK)
+            {
+                switch (speed) {
+                    case USBC_USB_SPEED_USB11:
+                    {
+                        pUsbCore->ep_tx_info[idx_cfg][idx_ep].queue_info.max_packet_size = USBC_USB11_MAX_PACKET_SIZE;
+                        break;
+                    }
+                    case USBC_USB_SPEED_USB20:
+                    {
+                        pUsbCore->ep_tx_info[idx_cfg][idx_ep].queue_info.max_packet_size = USBC_USB20_MAX_PACKET_SIZE;
+                        break;
+                    }
+                    case USBC_USB_SPEED_USB30:
+                    {
+                        pUsbCore->ep_tx_info[idx_cfg][idx_ep].queue_info.max_packet_size = USBC_USB30_MAX_PACKET_SIZE;
+                        break;
+                    }
+                    default:
+                    {
+                        ASSERT(0);
+                        break;
+                    }
+                }
+            }
+        }
+        for (idx_ep = 0; idx_ep < pUsbCore->resource_ep_rx_number[idx_cfg]; idx_ep ++)
+        {
+            if (pUsbCore->ep_rx_info[idx_cfg][idx_ep].queue_info.xfer_type == HIFUSB_EP_XFER_TYPE_BULK)
+            {
+                switch (speed) {
+                    case USBC_USB_SPEED_USB11:
+                    {
+                        pUsbCore->ep_rx_info[idx_cfg][idx_ep].queue_info.max_packet_size = USBC_USB11_MAX_PACKET_SIZE;
+                        break;
+                    }
+                    case USBC_USB_SPEED_USB20:
+                    {
+                        pUsbCore->ep_rx_info[idx_cfg][idx_ep].queue_info.max_packet_size = USBC_USB20_MAX_PACKET_SIZE;
+                        break;
+                    }
+                    case USBC_USB_SPEED_USB30:
+                    {
+                        pUsbCore->ep_rx_info[idx_cfg][idx_ep].queue_info.max_packet_size = USBC_USB30_MAX_PACKET_SIZE;
+                        break;
+                    }
+                    default:
+                    {
+                        ASSERT(0);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
+
+kal_bool usbc_core_handle_standard_request()
+{
+    static struct _usbc_request_entry {
+        kal_uint32          request;
+        kal_bool                (*request_handler)();
+    } request_entry_table[] = {
+        {USBC_REQ_SET_ADDRESS,              usbc_core_handle_set_address},
+        {USBC_REQ_GET_STATUS,               usbc_core_handle_get_status},
+        {USBC_REQ_SET_FEATURE,              usbc_core_handle_set_feature},
+        {USBC_REQ_CLEAR_FEATURE,            usbc_core_handle_clear_feature},
+        {USBC_REQ_GET_DESCRIPTOR,           usbc_core_handle_get_descriptor},
+        {USBC_REQ_SET_CONFIGURATION,        usbc_core_handle_set_configuration},
+        {USBC_REQ_GET_CONFIGURATION,        usbc_core_handle_get_configuration},
+        {USBC_REQ_SET_INTERFACE,            usbc_core_handle_set_interface},
+        {USBC_REQ_GET_INTERFACE,            usbc_core_handle_get_interface},
+        {USBC_REQ_SET_SEL,                  usbc_core_handle_set_sel},
+        {USBC_REQ_SET_ISOCHRONOUS_DELAY,    usbc_core_handle_set_isochro_delay},
+    };
+
+    kal_uint32      request_entry_table_num = sizeof(request_entry_table)/sizeof(struct _usbc_request_entry);
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_uint32      idx = 0;
+    kal_bool        handled = KAL_TRUE;
+
+    for (idx = 0; idx < request_entry_table_num; idx++) {
+        if (pUsbCore->setup_packet.bRequest == request_entry_table[idx].request) break;
+    }
+
+    if (idx < request_entry_table_num) {
+        handled = request_entry_table[idx].request_handler();
+    } else {
+        usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+    }
+
+    return handled;
+}
+
+
+void usbc_core_descriptors_speed_change(usbc_core_t *pUsbCore, usbc_usb_speed_e speed)
+{
+    usbc_core_device_descriptor_speed_change(
+            (usbc_device_descriptor_t *)pUsbCore->descriptors.device,
+            speed);
+
+    usbc_core_configuration_speed_change(pUsbCore, speed);
+}
+
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_task.c b/mcu/middleware/hif/usbcore/src/usbcore_task.c
new file mode 100644
index 0000000..c123e1c
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_task.c
@@ -0,0 +1,1000 @@
+/*!
+ *  @file usbcore_task.c
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main functions of usbcore
+ */
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "usbcore_hif.h"
+#include "usbcore_usbstd.h"
+#include "usbcore_main.h"
+#include "hmu.h"
+#include "hmu_conf_data.h"
+#include "sysservice_msgid.h"
+#include "nvram_interface.h"
+#include "nvram_data_items.h"
+#include "usbcore_debug.h"
+#include "usbcore_ind_q.h"
+#include "usbcore_dual_owner.h"
+#ifdef __MTK_MD_DIRECT_USB_SUPPORT__
+#include "usbcore_direct.h"
+#endif
+#ifdef __ESL_COSIM_HIF__
+#include "usbcore_cosim.h"
+#endif
+#include "usb_nvram_def.h"
+#include "l4_nvram_def.h" 
+#include "hif_mw_msgid.h"
+#include "custom_port.h"
+#include "usb_nvram_def.h" 
+#include "ps_public_l4_msgid.h"
+#include "ps_public_struct.h"
+#include "fs_general_types.h"
+#include "fs_general_api.h"
+#include "sleepdrv_interface.h"
+
+#define UNI_ID  NVRAM_EF_IMEI_IMEISV_LID
+extern ltable_entry_struct logical_data_item_table_usb[];
+extern kal_uint32 usb_mode_register_index;
+
+/*
+ * Current operation mode.
+ */
+static usbc_op_mode_e   usbc_op_mode_s = USBC_OP_MODE_UNKNOWN;
+
+/*
+ * USBCORE settings read from HMU.
+ */
+static usbc_hmu_info_t  usbc_hmu_info_s;
+
+/*
+ * Pointer to current USBCORE global context.
+ */
+static usbc_core_t     *usbc_inst_s = NULL;
+
+/*
+ * USBCORE global context for exception mode.
+ */
+static usbc_core_t      usbc_except_inst_s;
+
+/*
+ * USBCORE global context for normal mode.
+ */
+static usbc_core_t      usbc_normal_inst_s;
+
+/*
+ * USBCORE global context for DUALIPC parameters.
+ */
+kal_uint32 dipc_mode, port_mode, pcie_status;
+
+/*
+ * USBCORE global context for mode record.
+ */
+usbc_op_mode_e usbc_op_mode_record = USBC_OP_MODE_UNKNOWN;
+
+usbc_op_mode_e usbc_get_op_mode(void)
+{
+    return usbc_op_mode_s;
+}
+
+
+void usbc_set_op_mode(usbc_op_mode_e op_mode)
+{
+    if (USBC_OP_MODE_EXCEPTION == op_mode) {
+        usbc_inst_s = &usbc_except_inst_s;
+    } else {
+        usbc_inst_s = &usbc_normal_inst_s;
+    }
+    usbc_op_mode_s = op_mode;
+}
+
+
+usbc_core_t* usbc_core_get_instance()
+{
+    USBC_CORE_INSTANCE_CHECK(usbc_inst_s);
+    return usbc_inst_s;
+}
+
+
+usbc_hmu_info_t *usbc_core_get_hmu_info(void)
+{
+    return &usbc_hmu_info_s; 
+}
+
+
+void usbc_core_clear_register()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 i = 0;
+
+    /* Clear USB Core Register information */
+    for ( i=0; i<MAX_USBCORE_QUEUE_NUM; i++ )
+    {
+        pUsbCore->tx_queue[i].state = USBC_CORE_QUEUE_STATE_DISABLE;
+        pUsbCore->rx_queue[i].state = USBC_CORE_QUEUE_STATE_DISABLE;
+    }
+    for ( i=0; i<MAX_USBCORE_INTERFACE_NUM; i++ )
+    {
+        pUsbCore->class_interface[i].state = USBC_CORE_CLASS_INTERFACE_STATE_DISABLE;
+    }
+    for ( i=0; i<MAX_USBCORE_DEVICE_NUM; i++ )
+    {
+        pUsbCore->class_device[i].state = USBC_CORE_CLASS_DEVICE_STATE_NOTEXIST;
+    }
+
+    pUsbCore->total_class_devices = 0;
+    pUsbCore->total_class_interfaces = 0;
+    pUsbCore->total_tx_queues = 0;
+    pUsbCore->total_rx_queues = 0;
+}
+
+void usbc_core_clear_status()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 i;
+
+    /* Clear USBCORE task to wait for both indication events and tick events */
+    usbc_trace_info(USBCORE_SUSPEND_START_POLL);
+    pUsbCore->hmu_indication = HIF_DRV_EG_HIF_TICK_EVENT | HIF_DRV_EG_USBC_IND_EVENT;
+
+    /* Clear USB device status */
+    pUsbCore->usb_configuration = 0;
+    pUsbCore->is_device_u1_enable = KAL_FALSE;
+    pUsbCore->is_device_u2_enable = KAL_FALSE;
+    pUsbCore->is_device_ltm_enable = KAL_FALSE;
+
+    /* Clear USB class status */
+    for( i=0; i<MAX_USBCORE_DEVICE_NUM; i++ )
+    {
+        pUsbCore->class_device[i].is_func_suspend = KAL_FALSE;
+        pUsbCore->func_notify_list[i] = KAL_FALSE;
+    }
+
+    /* Clear USB XIT queue status */
+    for( i = 0; i < MAX_USBCORE_QUEUE_NUM; ++i) {
+        (pUsbCore->rx_xit_meta)[i].xit2meta_retry = KAL_FALSE;
+        (pUsbCore->rx_xit_meta)[i].remain_num = (pUsbCore->rx_xit_meta)[i].startIdx = (pUsbCore->rx_xit_meta)[i].endIdx = 0;
+    }
+
+    pUsbCore->usbc_txq_polled_mask = 0;
+    pUsbCore->usbc_rxq_polled_mask = 0;
+    pUsbCore->usbc_q_polled_duration = 0;
+}
+
+void usbc_core_queue_mutexlock_init()
+{
+    kal_uint8 i = 0;
+    kal_char usbc_queue_mutexlock_name[50];
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    for(i = 0 ; i < MAX_USBCORE_QUEUE_NUM; i++)
+    {
+        usbc_queue_mutexlock_name[0] = '\0';
+        sprintf(usbc_queue_mutexlock_name, "USBC_RXQ%d_MUTEX", i);
+        pUsbCore->rx_submit_enhmuexid[i] = kal_create_enh_mutex(usbc_queue_mutexlock_name);
+        ASSERT(pUsbCore->rx_submit_enhmuexid[i]);
+    }
+    return;
+}
+
+kal_bool usbc_core_is_1st_interface(kal_uint8 idx)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 i = 0;
+
+    for(i = 0; i <  pUsbCore->total_class_devices; i++)
+    {
+        if( pUsbCore->class_device[i].device_instance.interface_no[0] == idx )
+        {
+            return KAL_TRUE;
+        }
+    }
+
+    return KAL_FALSE;
+}
+
+kal_uint8 usbc_class_device_get_1st_interface(kal_uint8 class_device_id)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    return pUsbCore->class_device[class_device_id].device_instance.interface_no[0];
+}
+
+#define VAL_TO_STRING(uInt4Val) (((uInt4Val) < 0x0a)? ((uInt4Val) + 0x30):((uInt4Val) - 0x0a + 0x61))
+kal_bool usbc_core_set_serial_number(void)
+{
+    kal_bool result = KAL_FALSE;
+
+#if USB_UNIQUE_SERIAL_NUM_ENABLE
+
+    #define NO_IMEI_SERIAL_NUM  0xffffffffffffffff
+
+    kal_uint16* pSerialNumber = usbc_core_get_instance()->dev_param->serial_number;
+    kal_uint8 *pBuffer = NULL;
+    kal_uint16 record, size, sVal;
+    kal_uint8 i = 0;
+
+    /* check for valid ID for NVRAM */
+    if( NVRAM_ERRNO_SUCCESS != nvram_get_info(UNI_ID, &record, &size) )
+    {
+        EXT_ASSERT(0, USBCORE_LOC_GET_EMEI_LID_INFO_FAIL, (kal_uint32)UNI_ID, 0);
+        return result;
+    }
+
+    pBuffer = (kal_uint8*)get_ctrl_buffer(size);
+
+    /* store IMEI to pBuffer, and store the length of IMEI to size */
+    if ( nvram_external_read_data(UNI_ID, 1, pBuffer, (kal_uint32)size) )
+    {
+        if(NO_IMEI_SERIAL_NUM != *((kal_uint64*)pBuffer))   // update serial number if IEMI has been set
+        {
+            /* 
+            * Assume the maximum length of IEMI is 0x0F, and we also define the length of serial number as 0x0F.
+            * Then the length of parsed IMEI must be smaller or equal to the length of serial number
+            */
+            size = (size <= (0x0f >> 1))? size:(0x0f >> 1);
+            while( i < size )
+            {
+                sVal = pBuffer[i] & 0x0f;                       // the lower part of pBuffer[i] is the odd part of the serail number
+                pSerialNumber[(i<<1)+1] = VAL_TO_STRING(sVal);
+                sVal = (pBuffer[i] & 0xf0) >> 4;                // the higher part of pBuffer[i] is the even part of the serail number
+                pSerialNumber[(i<<1)+2] = VAL_TO_STRING(sVal);
+                i++;
+            }
+            sVal = pBuffer[i] & 0x0f;                           // pBuffer[15] is the last field of the serail number
+            pSerialNumber[0x0f] = VAL_TO_STRING(sVal);
+
+            free_ctrl_buffer(pBuffer);
+            result =  KAL_TRUE;
+        }
+    }
+    else
+    {
+        free_ctrl_buffer(pBuffer);
+        EXT_ASSERT(0, USBCORE_LOC_GET_EMEI_LID_VALUE_FAIL, (kal_uint32)UNI_ID, 0);
+    }
+#endif
+
+    return result;
+}
+
+kal_uint8 usbc_set_serial_number_for_internal()
+{
+    kal_bool result = KAL_FALSE;
+    kal_uint16* pSerialNumber = usbc_core_get_instance()->dev_param->serial_number;
+    kal_uint8 *pBuffer = NULL;
+    kal_uint16 record, size;
+    kal_uint8 i = 0;
+    kal_bool sn_valid_flag = KAL_TRUE;
+    kal_uint16 usb_serial_num[] = {0x031a,'6','6','5','5','4','4','3','3','2','2','1','1' };
+    
+    /* check for valid ID for NVRAM */
+    if( NVRAM_ERRNO_SUCCESS != nvram_get_info(NVRAM_EF_USB_SN_LID, &record, &size) )
+    {
+        EXT_ASSERT(0, USBCORE_LOC_GET_SN_LID_INFO_FOR_ENUM_FAIL, (kal_uint32)NVRAM_EF_USB_SN_LID, 0);
+        return result;
+    }
+
+    pBuffer = (kal_uint8*)get_ctrl_buffer(size);
+
+    /* store SN to pBuffer, and store the length of SN to size */
+    if ( nvram_external_read_data(NVRAM_EF_USB_SN_LID, 1, pBuffer, (kal_uint32)size) )
+    {
+        for(i = 0; i < size; i++)
+        {
+            if((pBuffer[i] >= '0' && pBuffer[i] <= '9') || (pBuffer[i] >= 'a' && pBuffer[i] <= 'z') || (pBuffer[i]>= 'A' && pBuffer[i] <= 'Z') || pBuffer[i] == '-' || pBuffer[i] == '_' || pBuffer[i] == '#')
+                pSerialNumber[i + 1] = pBuffer[i];
+            else
+            {
+                sn_valid_flag = KAL_FALSE;
+                break;
+            }
+        }
+        /*invalid SN*/
+        if(sn_valid_flag == KAL_FALSE)
+        {
+            kal_mem_cpy(pSerialNumber, usb_serial_num, sizeof(usb_serial_num));
+        }
+        
+        free_ctrl_buffer(pBuffer);
+        result =  KAL_TRUE;
+    }    
+    return result;
+}
+
+void usbc_core_check_low_power_enable()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    if(dipc_mode == PORT_DIPC_MODE_USB_ONLY)
+        pUsbCore->usb_low_power_enable = KAL_TRUE;
+    else
+        pUsbCore->usb_low_power_enable = KAL_FALSE;
+    usbc_trace_warn(USBCORE_GET_LOW_POWER_ENABLE_VALUE, pUsbCore->usb_low_power_enable);
+}
+
+kal_uint16 usbc_core_get_function_remote_wk_list(void)
+{
+    kal_uint8 i, total_class_device;
+    kal_uint16 result = 0; 
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    total_class_device = pUsbCore->total_class_devices;
+
+    for(i=0; i<total_class_device; i++)
+    {
+        if ( pUsbCore->class_device[i].query_func_wk_status &&
+             pUsbCore->class_device[i].query_func_wk_status(i) == 0x03 )
+        {
+            result |= (0x01 << i);
+        } 
+    }
+
+    return result;
+}
+
+kal_uint16 usbc_core_get_function_suspend_list(void)
+{
+    kal_uint8 i, total_class_device;
+    kal_uint16 result = 0; 
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    total_class_device = pUsbCore->total_class_devices;
+
+    for(i=0; i<total_class_device; i++)
+    {
+        /*if class_device is AP owner, its suspend state should not effect MD lowpower flow,
+        so set its state to suspended state when get suspend list*/
+        if (pUsbCore->class_device[i].owner != USB_CLASS_OWNER_MD)
+        {
+            result |= (0x01 << i);
+            continue;
+        }
+    
+        if ( pUsbCore->class_device[i].is_func_suspend &&
+             pUsbCore->class_device[i].is_func_suspend == KAL_TRUE )
+        {
+            result |= (0x01 << i);
+        }
+    }
+
+    return result;
+}
+
+void usbc_core_check_mass_strorage_onoff()
+{
+    kal_wchar *filepath = NULL;
+    filepath = (kal_wchar *)get_ctrl_buffer(USBC_READ_FILE_PATH_MAX_LENGTH);
+    kal_wsprintf(filepath, "%s", "V:\\usb_config");
+    char *buffer = NULL;
+    FS_HANDLE file_handle;
+    usbc_ms_enable_e ms_enable = MSD_INVALID;
+    kal_uint8 idx_cfg = 0; 
+    char *value = NULL;
+    char pattern[] = "mass_storage_mode:";
+    
+    usbc_core_t  *usbc_inst = usbc_core_get_instance();
+    usb_mode_e mode = usbc_inst->mode;
+    kal_uint8 cfg_num = usbc_inst->dev_param->mode_param[mode].cfg_num;
+    usb_cfg_param_t  *cfg_param;
+
+    buffer = (char *)get_ctrl_buffer(USBC_READ_FILE_DATA_MAX_LENGTH);
+    kal_mem_set((kal_uint8*)buffer, 0, USBC_READ_FILE_DATA_MAX_LENGTH);
+    if ((file_handle = FS_Open(filepath, FS_READ_ONLY | FS_OPEN_NO_DIR)) >= FS_NO_ERROR) {
+        kal_uint32 read_size;
+        if (FS_Read(file_handle, (kal_uint8*)buffer, USBC_READ_FILE_DATA_MAX_LENGTH - 1, &read_size) >= FS_NO_ERROR) {         
+            buffer[read_size] = '\0';
+            value = strstr(buffer, pattern);
+            if(value != NULL && buffer[strlen(pattern)] >= '0' && buffer[strlen(pattern)] <= '9')
+            {
+                ms_enable = buffer[strlen(pattern)] - '0';
+                if(ms_enable == MSD_ENABLE)
+                {
+                    /*msd is enable, change config*/
+                    for (idx_cfg = 0; idx_cfg < cfg_num; idx_cfg++)
+                    {
+                        cfg_param = &usbc_inst->dev_param->mode_param[mode].cfg_param[idx_cfg];
+                        if(cfg_param->class_num >= USB_MAX_CLASS_NUM)
+                            continue;
+                
+                        cfg_param->class_type[cfg_param->class_num] = USB_CLASS_MS;
+                        cfg_param->class_owner[cfg_param->class_num] = USB_CLASS_OWNER_AP;
+                        cfg_param->class_ctxt[cfg_param->class_num] = (void*)0;
+                        cfg_param->bulk_fifo_n[cfg_param->class_num] = 0x11;
+                        cfg_param->class_num++;
+                    }
+                }
+                else
+                {
+                    /*msd is disable, do nothing*/
+                }
+            }
+        }
+    }
+    free_ctrl_buffer(buffer);
+    free_ctrl_buffer(filepath);
+}
+
+void usbc_ut_dualipc_op_mode_select(kal_uint32 *dipc_mode, kal_uint32 *port_mode, kal_uint32 *pcie_status)
+{
+    kal_uint8 *pBuffer = NULL;
+    kal_uint16 record, size;
+
+    nvram_get_info(NVRAM_EF_USB_VIDPID_LID, &record, &size);
+    pBuffer = (kal_uint8*)get_ctrl_buffer(size);
+    nvram_external_read_data(NVRAM_EF_USB_VIDPID_LID, 1, pBuffer, (kal_uint32)size);
+    *dipc_mode = (*((kal_uint16*)pBuffer)) & 0xf;
+    *pcie_status = (*((kal_uint16*)pBuffer)) & 0xf0;
+    nvram_external_read_data(NVRAM_EF_USB_VIDPID_LID, 2, pBuffer, (kal_uint32)size);
+    *port_mode = (*((kal_uint16*)pBuffer)) & 0xf;
+}
+
+kal_bool usbc_core_get_dipc_status()
+{
+#ifndef __USBC_DIPC_UT_TEST__
+    dipc_mode = CUSTOM_PORT_GET_DIPC_MODE(0);
+    pcie_status = CUSTOM_PORT_GET_PCIE_STATUS(0);
+    port_mode = CUSTOM_PORT_GET_MODE(CUSTOM_PORT_USER_LOG);
+#else
+    usbc_ut_dualipc_op_mode_select(&dipc_mode, &port_mode, &pcie_status);
+#endif
+
+    switch(dipc_mode)
+    {
+        case PORT_DIPC_MODE_NOT_SUPPORT:
+        #ifdef __HIF_PCIE_SUPPORT__
+            usbc_set_op_mode(USBC_OP_MODE_METADEBUG);            
+        #else
+            usbc_set_op_mode(USBC_OP_MODE_NORMAL);            
+        #endif
+            break;
+        case PORT_DIPC_MODE_DUAL_IPC:
+            if((pcie_status == PORT_PCIE_STATUS_LINK_UP)&&(port_mode != PORT_MODE_USB && port_mode != PORT_MODE_USB_AND_PCIE))
+            {
+                usbc_set_op_mode(USBC_OP_MODE_NOLOGGING);            
+            }
+            else
+            {
+                usbc_set_op_mode(USBC_OP_MODE_NORMAL);            
+            }
+            break;
+        case PORT_DIPC_MODE_PCIE_ADVANCE:
+            if(pcie_status == PORT_PCIE_STATUS_LINK_UP)
+            {
+                usbc_set_op_mode(USBC_OP_MODE_UNUSED);                
+                return KAL_FALSE;
+            }
+            else
+            {
+                usbc_set_op_mode(USBC_OP_MODE_NORMAL);            
+            }
+            break;
+        case PORT_DIPC_MODE_PCIE_ONLY:
+            usbc_set_op_mode(USBC_OP_MODE_UNUSED);            
+            return KAL_FALSE;
+        case PORT_DIPC_MODE_USB_ONLY:
+            usbc_set_op_mode(USBC_OP_MODE_NORMAL);
+            break;
+        default:
+            EXT_ASSERT(0, USBCORE_LOC_DUALIPC_INVALID_PARAMETER, dipc_mode, 0);
+    }
+    return KAL_TRUE;
+}
+
+
+usbc_atcmd_hd_t usbc_atcmd_handle_table[] =
+{
+#ifndef __PRODUCTION_RELEASE__
+/* under construction !*/
+#endif
+    {"usb_mode",            usbc_core_handle_set_usb_mode_atcmd,        usbc_core_handle_get_usb_mode_atcmd},         
+    {"usb_pwrdown",            usbc_core_handle_powerdown_usb_atcmd,        NULL},  
+};
+
+kal_bool usbc_core_handle_powerdown_usb_atcmd(void *req, void *cnf)
+{
+    usbc_ind_t ind_to_enqueue;
+    usbc_normal_hif_disconnect();
+    ind_to_enqueue.type = USBC_IND_IP_PWRDOWN;
+    ind_to_enqueue.ext = 0;
+    ind_to_enqueue.data = 0;
+    usbc_enqueue_ind(&ind_to_enqueue);
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+
+    return KAL_TRUE;
+}
+kal_bool usbc_core_handle_set_usb_mode_atcmd(void *req, void *cnf)
+{
+    kal_uint16 record, size;
+    kal_uint8 mode_idx;
+    kal_uint8 *pBuffer = NULL;
+    kal_bool result = KAL_FALSE;            
+    usbc_core_t* usbc_inst = usbc_core_get_instance();
+    l4c_general_modem_configure_struct *at_data = &(((l4c_general_modem_configure_set_req_struct*)req)->data);
+
+    if(at_data->param_num != 2 || at_data->type[0] != L4C_AT_CMD_PARAM_INTEGER || at_data->type[1] != L4C_AT_CMD_PARAM_INTEGER)
+        return KAL_FALSE;
+    
+    /* check for valid ID for NVRAM */
+    if( NVRAM_ERRNO_SUCCESS != nvram_get_info(NVRAM_EF_USB_MODE_LID, &record, &size) )
+    {
+        EXT_ASSERT(0, USBCORE_LOC_GET_MODE_LID_INFO_FOR_SET_FAIL, (kal_uint32)NVRAM_EF_USB_MODE_LID, 0);
+        return KAL_FALSE;
+    }
+    ASSERT(size == 2);        
+    
+    pBuffer = (kal_uint8*)get_ctrl_buffer(size * record);
+    pBuffer[0] = at_data->param[0].integer_num;
+    pBuffer[1] = at_data->param[1].integer_num;
+
+    for(mode_idx = 0; mode_idx < usb_mode_register_index; mode_idx++)
+    {
+
+        if(usbc_inst->dev_param->mode_param[mode_idx].mode_owner == pBuffer[0] && usbc_inst->dev_param->mode_param[mode_idx].mode_index == pBuffer[1])
+        {
+            break;
+        }
+    }
+    if(mode_idx >= usb_mode_register_index)
+    {
+       /*mode or index invalid*/
+       return KAL_FALSE;
+    }
+
+   result =  nvram_external_write_data(NVRAM_EF_USB_MODE_LID, 1, pBuffer, size);
+   free_ctrl_buffer(pBuffer);
+   return result;
+}
+
+kal_bool usbc_core_handle_get_usb_mode_atcmd(void *req, void *cnf)
+{
+    kal_uint16 record, size;
+    kal_uint8 *pBuffer = NULL;
+    kal_bool result = KAL_FALSE;            
+    l4c_general_modem_configure_struct *at_data = &(((l4c_general_modem_configure_query_cnf_struct*)cnf)->data);
+    
+    /* check for valid ID for NVRAM */
+    if( NVRAM_ERRNO_SUCCESS != nvram_get_info(NVRAM_EF_USB_MODE_LID, &record, &size) )
+    {
+        EXT_ASSERT(0, USBCORE_LOC_GET_MODE_LID_INFO_FOR_AT_GET_FAIL, (kal_uint32)NVRAM_EF_USB_MODE_LID, 0);
+        return KAL_FALSE;
+    }
+    ASSERT(size == 2);        
+    
+    pBuffer = (kal_uint8*)get_ctrl_buffer(size * record);
+
+    if ( nvram_external_read_data(NVRAM_EF_USB_MODE_LID, 1, pBuffer, (kal_uint32)size) )
+    {
+        at_data->param_num = 2;
+        at_data->type[0] = L4C_AT_CMD_PARAM_INTEGER;
+        at_data->type[1] = L4C_AT_CMD_PARAM_INTEGER;
+        at_data->param[0].integer_num = *((kal_uint8*)pBuffer);
+        at_data->param[1].integer_num = *((kal_uint8*)(pBuffer + sizeof(kal_uint8)));
+        result = KAL_TRUE;
+    }
+
+    free_ctrl_buffer(pBuffer);
+    return result;
+}
+
+kal_bool usbc_core_handle_set_serialnumber_atcmd(void *req, void *cnf)
+{
+    kal_uint16 record, size, i;
+    kal_bool result = KAL_FALSE;    
+    kal_uint8 *pBuffer = NULL;
+    l4c_general_modem_configure_struct *at_data = &(((l4c_general_modem_configure_set_req_struct*)req)->data);
+    kal_uint8 length;
+    char c;
+
+    if(at_data->param_num != 1 || at_data->type[0] != L4C_AT_CMD_PARAM_STRING_S)
+        return KAL_FALSE;
+
+    length = strlen((char*)at_data->param[0].string_s);
+    if( NVRAM_ERRNO_SUCCESS != nvram_get_info(NVRAM_EF_USB_SN_LID, &record, &size) )
+    {
+        EXT_ASSERT(0, USBCORE_LOC_GET_SN_LID_INFO_FOR_SET_FAIL, (kal_uint32)NVRAM_EF_USB_SN_LID, 0);
+        return KAL_FALSE;
+    }
+    pBuffer = (kal_uint8*)get_ctrl_buffer(size);
+    if(pBuffer == NULL)
+    {
+        return KAL_FALSE;
+    }
+    
+    for(i = 0; i < size; i++)
+    {
+        if(i < length)
+        {
+            c = at_data->param[0].string_s[i];
+            if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c>= 'A' && c <= 'Z') || c == '-' || c == '_' || c == '#')
+                pBuffer[i] = c;
+            else
+            {
+                free_ctrl_buffer(pBuffer);
+                return KAL_FALSE;
+            }
+        }
+        else
+            pBuffer[i] = '0';
+    }
+
+    result =  nvram_external_write_data(NVRAM_EF_USB_SN_LID, 1, pBuffer, size);
+    free_ctrl_buffer(pBuffer);
+    return result;
+}
+
+kal_bool usbc_core_handle_get_serialnumber_atcmd(void *req, void *cnf)
+{
+    kal_uint16 record, size, i;
+    kal_bool result = KAL_FALSE;    
+    kal_uint8 *pBuffer = NULL;
+    l4c_general_modem_configure_struct *at_data = &(((l4c_general_modem_configure_query_cnf_struct*)cnf)->data);
+    kal_bool sn_valid_flag = KAL_TRUE;
+    
+    /* check for valid ID for NVRAM */
+    if( NVRAM_ERRNO_SUCCESS != nvram_get_info(NVRAM_EF_USB_SN_LID, &record, &size) )
+    {
+        EXT_ASSERT(0, USBCORE_LOC_GET_SN_LID_INFO_FOR_AT_GET_FAIL, (kal_uint32)NVRAM_EF_USB_SN_LID, 0);
+        return result;
+    }
+
+    pBuffer = (kal_uint8*)get_ctrl_buffer(size);
+
+    /* store SN to pBuffer, and store the length of SN to size */
+    if ( nvram_external_read_data(NVRAM_EF_USB_SN_LID, 1, pBuffer, (kal_uint32)size) )
+    {
+        for(i = 0; i < size; i++)
+        {
+            if((pBuffer[i] >= '0' && pBuffer[i] <= '9') || (pBuffer[i] >= 'a' && pBuffer[i] <= 'z') || (pBuffer[i] >= 'A' && pBuffer[i] <= 'Z') || pBuffer[i] == '-' || pBuffer[i] == '_'|| pBuffer[i] == '#')
+            {
+                at_data->param[0].string_s[i] = pBuffer[i];
+            }
+            else
+            {
+                sn_valid_flag = KAL_FALSE;
+                break;
+            }
+        }
+        /*invalid SN*/
+        if(sn_valid_flag == KAL_FALSE)
+        {
+            kal_mem_set(at_data->param[0].string_s, 0, MAX_ATCMD_EGMC_SHORT_STR_LEN);
+            return KAL_FALSE;
+        }
+        
+        at_data->param_num = 1;
+        at_data->type[0] = L4C_AT_CMD_PARAM_STRING_S;
+        free_ctrl_buffer(pBuffer);
+        result =  KAL_TRUE;
+    }    
+    return result;
+}
+
+static void usbc_core_handle_atcmd(ilm_struct *current_ilm)
+{
+    l4c_general_modem_configure_set_req_struct *set_req_ptr = NULL;    
+    l4c_general_modem_configure_set_cnf_struct *set_cnf_ptr = NULL;
+    l4c_general_modem_configure_query_req_struct *query_req_ptr = NULL;    
+    l4c_general_modem_configure_query_cnf_struct *query_cnf_ptr = NULL;
+    char *cmd_type = NULL;
+    kal_bool is_set;
+    kal_bool ret = KAL_FALSE;
+    kal_uint16 param_len;
+    kal_uint8 i = 0;
+
+    if(current_ilm->msg_id == MSG_ID_L4C_GENERAL_MODEM_CONFIGURE_SET_REQ)
+    {
+        set_req_ptr = (l4c_general_modem_configure_set_req_struct*)get_local_para_ptr(current_ilm->local_para_ptr, &param_len);
+        set_cnf_ptr = (l4c_general_modem_configure_set_cnf_struct*)construct_local_para(sizeof(l4c_general_modem_configure_set_cnf_struct), TD_RESET);
+        cmd_type = (char*)set_req_ptr->configure_string;
+        is_set = KAL_TRUE;
+    }
+    else
+    {
+        query_req_ptr = (l4c_general_modem_configure_query_req_struct*)get_local_para_ptr(current_ilm->local_para_ptr, &param_len);
+        query_cnf_ptr = (l4c_general_modem_configure_query_cnf_struct*)construct_local_para(sizeof(l4c_general_modem_configure_query_cnf_struct), TD_RESET);        
+        cmd_type = (char*)query_req_ptr->configure_string;        
+        is_set = KAL_FALSE;
+    }
+
+    for(i = 0 ; i < sizeof(usbc_atcmd_handle_table)/sizeof(usbc_atcmd_hd_t) ; i++)
+    {
+        if(0 == strcmp(cmd_type, usbc_atcmd_handle_table[i].cmd_type))
+            break;
+    }
+
+    if(i < sizeof(usbc_atcmd_handle_table)/sizeof(usbc_atcmd_hd_t))
+    {
+        if(is_set && usbc_atcmd_handle_table[i].handle_set_func != NULL)
+            ret = usbc_atcmd_handle_table[i].handle_set_func((void*)set_req_ptr, (void*)set_cnf_ptr);
+        else if(!is_set && usbc_atcmd_handle_table[i].handle_get_func != NULL)
+            ret = usbc_atcmd_handle_table[i].handle_get_func((void*)query_req_ptr, (void*)query_cnf_ptr);
+    }
+
+    usbc_trace_warn(USBCORE_RECEIVE_ATCMD_MSG, cmd_type,  ret);
+    if(is_set)
+    {
+        set_cnf_ptr->src_id = set_req_ptr->src_id;
+        set_cnf_ptr->result = ret;
+        set_cnf_ptr->data.param_num = 0;
+        kal_mem_cpy(set_cnf_ptr->configure_string, cmd_type, sizeof(set_cnf_ptr->configure_string));
+        msg_send6( kal_get_active_module_id(),                           /* src_mod_id */
+            MOD_L4C,                                                     /* dst_mod_id */
+            0,                                                                                                                     /* sap_id */
+            MSG_ID_L4C_GENERAL_MODEM_CONFIGURE_SET_CNF,                  /* msg_id */
+            (local_para_struct*)set_cnf_ptr,                             /* local_para_ptr */
+            NULL);  
+    }
+    else
+    {
+        query_cnf_ptr->src_id = query_req_ptr->src_id;
+        kal_mem_cpy(query_cnf_ptr->configure_string, cmd_type, sizeof(query_cnf_ptr->configure_string));
+        msg_send6( kal_get_active_module_id(),                           /* src_mod_id */
+            MOD_L4C,                                                     /* dst_mod_id */
+            0,                                                                                                                     /* sap_id */
+            MSG_ID_L4C_GENERAL_MODEM_CONFIGURE_QUERY_CNF,                  /* msg_id */
+            (local_para_struct*)query_cnf_ptr,                             /* local_para_ptr */
+            NULL);  
+    }
+    
+    return;
+}
+
+static void usbc_core_task_main(task_entry_struct* task_entry_ptr)
+{
+    ilm_struct current_ilm;
+    kal_uint32 rt_event;
+    kal_uint16 timer_index;
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    kal_set_active_module_id(MOD_USBCORE);
+    kal_mem_set(&current_ilm, 0, sizeof(ilm_struct));
+
+    usbc_trace_info(USBCORE_TASK_MAIN);
+
+    if(usbc_get_op_mode() == USBC_OP_MODE_UNUSED)
+    {
+        return;
+    }
+
+    if( !pUsbCore->is_mode_meta_reused )
+    {
+        ubm_drb_init_properties();
+        ubm_ul_meta_init_properties();
+
+#ifndef __MTK_MD_DIRECT_USB_SUPPORT__   
+        usbc_normal_hif_connect();
+#else
+        usbc_direct_hif_enable_poll_queue(KAL_FALSE);
+#endif
+    }
+
+#ifdef __UBM_UT__
+    ubm_ut_test_cases();
+#endif
+
+#ifdef __UFPM_UT__
+    ufpm_ut_func_test_series1();
+#endif
+
+    while (1)
+    {
+        //usbc_core_printf("=========>usbcore_task_main\r\n");
+
+        /* msg_receive_extq will block, therefore we poll if any message
+           exist first */
+        while ( msg_get_extq_messages() > 0 )
+        {
+            if ( msg_receive_extq(&current_ilm) != KAL_TRUE )
+            {
+                break;
+            }
+
+#ifdef __MTK_MD_DIRECT_USB_SUPPORT__ 
+            if(MOD_UFPM == current_ilm.dest_mod_id) {
+                ufpm_on_ilm(&current_ilm);
+            }
+            else 
+#endif            
+            {
+                switch (current_ilm.msg_id)
+                {
+                   case MSG_ID_TIMER_EXPIRY:
+                        timer_index = evshed_get_index(&current_ilm);
+                        switch (timer_index)
+                        {
+                            case USBC_WK_NOTIFY_INDEX:
+                                evshed_timer_handler(pUsbCore->usbc_es_wk_notify_g);
+                                break;
+
+                            default:
+                                break;
+                        }
+                        break;
+                    /*msgid for AP msg receive in dual usb owner, read CCCI buffer and handle when receive msgid*/
+                    case MSG_ID_USBCORE_DUAL_OWNER_MSG_RECEIVE:
+                        if(usbc_dual_owner_ilm_handle != NULL)
+                            usbc_dual_owner_ilm_handle();
+                        break;
+                    case MSG_ID_L4C_GENERAL_MODEM_CONFIGURE_SET_REQ:         
+                    case MSG_ID_L4C_GENERAL_MODEM_CONFIGURE_QUERY_REQ:   
+                        usbc_core_handle_atcmd(&current_ilm);
+                        break;
+                    default:
+                        break;
+                }        
+            }
+
+            destroy_ilm(&current_ilm);
+        }
+
+        /* Wait someone notify HMU to wake up HIF. */
+        rt_event = hmu_hifeg_wait(pUsbCore->hmu_indication) & pUsbCore->hmu_indication;
+        if ((HIF_DRV_EG_HIF_TICK_EVENT & rt_event) && 
+            (pUsbCore->state != USBC_USB_STATE_SUSPENDED) && (pUsbCore->state != USBC_USB_STATE_DETACHED))
+        {
+            /* poll HIF queue data */
+            usbc_normal_hif_poll_queue();
+        } 
+        if ((HIF_DRV_EG_USBC_IND_EVENT & rt_event))
+        {
+            /* Handle indications */
+            usbc_normal_hif_process_indications();
+        } 
+    }
+}
+
+
+static kal_bool usbc_core_task_init(void)
+{
+    usbc_core_t* pUsbCore;
+    kal_char usbc_class_mutex_name[50];
+    kal_bool ind_q_spinlock_init;
+    usbc_core_printf("=========>usbcore_task_init\r\n");
+    usbc_trace_info(USBCORE_TASK_INIT);
+
+#if defined(IPCORE_NOT_PRESENT) || !defined(__IPCORE_SUPPORT__) || defined(__IPCORE_TASK_DISABLE__)
+    hmu_boot_init();
+#endif
+
+    usbc_set_op_mode(USBC_OP_MODE_NORMAL);
+    kal_mem_set(usbc_core_get_instance(), 0, sizeof(usbc_core_t));
+
+    usbc_core_clear_register();
+    usbc_core_clear_status();
+
+    pUsbCore = usbc_core_get_instance();    
+    nvram_ltable_register(logical_data_item_table_usb);
+    if(KAL_FALSE == usbc_core_get_dipc_status())
+    {
+        return KAL_TRUE;
+    }
+    usbc_op_mode_record = usbc_get_op_mode();
+
+    // create enhance mutex
+    sprintf(usbc_class_mutex_name, "USBC_CLASS_REMOTE_WK_MUTEX");
+    pUsbCore->usbc_class_remote_wk_mutex = kal_create_enh_mutex(usbc_class_mutex_name);
+    sprintf(usbc_class_mutex_name, "USBC_CLASS_RENOTIFY_MUTEX");
+    pUsbCore->usbc_class_renotify_mutex = kal_create_enh_mutex(usbc_class_mutex_name);
+    sprintf(usbc_class_mutex_name, "USBC_CLASS_FUNC_ACCESS_MUTEX");
+    pUsbCore->usbc_class_func_access_mutex = kal_create_enh_mutex(usbc_class_mutex_name);
+    sprintf(usbc_class_mutex_name, "USBC_RESUME_MUTEX");
+    pUsbCore->usbc_class_resume_mutex = kal_create_enh_mutex(usbc_class_mutex_name);
+    sprintf(usbc_class_mutex_name, "USBC_SETUP_SPINLOCK");
+    pUsbCore->setup_packet_spinlock= kal_create_spinlock(usbc_class_mutex_name);
+    ind_q_spinlock_init = usbc_ind_queue_spinlock_init();
+    usbc_core_queue_mutexlock_init();
+
+    if ( NULL == pUsbCore->usbc_class_remote_wk_mutex ||
+         NULL == pUsbCore->usbc_class_renotify_mutex ||
+         NULL == pUsbCore->usbc_class_func_access_mutex ||
+         NULL == pUsbCore->usbc_class_resume_mutex ||
+         NULL == pUsbCore->setup_packet_spinlock ||
+         KAL_FALSE == ind_q_spinlock_init)
+    {
+        ASSERT(0);
+    }
+
+    // initial an evnet scheduler
+    pUsbCore->usbc_es_wk_notify_g = evshed_create(
+                        "USBC_WK_NOTIFY", /* timer_name: event scheduler name */
+                        MOD_USBCORE, /* dest_mod_id: system sends timeout message to this module when event scheduler timeout happens */
+                        0, /* fuzz */
+                        (KAL_TICKS_10_MSEC * 255 / 2)); /* max_delay_ticks */
+    if (pUsbCore->usbc_es_wk_notify_g) {
+        evshed_set_index(pUsbCore->usbc_es_wk_notify_g, USBC_WK_NOTIFY_INDEX);
+    } else {
+        ASSERT(0);
+    }
+
+    usbc_normal_hif_factory();      
+    
+#if defined(__HIF_USB_ENUM_PORT_FOR_AP__) && defined(__HIF_CCCI_SUPPORT__)
+    dual_owner_funciton_register();
+#endif
+    if(usbc_dual_owner_init != NULL)
+        usbc_dual_owner_init();
+
+    usbc_stack_checkin(USB_CLASS_NUM, NULL);
+    return KAL_TRUE;
+}
+
+
+static kal_bool usbc_core_task_reset(void)
+{
+    usbc_core_printf("=========>usbcore_task_reset\r\n");
+    usbc_trace_info(USBCORE_TASK_RESET);
+
+    /* Do task's reset here.
+     * Notice that: shouldn't execute modules reset handler since
+     * stack_task_reset() will do. */
+    return KAL_TRUE;
+}
+
+#ifdef __MODIS_USB_TAP_ACCESS__
+extern kal_bool uta_usbcore_task_init(void);
+extern void uta_usbcore_task_main(task_entry_struct*);
+#endif
+
+extern void usbc_stack_reset(); /* Simply reset USB stack before task init, so, no need to be public. */
+
+kal_bool usbc_core_create(comptask_handler_struct **handle)
+{
+    static const comptask_handler_struct usbc_core_handler_info =
+    {
+#if defined(__ESL_COSIM_HIF__)
+        usbc_cosim_core_task_main,  /* task entry function for ESL COSIM */
+        usbc_cosim_core_task_init,  /* task initialization function for ESL_COSIM */
+#elif defined(__MODIS_USB_TAP_ACCESS__)
+        uta_usbcore_task_main,      /* task entry function for MoDIS TAP Access */
+        uta_usbcore_task_init,      /* task initialization function for MoDIS TAP Access */
+#else
+        usbc_core_task_main,        /* task entry function */
+        usbc_core_task_init,        /* task initialization function */
+#endif
+        usbc_core_task_reset        /* task reset handler */
+    };
+
+    usbc_core_printf("=========>usbcore_create\r\n");
+    usbc_trace_info(USBCORE_TASK_CREATE);
+
+    *handle = (comptask_handler_struct *)&usbc_core_handler_info;
+
+    usbc_stack_reset();
+    return KAL_TRUE;
+}
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_ut.c b/mcu/middleware/hif/usbcore/src/usbcore_ut.c
new file mode 100644
index 0000000..d5a1b04
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_ut.c
@@ -0,0 +1,871 @@
+//#include "kal_release.h"
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "task_config.h"
+//#include "kal_debug.h"
+#include "sys_test.h"
+#include "usbcore_main.h"
+#include "usbcore_hif.h"
+#include "usbcore_common.h"
+#include "usbcore_ind_q.h"
+#include "hifusb_qmu.h"
+#include "hmu.h"
+#include "usbcore_ut.h"
+
+/****************************************************************************
+                Macro Declaration
+ ***************************************************************************/
+#define ST_MOD_NAME     "USBCORE"
+
+/****************************************************************************
+               Global Variables
+***************************************************************************/
+static usbc_ut_fake_class_func_info_t fake_class_func;
+
+hifusb_setup_packet_t getDevStatusPkt =
+{
+    0x80,   // bmRequestType
+    0x00,   // bRequest
+    0x00,   // wValue
+    0x00,   // wIndex
+    0x02,   // wLength
+};
+
+hifusb_setup_packet_t getNon1stInfxStatusPkt =
+{
+    0x81,   // bmRequestType
+    0x00,   // bRequest
+    0x00,   // wValue
+    0x01,   // wIndex
+    0x02,   // wLength
+};
+
+hifusb_setup_packet_t get1stInfxStatusPkt =
+{
+    0x81,   // bmRequestType
+    0x00,   // bRequest
+    0x00,   // wValue
+    0x00,   // wIndex
+    0x02,   // wLength
+};
+
+hifusb_setup_packet_t setDevFeatureRemoteWkPkt =
+{
+    0x00,   // bmRequestType
+    0x03,   // bRequest
+    0x01,   // wValue
+    0x00,   // wIndex
+    0x00,   // wLength
+};
+
+hifusb_setup_packet_t setDevFeatureU1Pkt =
+{
+    0x00,   // bmRequestType
+    0x03,   // bRequest
+    0x30,   // wValue
+    0x00,   // wIndex
+    0x00,   // wLength
+};
+
+hifusb_setup_packet_t setDevFeatureU2Pkt =
+{
+    0x00,   // bmRequestType
+    0x03,   // bRequest
+    0x31,   // wValue
+    0x00,   // wIndex
+    0x00,   // wLength
+};
+
+hifusb_setup_packet_t setDevFeatureLtmPkt =
+{
+    0x00,   // bmRequestType
+    0x03,   // bReques: set featuret
+    0x32,   // wValue: feature selector LTM_ENABLE
+    0x00,   // wIndex
+    0x00,   // wLength
+};
+
+hifusb_setup_packet_t setInfxFeatureWkPkt =
+{
+    0x01,   // bmRequestType
+    0x03,   // bRequest: set feature
+    0x00,   // wValue: function suspend feature selector
+    0x0200,   // wIndex: suspend option + nInterface 
+    0x00,
+};
+
+hifusb_setup_packet_t setInfxFeatureSuspendPkt =
+{
+    0x01,   // bmRequestType
+    0x03,   // bRequest: set feature
+    0x00,   // wValue: function suspend feature selector
+    0x0300,   // wIndex: suspend option + nInterface
+    0x00,
+};
+
+hifusb_setup_packet_t setInfxFeatureResumePkt =
+{
+    0x01,   // bmRequestType
+    0x03,   // bRequest: set feature
+    0x00,   // wValue: function suspend feature selector
+    0x00,   // wIndex: suspend option + nInterface
+    0x00,
+};
+
+hifusb_setup_packet_t clsDevFeatureRemoteWkPkt =
+{
+    0x00,   // bmRequestType
+    0x01,   // bRequest
+    0x01,   // wValue
+    0x00,   // wIndex
+    0x00,   // wLength
+};
+
+hifusb_setup_packet_t clsDevFeatureU1Pkt =
+{
+    0x00,   // bmRequestType
+    0x01,   // bRequest
+    0x30,   // wValue
+    0x00,   // wIndex
+    0x00,   // wLength
+};
+
+hifusb_setup_packet_t clsDevFeatureU2Pkt =
+{
+    0x00,   // bmRequestType
+    0x01,   // bRequest
+    0x31,   // wValue
+    0x00,   // wIndex
+    0x00,   // wLength
+};
+
+hifusb_setup_packet_t clsDevFeatureLtmPkt =
+{
+    0x00,   // bmRequestType
+    0x01,   // bRequest
+    0x32,   // wValue
+    0x00,   // wIndex
+    0x00,   // wLength
+};
+
+hifusb_setup_packet_t clsInfxFeatureWkPkt =
+{
+    0x01,   // bmRequestType
+    0x01,   // bRequest: clear feature
+    0x00,   // wValue: function suspend feature selector
+    0x00,   // wIndex: nInterface
+    0x00,   // wLength
+};
+
+/****************************************************************************
+               Private Function
+***************************************************************************/
+static void usbc_ut_std_req(void *p_param)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    
+    // set control setup packet
+    usbc_core_dispatch_control_setup_packet(pUsbCore, p_param);
+}
+
+static kal_uint16 usbc_ut_get_status(void *p_param)
+{
+    usbc_core_t* pUsbCore;
+    kal_uint16* pStatus;
+
+    usbc_ut_std_req(p_param);
+
+    pUsbCore = usbc_core_get_instance();
+    pStatus = (kal_uint16*)pUsbCore->control_request_buffer;
+
+    return *pStatus;
+}
+
+
+/****************************************************************************
+               Public Fake Function
+***************************************************************************/
+kal_uint16 usbc_ut_fake_query_func_wk_status(kal_uint8 class_device_id)
+{
+    return fake_class_func.infx_status;
+}
+
+void usbc_ut_fake_notify_func_wk_ability(kal_uint8 class_device_id, kal_bool ability)
+{
+    if (ability)
+    {
+        fake_class_func.infx_status |= 0x0002;
+    }
+    else
+    {
+        fake_class_func.infx_status &= 0xFFFD;
+    }
+}
+
+kal_bool usbc_ut_fake_notify_retry(kal_uint8 nInterface)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 class_device_id = 0;
+
+    fake_class_func.nRetry++;
+    if( fake_class_func.nRetry >= 5)
+    {
+        pUsbCore->is_func_be_accessed[class_device_id] = KAL_TRUE;
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool usbc_ut_fake_hif_remote_wakeup()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 class_device_id = pUsbCore->class_interface[0].class_device_id;
+    kal_uint16 status;
+    usbc_usb_state_e    dev_state;
+    usbc_ind_t          ind_to_enqueue;
+
+    // device resume
+    dev_state = USBC_USB_STATE_RESUME;
+    ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+    ind_to_enqueue.ext = 0;
+    ind_to_enqueue.data = (kal_uint8)dev_state;
+    usbc_enqueue_ind(&ind_to_enqueue);
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+
+    return KAL_TRUE;
+}
+
+kal_bool usbc_ut_fake_set_control_request(kal_uint8 *buffer, kal_uint32 length, usbc_control_request_type_e type)
+{
+    return KAL_TRUE;
+}
+/****************************************************************************
+                Test Function
+ ***************************************************************************/
+kal_bool
+usbc_ut_is_dev_attached(void *p_parm,
+           kal_char *p_ret_err_str,
+           kal_uint32 *p_ret_err_str_sz)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+	usbc_fake_hif_factory();
+
+    return KAL_TRUE;
+}
+
+kal_bool
+usbc_ut_check_1st_infx(void *p_param,
+           kal_char *p_ret_err_str,
+           kal_uint32 *p_ret_err_str_sz)
+{
+    kal_uint8 total_interface_number;
+    kal_bool ans[6] = {KAL_TRUE, KAL_FALSE, KAL_TRUE, KAL_FALSE, KAL_TRUE, KAL_FALSE};
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    kal_uint8 i;
+    kal_bool isFirstInfx;
+
+    if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+    {
+        total_interface_number = 6;
+    }
+    else
+    {
+        total_interface_number = 3;
+    }
+
+    for( i=0; i<total_interface_number; i++)
+    {
+        isFirstInfx = usbc_core_is_1st_interface(i);
+        if (isFirstInfx != ans[i])
+        {
+            return KAL_FALSE;
+        }
+    }
+    
+    return KAL_TRUE;
+}
+
+kal_bool
+usbc_ut_get_1st_infx(void *p_param,
+           kal_char *p_ret_err_str,
+           kal_uint32 *p_ret_err_str_sz)
+{
+    // set test parameters
+    kal_uint8 total_dev_num = 3;
+    kal_uint8 ans[3] = {0, 2, 4};
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    kal_uint8 i;
+    kal_uint8 nFirstInfx;
+
+    for( i=0; i<total_dev_num; i++)
+    {
+        nFirstInfx = usbc_class_device_get_1st_interface(i);
+        if (nFirstInfx != ans[i])
+        {
+            return KAL_FALSE;
+        }
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool
+usbc_ut_set_dev_feature(void *p_parm,
+        kal_char *p_ret_err_str,
+        kal_uint32 *p_ret_err_st_ss)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint16 status = usbc_ut_get_status(&getDevStatusPkt);
+
+    if( 0x0000 != (status & 0xFFFE))
+    {
+        return KAL_FALSE;
+    }
+
+    if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+    {
+        // set LTM enable
+        usbc_ut_std_req(&setDevFeatureLtmPkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x0010 != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        }    
+
+        // set U2 enable
+        usbc_ut_std_req(&setDevFeatureU2Pkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x0018 != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        }
+
+        // set U1 enable
+        usbc_ut_std_req(&setDevFeatureU1Pkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x001C != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        }
+
+        // clear U1 enable
+        usbc_ut_std_req(&clsDevFeatureU1Pkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x0018 != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        }
+
+        // clear U2 enable
+        usbc_ut_std_req(&clsDevFeatureU2Pkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x0010 != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        }
+
+        // clear LTM enable
+        usbc_ut_std_req(&clsDevFeatureLtmPkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x0000 != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        }
+    }
+    else
+    {
+        // set remote wakeup
+        usbc_ut_std_req(&setDevFeatureRemoteWkPkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x0002 != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        }
+
+        // clear remote wakeup
+        usbc_ut_std_req(&clsDevFeatureRemoteWkPkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x0000 != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        } 
+    }
+
+    return KAL_TRUE;
+}
+
+
+kal_bool
+usbc_ut_set_infx_feature(void *p_parm,
+        kal_char *p_ret_err_str,
+        kal_uint32 *p_ret_err_st_ss)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint16 status;
+
+    // non 1st interface of any function, the reported status is 0
+    status = usbc_ut_get_status(&getNon1stInfxStatusPkt);
+    if( 0x0000 != (status & 0xFFFF))
+    {
+        return KAL_FALSE;
+    }
+
+    status = usbc_ut_get_status(&get1stInfxStatusPkt);
+    // 1st interface of a super-speed function
+    if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+    {
+        if ( 0x0001 != (status & 0xFFFF))
+        {
+            return KAL_FALSE;
+        }
+    }
+    //  1st interface of a non super-speed function
+    else
+    {
+        if( 0x0000 != (status & 0xFFFF))
+        {
+            return KAL_FALSE;
+        }
+    }
+
+    if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+    {
+        // set feature to enable function remote wakeup
+        usbc_ut_std_req(&setInfxFeatureWkPkt);
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( 0x0003 != (status & 0xFFFF))
+        {
+            return KAL_FALSE;
+        }
+
+        // clear feature to disable function remote wakeup
+        usbc_ut_std_req(&clsInfxFeatureWkPkt); 
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( 0x0001 != (status & 0xFFFF))
+        {
+            return KAL_FALSE;
+        }
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool
+usbc_ut_func_suspend_resume(void *p_parm,
+        kal_char *p_ret_err_str,
+        kal_uint32 *p_ret_err_st_ss)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 class_device_id = pUsbCore->class_interface[0].class_device_id;
+    kal_uint16 status;
+
+    // function suspend is supported in super-speed device only
+    if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+    {
+        // set feature to enable function remote wakeup and set function to suspend
+        usbc_ut_std_req(&setInfxFeatureSuspendPkt);
+        while( !pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( !pUsbCore->class_device[class_device_id].is_func_suspend ||
+             0x0003 != (status & 0xFFFF) )
+        {
+            return KAL_FALSE;
+        }
+        // set feature to disable function remote wakeu and resume function
+        usbc_ut_std_req(&setInfxFeatureResumePkt);
+        while( pUsbCore->class_device[class_device_id].is_func_suspend)
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( pUsbCore->class_device[class_device_id].is_func_suspend ||
+             0x0001 != (status & 0xFFFF) )
+        {
+            return KAL_FALSE;
+        }
+
+        // set feature to enable function remote wakeup and set function to suspend
+        usbc_ut_std_req(&setInfxFeatureSuspendPkt);
+        while( !pUsbCore->class_device[class_device_id].is_func_suspend)
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( !pUsbCore->class_device[class_device_id].is_func_suspend ||
+             0x0003 != (status & 0xFFFF) )
+        {
+            return KAL_FALSE;
+        }
+        // clear feature to disable function remote wakeu and resume function
+        usbc_ut_std_req(&clsInfxFeatureWkPkt);
+        while( pUsbCore->class_device[class_device_id].is_func_suspend)
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( pUsbCore->class_device[class_device_id].is_func_suspend ||
+             0x0001 != (status & 0xFFFF) )
+        {
+            return KAL_FALSE;
+        }
+    }
+
+    return KAL_TRUE;   
+}
+
+kal_bool
+usbc_ut_func_suspend_remote_wk(void *p_parm,
+        kal_char *p_ret_err_str,
+        kal_uint32 *p_ret_err_st_ss)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 class_device_id = pUsbCore->class_interface[0].class_device_id;
+    kal_uint16 status;
+    fake_class_func.nRetry = 0;
+
+    // function suspend is supported in super-speed device only
+    if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+    {
+        // set feature to enable function remote wakeup and set function to suspend
+        usbc_ut_std_req(&setInfxFeatureSuspendPkt);
+        while( !pUsbCore->class_device[class_device_id].is_func_suspend)
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( !pUsbCore->class_device[class_device_id].is_func_suspend ||
+             0x0003 != (status & 0xFFFF) )
+        {
+            return KAL_FALSE;
+        }
+        // remote wakeup to resume the function
+        usbc_class_device_func_remote_wk(class_device_id);
+        while( pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( pUsbCore->class_device[class_device_id].is_func_suspend ||
+             0x0003 != (status & 0xFFFF) )
+        {
+            return KAL_FALSE;
+        }
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool
+usbc_ut_dev_suspend_resume(void *p_parm,
+        kal_char *p_ret_err_str,
+        kal_uint32 *p_ret_err_st_ss)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 class_device_id = pUsbCore->class_interface[0].class_device_id;
+    kal_uint16 status;
+    usbc_usb_state_e    dev_state;
+    usbc_ind_t          ind_to_enqueue;
+
+
+    /* test for USB non super-speed devices and supoer-speed devices without function suspend */
+    // device suspend
+    dev_state = USBC_USB_STATE_SUSPENDING;
+    ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+    ind_to_enqueue.ext = 0;
+    ind_to_enqueue.data = (kal_uint8)dev_state;
+    usbc_enqueue_ind(&ind_to_enqueue);
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+    while ( USBC_USB_STATE_SUSPENDED!= pUsbCore->state )
+    {
+        kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+    }
+    if ( pUsbCore->class_device[class_device_id].is_func_suspend )
+    {
+       return KAL_FALSE;
+    }
+
+    // device resume
+    dev_state = USBC_USB_STATE_RESUME;
+    ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+    ind_to_enqueue.ext = 0;
+    ind_to_enqueue.data = (kal_uint8)dev_state;
+    usbc_enqueue_ind(&ind_to_enqueue);
+    hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+    while ( USBC_USB_STATE_RESUME != pUsbCore->state )
+    {
+        kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+    }
+    if ( pUsbCore->class_device[class_device_id].is_func_suspend )
+    {
+        return KAL_FALSE;
+    }
+
+    // test for USB super-speed device with function suspend
+    if ( pUsbCore->speed == USBC_USB_SPEED_USB30 )
+    {
+        // set function to be suspended
+        usbc_ut_std_req(&setInfxFeatureSuspendPkt);
+        if ( !pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+            return KAL_FALSE;
+        }
+
+        // device suspend
+        dev_state = USBC_USB_STATE_SUSPENDING;
+        ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+        ind_to_enqueue.ext = 0;
+        ind_to_enqueue.data = (kal_uint8)dev_state;
+        usbc_enqueue_ind(&ind_to_enqueue);
+        hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+        while ( USBC_USB_STATE_SUSPENDED != pUsbCore->state )
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        if ( !pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+            return KAL_FALSE;
+        }
+
+        // device resume
+        dev_state = USBC_USB_STATE_RESUME;
+        ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+        ind_to_enqueue.ext = 0;
+        ind_to_enqueue.data = (kal_uint8)dev_state;
+        usbc_enqueue_ind(&ind_to_enqueue);
+        hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+        while ( USBC_USB_STATE_RESUME != pUsbCore->state )
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        if ( !pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+            return KAL_FALSE;
+        }
+
+        // set the function to be resumed
+        usbc_ut_std_req(&setInfxFeatureResumePkt);
+        if ( pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+            return KAL_FALSE;
+        }
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool
+usbc_ut_dev_suspend_remote_wk(void *p_parm,
+        kal_char *p_ret_err_str,
+        kal_uint32 *p_ret_err_st_ss)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 class_device_id = pUsbCore->class_interface[0].class_device_id;
+    kal_uint16 status;
+    usbc_usb_state_e    dev_state;
+    usbc_ind_t          ind_to_enqueue;
+
+    // for non super-speed device, use device remote wakeup
+    if ( pUsbCore->speed != USBC_USB_SPEED_USB30 )
+    {
+        // set feature to enable device remote wakeup
+        usbc_ut_std_req(&setDevFeatureRemoteWkPkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x0002 != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        }
+
+        // device suspend
+        dev_state = USBC_USB_STATE_SUSPENDING;
+        ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+        ind_to_enqueue.ext = 0;
+        ind_to_enqueue.data = (kal_uint8)dev_state;
+        usbc_enqueue_ind(&ind_to_enqueue);
+        hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+        while ( USBC_USB_STATE_SUSPENDED!= pUsbCore->state )
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        if ( pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+           return KAL_FALSE;
+        }
+
+        // device remote wakeup
+        usbc_class_device_func_remote_wk(class_device_id);
+        while ( USBC_USB_STATE_RESUME != pUsbCore->state )
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        if ( pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+            return KAL_FALSE;
+        }
+
+        // clear remote wakeup
+        usbc_ut_std_req(&clsDevFeatureRemoteWkPkt);
+        status = usbc_ut_get_status(&getDevStatusPkt);
+        if( 0x0000 != (status & 0xFFFE))
+        {
+            return KAL_FALSE;
+        }
+    }
+    else
+    {
+        // set feature to enable function remote wakeup and set function to suspend
+        usbc_ut_std_req(&setInfxFeatureSuspendPkt);
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( !pUsbCore->class_device[class_device_id].is_func_suspend ||
+             0x0003 != (status & 0xFFFF) )
+        {
+            return KAL_FALSE;
+        }
+
+        // device suspend
+        dev_state = USBC_USB_STATE_SUSPENDING;
+        ind_to_enqueue.type = USBC_IND_DEV_EVENT;
+        ind_to_enqueue.ext = 0;
+        ind_to_enqueue.data = (kal_uint8)dev_state;
+        usbc_enqueue_ind(&ind_to_enqueue);
+        hmu_hifeg_set(HIF_DRV_EG_USBC_IND_EVENT);
+        while ( USBC_USB_STATE_SUSPENDED!= pUsbCore->state )
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        if ( !pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+           return KAL_FALSE;
+        }
+
+        // device resume and function remote wakeup
+        usbc_class_device_func_remote_wk(class_device_id);
+        while ( USBC_USB_STATE_RESUME != pUsbCore->state  ||
+                pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+            kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+        }
+        if ( pUsbCore->class_device[class_device_id].is_func_suspend )
+        {
+            return KAL_FALSE;
+        }
+
+        // clear feature to disable function remote wakeup
+        usbc_ut_std_req(&clsInfxFeatureWkPkt);
+        status = usbc_ut_get_status(&get1stInfxStatusPkt);
+        if ( 0x0001 != (status & 0xFFFF))
+        {
+            return KAL_FALSE;
+        }
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool
+usbc_ut_notification_timeout(void *p_parm,
+        kal_char *p_ret_err_str,
+        kal_uint32 *p_ret_err_st_ss)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 class_device_id = 0;
+    fake_class_func.nRetry = 0;
+
+    usbc_set_wk_notify_timer((class_device_id));
+    while ( !pUsbCore->is_func_be_accessed[class_device_id] )
+    {
+        kal_sleep_task(USBC_UT_BLOCK_TICK_T);
+    }
+
+    if( fake_class_func.nRetry >=5 )
+    {
+        return KAL_TRUE;
+    }
+    else
+    {
+        return KAL_FALSE;
+    }
+}
+
+//#define  ERR_STR   "This is a sample error case"
+//kal_bool
+//usbc_ut_get_1st_infx(void *p_param,
+//           kal_char *p_ret_err_str,
+//           kal_uint32 *p_ret_err_str_sz)
+//{
+    /* Test case is FAILED */
+//    strncpy(p_ret_err_str, ERR_STR, MIN(strlen(ERR_STR), *p_ret_err_str_sz));
+//    *p_ret_err_str_sz = MIN(strlen(ERR_STR), *p_ret_err_str_sz);
+
+//    return KAL_FALSE;
+//}
+
+
+/****************************************************************************
+                USBCORE Task Init Function
+ ***************************************************************************/
+
+ST_TCASE_T st_tcase_g[] = {
+    { "Check the attachment of the device",
+      usbc_ut_is_dev_attached,
+      NULL
+    },
+   { "Check 1st interface", 
+       usbc_ut_check_1st_infx, 
+       NULL
+    },
+    { "Get 1st interface", 
+       usbc_ut_get_1st_infx, 
+       NULL 
+    },
+    { "Set/clear features of device", 
+      usbc_ut_set_dev_feature,
+      NULL
+    },
+    { "Set/clear feature of interface",
+      usbc_ut_set_infx_feature,
+      NULL
+    },
+    { "Function wakeup notification timeout and retry",
+      usbc_ut_notification_timeout,
+      NULL
+    },
+    { "Function suspend and resume by host",
+      usbc_ut_func_suspend_resume,
+      NULL
+    },
+    { "Function suspend and remote wakeup by class devices",
+      usbc_ut_func_suspend_remote_wk,
+      NULL
+    },
+    { "Device suspend and resume by host",
+      usbc_ut_dev_suspend_resume,
+      NULL
+    },
+    { "Device suspend and remote wakeup by class devices",
+      usbc_ut_dev_suspend_remote_wk,
+      NULL
+    }
+};
+
+kal_uint32 st_tcase_count_g = sizeof(st_tcase_g) / sizeof(ST_TCASE_T);
+
+kal_bool usbcore_ut_st_create (void)
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+
+    // set fefault fake class device value
+    fake_class_func.infx_status = 0x0001;
+    fake_class_func.nRetry = 0;
+
+    pUsbCore->speed = USBC_USB_SPEED_USB30;
+
+      return st_reg_test(ST_MOD_NAME,  /* p_mod_name */
+                     st_tcase_g, /* p_tcase */
+                     st_tcase_count_g /* tcase_num */
+           );
+}
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_ut_except.c b/mcu/middleware/hif/usbcore/src/usbcore_ut_except.c
new file mode 100644
index 0000000..ce60403
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_ut_except.c
@@ -0,0 +1,129 @@
+#include "kal_public_api.h"
+#include "intrCtrl.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+
+#include "usbcore_except.h"
+
+static usbc_class_device_info_t         dev_info_s;
+static usbc_class_device_instance_t    *dev_inst_s = NULL;
+static kal_uint8                        ct_data_buf[2048];
+
+#define MIN(_a, _b) (((_a) <= (_b)) ? (_a) : (_b))
+
+void usbc_at_notify_usb_state(kal_uint8 class_device_id, usbc_usb_state_e state)
+{
+    ASSERT(0);
+}
+
+void usbc_at_notify_usb_speed(kal_uint8 class_device_id, usbc_usb_speed_e speed)
+{
+    ASSERT(dev_inst_s);
+    ASSERT(class_device_id == dev_inst_s->id);
+}
+
+void usbc_at_notify_control_setup_packet(kal_uint8 class_device_id, usbc_setup_packet_t *packet)
+{
+    kal_bool    result;
+    
+    ASSERT(dev_inst_s);
+    ASSERT(class_device_id == dev_inst_s->id);  
+
+    if (packet->bmRequestType & 0x80) { // IN
+        ASSERT(packet->wLength > 0);
+        result = usbc_class_device_submit_control_request(
+                class_device_id, /* kal_uint8 class_device_id */
+                NULL, /* kal_uint8 *buffer */
+                0, /* kal_uint32 length */
+                USBC_CONTROL_REQUEST_TYPE_SEND); /* usbc_control_request_type_e */
+    } else { // OUT
+        result = usbc_class_device_submit_control_request(
+                class_device_id, /* kal_uint8 class_device_id */
+                ct_data_buf, /* kal_uint8 *buffer */
+                MIN(packet->wLength, sizeof(ct_data_buf)), /* kal_uint32 length */
+                USBC_CONTROL_REQUEST_TYPE_RECEIVE); /* usbc_control_request_type_e */
+    }
+    ASSERT(result);
+}
+
+void usbc_at_notify_control_complete(kal_uint8 class_device_id)
+{
+    ASSERT(dev_inst_s);
+    ASSERT(class_device_id == dev_inst_s->id);  
+    return; 
+}
+
+void usbc_at_exception(void)
+{
+    static kal_uint32   cnt = 0;
+    kal_uint32     mask; 
+    kal_uint32     num_gpd;
+    void          *head_gpd;
+    void          *tail_gpd;
+    void          *rx_gpd;
+    void          *next_gpd;
+    usbc_except_link_st_e   link_state;
+
+    if (cnt++ < 5000) {
+        return;
+    }
+
+    ASSERT(2 == qbmt_alloc_q_no_tail(QBM_TYPE_HIF_DL, 2, &head_gpd, &tail_gpd));
+    for (rx_gpd = head_gpd; rx_gpd; rx_gpd = next_gpd) {
+        next_gpd = QBM_DES_GET_NEXT(rx_gpd);
+
+        QBM_DES_SET_ALLOW_LEN(rx_gpd, 512);
+        qbm_cal_set_checksum((kal_uint8*)rx_gpd);
+        QBM_CACHE_FLUSH(rx_gpd, sizeof(qbm_gpd));
+        rx_gpd = QBM_DES_GET_NEXT(rx_gpd);
+
+        if (rx_gpd == tail_gpd) break;
+    }
+
+    mask = SaveAndSetIRQMask();
+
+    dev_info_s.class_type = USBC_CLASS_TYPE_CDC_ACM;
+    dev_info_s.total_pipes = 3;
+    dev_info_s.pipe_type[0] = USBC_PIPE_TYPE_CDC_ACM_COMM_IN;
+    dev_info_s.pipe_type[1] = USBC_PIPE_TYPE_CDC_ACM_DATA_IN;
+    dev_info_s.pipe_type[2] = USBC_PIPE_TYPE_CDC_ACM_DATA_OUT;
+    dev_info_s.notify_usb_state = usbc_at_notify_usb_state;
+    dev_info_s.notify_usb_speed = usbc_at_notify_usb_speed;
+    dev_info_s.notify_control_setup_packet = usbc_at_notify_control_setup_packet;
+    dev_info_s.notify_control_complete = usbc_at_notify_control_complete;
+    dev_info_s.notify_alternate_setting = NULL;
+    dev_info_s.notify_pipe_complete[0] = NULL;
+    dev_info_s.notify_pipe_complete[1] = NULL;
+    dev_info_s.notify_pipe_complete[2] = NULL;
+    dev_info_s.notify_pipe_stall[0] = NULL;
+    dev_info_s.notify_pipe_stall[1] = NULL;
+    dev_info_s.notify_pipe_stall[2] = NULL;
+
+    dev_inst_s = usbc_except_reset_ch(&dev_info_s);
+    ASSERT(dev_inst_s);
+    ASSERT(usbc_except_enum_loop());
+
+    ASSERT(usbc_except_init());
+    ASSERT(usbc_except_submit_gpd(dev_inst_s->id, dev_inst_s->queue_no_for_pipe[1], head_gpd, tail_gpd));
+
+    do {
+        usbc_except_hif_poll(dev_inst_s->id);
+
+        ASSERT(usbc_except_poll_queue(dev_inst_s->id, dev_inst_s->queue_no_for_pipe[1], &head_gpd, &tail_gpd, &num_gpd));
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+        ASSERT(usbc_except_hif_state(dev_inst_s->id, dev_inst_s->queue_no_for_pipe[1], &link_state));
+#if 0
+/* under construction !*/
+#endif
+
+    } while(1);
+
+    RestoreIRQMask(mask);
+}
diff --git a/mcu/middleware/hif/usbcore/src/usbcore_vendreq.c b/mcu/middleware/hif/usbcore/src/usbcore_vendreq.c
new file mode 100644
index 0000000..92aeb15
--- /dev/null
+++ b/mcu/middleware/hif/usbcore/src/usbcore_vendreq.c
@@ -0,0 +1,209 @@
+/*!
+ *  @file usbcore_usbstd.c
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides usb standard request handler function
+ */
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "usbcore_common.h"
+#include "usbcore_usbstd.h"
+#include "usbcore_main.h"
+#include "usbcore_hif.h"
+#ifdef __USB_OSD_SUPPORT__
+#include "usbosd.h"
+#endif /* __USB_OSD_SUPPORT__ */
+
+
+#define MIN(_a, _b) (((_a) <= (_b)) ? (_a) : (_b))
+
+/*
+ *  Define Microsoft OS feature descriptor
+ */
+#define USBC_FEATURE_EXT_COMPAT_ID          0x0004
+#define USBC_MAX_OS_FEATURE_DESC_LENGTH     40
+static usbc_ext_compat_id_os_feature_descriptor_t usbc_os_descriptor =
+{
+    USBC_MAX_OS_FEATURE_DESC_LENGTH,                     /* dwLength */
+    0x0100,                                              /* bcdVersion */
+    USBC_FEATURE_EXT_COMPAT_ID,                          /* wIndex */
+    0x01,                                                /* bCount */
+    {0,0,0,0,0,0,0},                                     /* bPads_1 */
+    0x00,                                                /* bFirstInterfaceNumber */
+    0x01,                                                /* bInterfaceCount */
+    {0x41, 0x4C, 0x54, 0x52, 0x43, 0x46, 0x47, 0x00},    /* compatibleID (ALTRCFG) */
+    {0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},    /* subcompatibleID (default:2) */
+    {0,0,0,0,0,0}                                        /* bPads_2 */
+};
+
+#ifdef __USB_OSD_SUPPORT__
+static usbc_ext_compat_id_os_feature_descriptor_t usbc_mod_str_descriptor =
+{
+    USBC_MAX_OS_FEATURE_DESC_LENGTH,                     /* dwLength */
+    0x0100,                                              /* bcdVersion */
+    USBC_FEATURE_EXT_COMPAT_ID,                          /* wIndex */
+    0x01,                                                /* bCount */
+    {0,0,0,0,0,0,0},                                     /* bPads_1 */
+    0x00,                                                /* bFirstInterfaceNumber */
+    0x01,                                                /* bInterfaceCount */
+    {0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00},    /* compatibleID (WINUSB) */
+    {0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},    /* subcompatibleID (default:2) */
+    {0,0,0,0,0,0}                                        /* bPads_2 */
+};
+#endif
+
+static void usbc_core_handle_get_ms_descriptor()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 bRecip = pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK;
+    kal_uint16 wValue = pUsbCore->setup_packet.wValue;
+    kal_uint16 wIndex = pUsbCore->setup_packet.wIndex;
+    kal_uint16 wLength = pUsbCore->setup_packet.wLength;
+    kal_uint8* pBuffer = NULL;
+    kal_uint32 length = 0;
+
+	if ( bRecip == USBC_REQUEST_RECIP_DEVICE &&
+         pUsbCore->morphing_enable   )
+	{
+	    if (wValue == 0x00 && wIndex == USBC_FEATURE_EXT_COMPAT_ID)
+	    {
+	        /* Morphing device must not report the compatible and subcompatible ID after a configuration is selected */
+	        if (pUsbCore->state == USBC_USB_STATE_ATTACHED) {
+	            usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+	            return;
+	        }
+	        pUsbCore->morph_active = KAL_TRUE;
+            if (pUsbCore->dev_param->morphing_sub_id >= 2 && pUsbCore->dev_param->morphing_sub_id <= 4)
+            {   /*
+                 *  0x32 -> '2',   0x33 -> '3',   0x34 -> '4'
+                 */
+                usbc_os_descriptor.subcompatibleID[0] = 0x30 + pUsbCore->dev_param->morphing_sub_id;
+            }
+
+            length = MIN(USBC_MAX_OS_FEATURE_DESC_LENGTH, wLength);
+            pBuffer = (kal_uint8*)&usbc_os_descriptor;
+	        usbc_core_set_control_request(pBuffer, length, USBC_CONTROL_REQUEST_TYPE_SEND);
+	    }
+	} else
+	{
+	    usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+	}
+}
+
+#ifdef __USB_OSD_SUPPORT__
+/* Debug for Win8 U3 enumeration failed issue */
+static void usbc_core_handle_get_mod_str_descriptor()
+{
+    usbc_core_t* pUsbCore = usbc_core_get_instance();
+    kal_uint8 bRecip = pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK;
+    kal_uint16 wValue = pUsbCore->setup_packet.wValue;
+    kal_uint16 wIndex = pUsbCore->setup_packet.wIndex;
+    kal_uint16 wLength = pUsbCore->setup_packet.wLength;
+    kal_uint8* pBuffer = NULL;
+    kal_uint32 length = 0;
+
+	if ( bRecip == USBC_REQUEST_RECIP_DEVICE )
+	{
+	    if (wValue == 0x00 && wIndex == USBC_FEATURE_EXT_COMPAT_ID)
+	    {
+
+            length = MIN(USBC_MAX_OS_FEATURE_DESC_LENGTH, wLength);
+            pBuffer = (kal_uint8*)&usbc_mod_str_descriptor;
+	        usbc_core_set_control_request(pBuffer, length, USBC_CONTROL_REQUEST_TYPE_SEND);
+	    }
+	} else
+	{
+	    usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+	}
+}
+#endif
+
+void usbc_core_handle_vendor_request()
+{
+    static struct _usbc_request_entry {
+        kal_uint32          request;
+        void                (*request_handler)();
+    } request_entry_table[] = {
+        {USBC_REQ_GET_MS_DESCRIPTOR,    usbc_core_handle_get_ms_descriptor},
+#ifdef __USB_OSD_SUPPORT__
+        {VENDOR_CODE_1,    usbc_core_handle_get_mod_str_descriptor},
+        {VENDOR_CODE_2,    usbc_core_handle_get_mod_str_descriptor},
+#endif
+    };
+
+    kal_uint32      request_entry_table_num = sizeof(request_entry_table)/sizeof(struct _usbc_request_entry);
+    usbc_core_t    *pUsbCore = usbc_core_get_instance();
+    kal_uint32      idx;
+    kal_uint8       bInterface;
+
+    for (idx = 0; idx < request_entry_table_num; idx++) {
+        if (pUsbCore->setup_packet.bRequest == request_entry_table[idx].request) break;
+    }
+
+    if (idx < request_entry_table_num)
+    {
+        request_entry_table[idx].request_handler();
+    } else
+    {   /* If request handler can't be found, search all interface and notify class driver if existed */
+        if ((pUsbCore->setup_packet.bmRequestType & USBC_REQUEST_RECIP_MASK) == USBC_REQUEST_RECIP_INTERFACE)
+        {
+            kal_uint8 i;
+            bInterface = pUsbCore->setup_packet.wIndex & 0xff;
+
+            /* notify class driver by interface if exist */
+            for ( i=0 ; i< pUsbCore->total_class_interfaces; i++ ) {
+                if ( (pUsbCore->class_interface[i].interface_no == bInterface) &&
+                    (pUsbCore->class_interface[i].state == USBC_CORE_CLASS_INTERFACE_STATE_ACTIVE) &&
+                    (pUsbCore->class_interface[i].notify_control_setup_packet != NULL)) {
+                    break;
+                }
+            }
+
+            if ( i == pUsbCore->total_class_interfaces ) {
+                /* incorrect request */
+                usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+            } else {
+                usbc_core_indicate_control_setup_packet(i, &pUsbCore->setup_packet);
+            }
+        } else
+        {   // not support
+            usbc_core_set_control_request(NULL, 0, HIFUSB_CONTROL_REQUEST_TYPE_STALL);
+        }
+    }
+}
+
+
diff --git a/mcu/middleware/hif/usbidle/include/usbidle_hif.h b/mcu/middleware/hif/usbidle/include/usbidle_hif.h
new file mode 100644
index 0000000..a837730
--- /dev/null
+++ b/mcu/middleware/hif/usbidle/include/usbidle_hif.h
@@ -0,0 +1,47 @@
+/*!
+ *  @file usbidle_main.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main definitions of usbcore
+ */
+
+#ifndef _USBIDLE_HIF_H
+#define _USBIDLE_HIF_H
+
+void usb_idle_suspend_done_handle(void);
+
+#endif  // _USBIDLE_MAIN_H
+
diff --git a/mcu/middleware/hif/usbidle/include/usbidle_main.h b/mcu/middleware/hif/usbidle/include/usbidle_main.h
new file mode 100644
index 0000000..10d06dc
--- /dev/null
+++ b/mcu/middleware/hif/usbidle/include/usbidle_main.h
@@ -0,0 +1,84 @@
+/*!
+ *  @file usbidle_main.h
+ *  @author Roger Huang <chaomin.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main definitions of usbcore
+ */
+
+#ifndef _USBIDLE_MAIN_H
+#define _USBIDLE_MAIN_H
+
+#include "hif_mw_msgid.h"
+#include "kal_public_api.h"
+
+#define USBIDLE_MUTEX_LOCK(_s)   kal_take_enh_mutex(_s)
+#define USBIDLE_MUTEX_UNLOCK(_s) kal_give_enh_mutex(_s)
+
+typedef struct _usbidle_t{
+
+    /*!
+     * @brife use to notify whether USBIDLE has to gate the clock of USB IP or not
+     */
+    kal_bool usbidle_clock_off;
+
+    /*!
+     * @brife use to notify whether USBIDLE has to ask L4 to do power saving
+     */
+    kal_bool usbidle_l4_power_saving;
+
+    /*!
+     * @brief mutex for setting usbidle_clock_off
+     */
+    //kal_enhmutexid usbidle_clock_gating_mutex;
+
+    /*!
+     * @brief mutex for setting usbidle_L4 power saving
+     */
+    kal_enhmutexid usbidle_l4_power_saving_mutex;
+
+    kal_spinlockid usbidle_notify_driver_spinlock;
+
+} usbidle_t;
+
+
+/*!
+ *  @brief get the instance of USBIDLE module
+ *  @return pointer to usbidle_t* instance if success, NULL if fail
+ */
+usbidle_t* usbidle_get_instance(void);
+
+#endif  // _USBIDLE_MAIN_H
+
diff --git a/mcu/middleware/hif/usbidle/src/usbidle_hif.c b/mcu/middleware/hif/usbidle/src/usbidle_hif.c
new file mode 100644
index 0000000..68af3dc
--- /dev/null
+++ b/mcu/middleware/hif/usbidle/src/usbidle_hif.c
@@ -0,0 +1,59 @@
+/*!
+ *  @file usbidle_hif.c
+ *  @author Bo-Kai Huang <bo-kai.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main functions of usbidle
+ */
+
+#include "kal_public_api.h"
+#include "intrCtrl.h"
+#include "usbidle_hif.h"
+#include "usbidle_main.h"
+#include "hif_usb.h"
+
+void usb_idle_suspend_done_handle(void)
+{
+    usbidle_t* pUsbIdle = usbidle_get_instance();
+
+    kal_take_spinlock(pUsbIdle->usbidle_notify_driver_spinlock, KAL_INFINITE_WAIT);
+
+    if(pUsbIdle->usbidle_clock_off)
+    {
+        hifusb_suspend_done_handle();   // notification to HIF driver for the completion of USB suspending
+    }
+
+    kal_give_spinlock(pUsbIdle->usbidle_notify_driver_spinlock);
+}
diff --git a/mcu/middleware/hif/usbidle/src/usbidle_if.c b/mcu/middleware/hif/usbidle/src/usbidle_if.c
new file mode 100644
index 0000000..5853943
--- /dev/null
+++ b/mcu/middleware/hif/usbidle/src/usbidle_if.c
@@ -0,0 +1,96 @@
+/*!
+ *  @file usbidle_task.c
+ *  @author Bo-Kai Huang <bo-kai.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main functions of usbidle
+ */
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "sysservice_msgid.h"
+#include "usbidle_main.h"
+#include "usbidle_if.h"
+#include "ps_public_l4_msgid.h"
+#include "ps_public_struct.h"
+
+void usb_idle_set_clockGating(kal_bool gatingValue)
+{
+    usbidle_t* pUsbIdle = usbidle_get_instance();
+
+    //USBIDLE_MUTEX_LOCK(pUsbIdle->usbidle_clock_gating_mutex);
+    kal_take_spinlock(pUsbIdle->usbidle_notify_driver_spinlock, KAL_INFINITE_WAIT);
+    pUsbIdle->usbidle_clock_off = gatingValue;
+    kal_give_spinlock(pUsbIdle->usbidle_notify_driver_spinlock);
+    //USBIDLE_MUTEX_UNLOCK(pUsbIdle->usbidle_clock_gating_mutex);
+}
+
+void usb_idle_set_l4_power_saving(kal_bool gatingValue)
+{
+    usbidle_t* pUsbIdle = usbidle_get_instance();
+
+    USBIDLE_MUTEX_LOCK(pUsbIdle->usbidle_l4_power_saving_mutex);
+    pUsbIdle->usbidle_l4_power_saving = gatingValue;
+    USBIDLE_MUTEX_UNLOCK(pUsbIdle->usbidle_l4_power_saving_mutex);
+}
+
+void usb_idle_event_notify_to_l4(kal_bool usb_suspend, kal_bool remote_wk)
+{
+#if !defined(L4_NOT_PRESENT) && !defined(__L4_TASK_DISABLE__)
+    l4c_usb_suspend_req_struct *rsp_msg_p;
+    msg_type msg_id;
+    usbidle_t* pUsbIdle = usbidle_get_instance();
+
+    msg_id = usb_suspend? MSG_ID_L4C_USB_SUSPEND_REQ:MSG_ID_L4C_USB_RESUME_REQ;
+    rsp_msg_p = (l4c_usb_suspend_req_struct*)construct_local_para(sizeof(l4c_usb_suspend_req_struct), TD_RESET);
+    ASSERT(rsp_msg_p);
+    rsp_msg_p->remote_wakeup_enable = remote_wk;
+
+    if(usb_suspend && !pUsbIdle->usbidle_l4_power_saving)
+    {
+        return;
+    }
+
+    /*
+     *  Send ILM to L4 to notify power saving
+     */
+    msg_send6(MOD_USBIDLE,  // src module
+              MOD_L4C,  // dst module
+              0,       // sap id
+              msg_id,
+              (local_para_struct*)rsp_msg_p,
+              0); //msg id
+#endif
+}
diff --git a/mcu/middleware/hif/usbidle/src/usbidle_task.c b/mcu/middleware/hif/usbidle/src/usbidle_task.c
new file mode 100644
index 0000000..84e329e
--- /dev/null
+++ b/mcu/middleware/hif/usbidle/src/usbidle_task.c
@@ -0,0 +1,152 @@
+/*!
+ *  @file usbidle_task.c
+ *  @author Bo-Kai Huang <bo-kai.haung@mediatek.com>
+ *  @version 1.0
+ *  @section LICENSE
+ *
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *  @section DESCRIPTION
+ *  This file provides main functions of usbidle
+ */
+
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "sysservice_msgid.h"
+#include "usbidle_main.h"
+#include "usbidle_hif.h"
+#include "usbidle_if.h"
+#include "hif_usb.h"
+#ifdef __MTK_MD_DIRECT_USB_SUPPORT__
+#include "ufpm_usbcore.h"
+#include "ps_public_l4_msgid.h"
+#endif
+
+static usbidle_t usbidle_inst_s;
+
+usbidle_t* usbidle_get_instance()
+{
+    return &usbidle_inst_s;
+}
+
+static void usb_idle_task_main(task_entry_struct* task_entry_ptr)
+{
+    ilm_struct current_ilm;
+    kal_set_active_module_id(MOD_USBIDLE);
+    kal_mem_set(&current_ilm, 0, sizeof(ilm_struct));
+
+    while (1)
+    {
+        /* msg_receive_extq will block, therefore we poll if any message
+           exist first */
+        if ( KAL_TRUE == msg_receive_extq(&current_ilm) )
+        {
+            kal_set_active_module_id(current_ilm.dest_mod_id);
+
+            switch (current_ilm.msg_id)
+            {
+#ifndef __MTK_MD_DIRECT_USB_SUPPORT__            
+                case MSG_ID_USBCORE_SUSPEND_TO_IDLE:
+                    usb_idle_suspend_done_handle();   // notification to HIF driver for the completion of USB suspending
+                    break;
+
+                case MSG_ID_USBCORE_IDLE_NOTIFY_TO_L4:
+                {
+                    usbcore_usbidle_l4_power_saving_req_struct *rsp_msg_l4_power_p = (usbcore_usbidle_l4_power_saving_req_struct*)current_ilm.local_para_ptr;
+                    usb_idle_event_notify_to_l4(rsp_msg_l4_power_p->notify_suspend, rsp_msg_l4_power_p->notify_suspend_with_remote_wk);
+                    break;
+                }
+#else
+#ifdef __UFPM_AT_COMMAND_SUPPORT__
+                case MSG_ID_L4C_UFPM_ENABLE_MD_FAST_PATH_REQ:
+                case MSG_ID_L4C_UFPM_DISABLE_MD_FAST_PATH_REQ:
+                case MSG_ID_L4C_UFPM_ACTIVATE_MD_FAST_PATH_REQ:
+                case MSG_ID_L4C_UFPM_DEACTIVATE_MD_FAST_PATH_REQ:
+                    ufpm_redirect_l4_ilm(&current_ilm);
+                    break;
+#endif
+#endif
+                default:
+                    break;
+            }
+            
+            destroy_ilm(&current_ilm);
+        }
+    }
+}
+
+
+static kal_bool usb_idle_task_init(void)
+{
+    usbidle_t *pUsbIdle;
+    kal_char usbidle_mutex_name[50];
+
+    kal_mem_set(usbidle_get_instance(), 0, sizeof(usbidle_t));
+
+    pUsbIdle = usbidle_get_instance();
+
+    pUsbIdle->usbidle_clock_off = KAL_FALSE;
+    pUsbIdle->usbidle_l4_power_saving = KAL_FALSE;
+
+    //sprintf(usbidle_mutex_name, "USBIDLE_CLOCK_GATE_MUTEX");
+    //pUsbIdle->usbidle_clock_gating_mutex = kal_create_enh_mutex(usbidle_mutex_name);
+    sprintf(usbidle_mutex_name, "USBIDLE_L4_POWER_SAVING_MUTEX");
+    pUsbIdle->usbidle_l4_power_saving_mutex = kal_create_enh_mutex(usbidle_mutex_name);
+    sprintf(usbidle_mutex_name, "USBIDLE_NOTIFY_DRIVER_SPINLOCK");
+    pUsbIdle->usbidle_notify_driver_spinlock = kal_create_spinlock(usbidle_mutex_name);
+
+    return KAL_TRUE;
+}
+
+
+static kal_bool usb_idle_task_reset(void)
+{
+    /* Do task's reset here.
+     * Notice that: shouldn't execute modules reset handler since
+     * stack_task_reset() will do. */
+    return KAL_TRUE;
+}
+
+
+kal_bool usb_idle_create(comptask_handler_struct **handle)
+{
+    static const comptask_handler_struct usb_idle_handler_info =
+    {
+        usb_idle_task_main,        /* task entry function */
+        usb_idle_task_init,        /* task initialization function */
+        usb_idle_task_reset        /* task reset handler */
+    };
+
+    *handle = (comptask_handler_struct *)&usb_idle_handler_info;
+
+    return KAL_TRUE;
+}
+
diff --git a/mcu/middleware/kpalv/include/kpalv.h b/mcu/middleware/kpalv/include/kpalv.h
new file mode 100644
index 0000000..7f147a1
--- /dev/null
+++ b/mcu/middleware/kpalv/include/kpalv.h
@@ -0,0 +1,120 @@
+/*****************************************************************************
+ *  Copyright Statement:
+ *  --------------------
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2012
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   kpalv.h
+ *
+ * Project:
+ * --------
+ *   
+ *
+ * Description:
+ * ------------
+ *  keepalive internal function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ *
+ *
+ ****************************************************************************/
+
+#ifndef __INC_KPALV_H
+#define __INC_KPALV_H
+
+#include "kal_general_types.h"
+#include "kal_public_defs.h"
+#include "kal_public_api.h"
+#include "kpalv_struct.h"
+#include "kpalv_data.h"
+#include "ipc_struct.h"
+
+void kpalv_dispatch_ilm(ilm_struct *ilm);
+void kpalv_ilm_handler(ilm_struct *ilm);
+
+void kpalv_timer_init(void);
+void kpalv_init(void);
+void kpalv_reset(void);
+
+void kpalv_stop_reset_all_connections(void);
+
+void kpalv_receive_keep_alive_enable_cmd(ilm_struct *ilm);
+void kpalv_receive_keep_alive_disable_cmd(ilm_struct *ilm);
+void kpalv_receive_keep_alive_query_cmd(ilm_struct *ilm);
+void kpalv_receive_keep_alive_invalid_cmd(ilm_struct *ilm);
+kal_bool kpalv_receive_keep_alive_query_result(ilm_struct *ilm, kal_uint8 *conn_id, kal_uint8 *conn_status);
+void kpalv_idle_poll_tmout_hndlr(void *event_hf_param);
+void kpalv_interval_poll_tmout_hndlr(void *event_hf_param);
+void kpalv_register_ul_filter_at_ipc(kal_uint8 conn_id, kpalv_req_ip_type_e ip_type);
+void kpalv_register_dl_filter_at_ipc(kal_uint8 conn_id, kpalv_req_ip_type_e ip_type);
+void kpalv_start_retry_timer(kal_uint8 conn_id);
+void kpalv_start_idle_timer(kal_uint8 conn_id);
+void kpalv_idle_poll_tmout_hndlr(void *event_hf_param);
+void kpalv_unregister_ul_dl_filter_at_ipc(kal_uint8 conn_id);
+void kpalv_stop_keep_alive_for_connection(kal_uint8 conn_id);
+void kpalv_stop_idle_timer(kal_uint8 conn_id);
+void kpalv_send_keep_alive_notify(kal_bool ok, kal_uint8 conn_handle, kpalv_md_kpalive_state_e state, kal_bool ap_disable_rsp, kal_uint8 rsp_ps_idx);
+void kpalv_send_keep_alive_notify_urc(kal_uint8 conn_handle, kpalv_md_kpalive_state_e state, kal_uint8 rsp_ps_idx);
+
+
+void kpalv_ul_filter_cbk(ipc_filter_info_t *info_p,
+                            void *context,
+                            kal_int32 filter_id,
+                            qbm_gpd *head_gpd,
+                            qbm_gpd *tail_gpd,
+                            kal_uint32 length);
+
+void kpalv_dl_filter_cbk(ipc_filter_info_t *info_p,
+                        void *context,
+                        kal_int32 filter_id,
+                        qbm_gpd *head_gpd,
+                        qbm_gpd *tail_gpd,
+                        kal_uint32 length);
+
+void kpalv_prepare_udp_keep_alive_packet_buffer(kal_uint8 conn_id);
+void kpalv_send_udp_keep_alive_packet(kal_uint8 conn_id);
+
+#ifdef ATEST_SYS_KPALV 
+void* kpalv_get_connection_address(kal_uint8 conn_id);
+kal_int32 kpalv_get_connection_ul_filter_id(kal_uint8 conn_id);
+kal_int32 kpalv_get_connection_dl_filter_id(kal_uint8 conn_id);
+#endif
+#endif /* __INC_KPALV_H */
diff --git a/mcu/middleware/kpalv/include/kpalv_data.h b/mcu/middleware/kpalv/include/kpalv_data.h
new file mode 100644
index 0000000..f7445f9
--- /dev/null
+++ b/mcu/middleware/kpalv/include/kpalv_data.h
@@ -0,0 +1,140 @@
+/*****************************************************************************
+ *  Copyright Statement:
+ *  --------------------
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2012
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   kpalv_data.h
+ *
+ * Project:
+ * --------
+ *   
+ *
+ * Description:
+ * ------------
+ *  Keep alive context structure definitions
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ *
+ *
+ ****************************************************************************/
+#ifndef __INC_KPALV_DATA_H
+#define __INC_KPALV_DATA_H
+
+#include "kal_general_types.h"
+#include "kal_public_defs.h"
+#include "kal_public_api.h"
+#include "kpalv_struct.h"
+#include "kpalv_ut.h"
+
+#ifdef ATEST_SYS_KPALV
+#define KPALV_SEND_KEEP_ALIVE_NOTIFY_CNF    kpalv_ut_send_keep_alive_notify
+#define KPALV_SEND_KEEP_ALIVE_NOTIFY_URC    kpalv_ut_send_keep_alive_notify_urc
+#else
+#define KPALV_SEND_KEEP_ALIVE_NOTIFY_CNF    kpalv_send_keep_alive_notify
+#define KPALV_SEND_KEEP_ALIVE_NOTIFY_URC    kpalv_send_keep_alive_notify_urc
+#endif
+
+
+#define KPALV_KEEP_ALIVE_DATA_LENGTH        1
+#define KPALV_KEEP_ALIVE_IPV4_PACKET        40 /* ipv4:20 + tcp:20 */
+#define KPALV_KEEP_ALIVE_IPV6_PACKET        60 /* ipv6:40 + tcp:20 */
+
+#define KPALV_KEEP_ALIVE_IPV4_UDP_PACKET        28 /* ipv4:20 + udp:8 */
+#define KPALV_KEEP_ALIVE_IPV6_UDP_PACKET        48 /* ipv6:40 + udp:8 */
+
+#define KPALV_KEEP_ALIVE_V4_PACKET_LENGTH  (KPALV_KEEP_ALIVE_IPV4_PACKET + KPALV_KEEP_ALIVE_DATA_LENGTH)
+#define KPALV_KEEP_ALIVE_V6_PACKET_LENGTH  (KPALV_KEEP_ALIVE_IPV6_PACKET + KPALV_KEEP_ALIVE_DATA_LENGTH)
+
+#define KPALV_KEEP_ALIVE_V4_UDP_PACKET_LENGTH  (KPALV_KEEP_ALIVE_IPV4_UDP_PACKET + KPALV_KEEP_ALIVE_DATA_LENGTH)
+#define KPALV_KEEP_ALIVE_V6_UDP_PACKET_LENGTH  (KPALV_KEEP_ALIVE_IPV6_UDP_PACKET + KPALV_KEEP_ALIVE_DATA_LENGTH)
+
+/** this is the index value for idle timer for connection 0 */
+#define IDLE_TIMER_INDEX_VALUE_START    5 
+
+/** this is the index value for retry timer for connection 0 */
+#define RETRY_TIMER_INDEX_VALUE_START   10
+
+typedef struct {
+    kal_bool            is_enable;                              /**< keep-alive enabled or disabled */
+    kpalv_req_ip_type_e ip_type;                                /**< ipv4/v6 tcp udp type */
+    kal_uint32          netif_id;                               /**< ap module attached to nw_interface_id */
+    kal_uint8           src_ipv4_addr[KPALV_IPV4_ADDR_LEN];     /**< IPV4 src addr */
+    kal_uint8           dst_ipv4_addr[KPALV_IPV4_ADDR_LEN];     /**< IPV4 dst addr */
+    kal_uint8           src_ipv6_addr[KPALV_IPV6_ADDR_LEN];     /**< IPV6 src addr */
+    kal_uint8           dst_ipv6_addr[KPALV_IPV6_ADDR_LEN];     /**< IPV6 dst addr */
+    kal_uint16          src_port;                               /**< src port */
+    kal_uint16          dst_port;                               /**< dst port */
+    kal_uint16          idle_time;                              /**< idle time in sec */
+    kal_uint16          probe_interval;                         /**< retry time in sec */
+    kal_uint8           max_retry_cnt;                          /**< number of retries */
+} kpalv_keep_alive_at_cmd_info_struct;
+
+typedef struct {
+    kal_uint32          pdn_id;                          /**< get ipc_find_pdn_id_by_netif_id */
+    kal_uint8           ps_id;                           /**< get ipc_find_pdn_id_by_netif_id */
+    kal_uint8           curr_retry_attempt;              /**< curr retry count */
+    kal_int32           ul_filter_id;                    /**< UL filter id */
+    kal_int32           dl_filter_id;                    /**< DL filter id */
+    event_scheduler     *idle_timer_scheduler;           /**< T1 event schduler */
+    event_scheduler     *retry_timer_scheduler;          /**< T2 event scheduler */
+    eventid             eid_idle_timer;                  /**< T1 event id */
+    eventid             eid_retry_timer;                 /**< T2 event id */
+} kpalv_keep_alive_control_struct;
+
+typedef struct {
+    kal_bool            is_already_updated;                                                  /**< received first UL packet from AP or not */
+    kal_uint8           ipv4_tcp_keep_alive_packet[KPALV_KEEP_ALIVE_V4_PACKET_LENGTH];       /**< ipv4 keep-alive ready buffer */
+    kal_uint8           ipv6_tcp_keep_alive_packet[KPALV_KEEP_ALIVE_V6_PACKET_LENGTH];       /**< ipv6 keep-alive ready buffer */
+    kal_uint8           ipv4_udp_keep_alive_packet[KPALV_KEEP_ALIVE_V4_UDP_PACKET_LENGTH];   /**< ipv4 udp keep-alive ready buffer */
+    kal_uint8           ipv6_udp_keep_alive_packet[KPALV_KEEP_ALIVE_V6_UDP_PACKET_LENGTH];   /**< ipv6 udp keep-alive ready buffer */
+} kpalv_keep_alive_data_struct;
+
+typedef struct {
+    kpalv_keep_alive_at_cmd_info_struct     at_info;
+    kpalv_keep_alive_control_struct         control_info;
+    kal_bool                                is_cntx_valid;
+    kpalv_md_kpalive_state_e                status;
+    kpalv_keep_alive_data_struct            data_info;
+} kpalv_keep_alive_struct;
+
+
+#endif /* __INC_KPALV_DATA_H */
diff --git a/mcu/middleware/kpalv/include/kpalv_debug.h b/mcu/middleware/kpalv/include/kpalv_debug.h
new file mode 100644
index 0000000..c6de6ed
--- /dev/null
+++ b/mcu/middleware/kpalv/include/kpalv_debug.h
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ *  Copyright Statement:
+ *  --------------------
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2012
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   kpalv_debug.h
+ *
+ * Project:
+ * --------
+ *   
+ *
+ * Description:
+ * ------------
+ *  keepalive debug functions
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ *
+ *
+ ****************************************************************************/
+#ifndef __INC_KPALV_DEBUG_H
+#define __INC_KPALV_DEBUG_H
+
+#include "kpalv_trace.h"
+
+#define KPALV_LOG             dhl_trace
+
+#endif /* __INC_KPALV_DEBUG_H */
diff --git a/mcu/middleware/kpalv/include/kpalv_trace.h b/mcu/middleware/kpalv/include/kpalv_trace.h
new file mode 100644
index 0000000..c73dfa4
--- /dev/null
+++ b/mcu/middleware/kpalv/include/kpalv_trace.h
@@ -0,0 +1,78 @@
+/*****************************************************************************
+ *  Copyright Statement:
+ *  --------------------
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2012
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   kpalv_debug.h
+ *
+ * Project:
+ * --------
+ *   
+ *
+ * Description:
+ * ------------
+ *  keepalive debug traces
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ *
+ *
+ ****************************************************************************/
+ 
+#ifndef __INC_KPALV_TRACE_H
+#define __INC_KPALV_TRACE_H
+
+#ifndef GEN_FOR_PC
+    #include "kal_public_defs.h"
+#endif  /* GEN_FOR_PC */
+
+#include "dhl_trace.h"
+
+#if !defined(GEN_FOR_PC)
+#if defined(__DHL_MODULE__) || defined(__CUSTOM_RELEASE__)
+#endif
+#endif
+#if !defined(GEN_FOR_PC)
+#include "kpalv_trace_mod_kpalv_utmd.h"
+#endif
+
+#endif /* __INC_KPALV_TRACE_H */
+
diff --git a/mcu/middleware/kpalv/include/kpalv_trace_mod_kpalv_utmd.json b/mcu/middleware/kpalv/include/kpalv_trace_mod_kpalv_utmd.json
new file mode 100644
index 0000000..b4ff25a
--- /dev/null
+++ b/mcu/middleware/kpalv/include/kpalv_trace_mod_kpalv_utmd.json
@@ -0,0 +1,278 @@
+{

+  "endGen": "-",

+  "LegacyParameters": {},

+  "module": "MOD_KPALV",

+  "startGen": "93",

+  "traceClassDefs": [

+    {

+      "TRACE_INFO": {

+        "debugLevel": "High",

+	    "tag": [

+	      "Baseline",

+	      "TRACE_INFO"

+	    ],

+	    "traceType": "CoreDesign"

+      }

+    },

+    {

+      "TRACE_ERROR": {

+        "debugLevel": "Ultra-High",

+        "tag": [

+        	"Baseline",

+        	"TRACE_ERROR"

+        ],

+        "traceType": "CoreDesign"

+      }

+    },

+	{

+      "TRACE_WARNING": {

+        "debugLevel": "Medium",

+        "tag": [

+        	"Baseline",

+        	"TRACE_WARNING"

+        ],

+        "traceType": "InternalDesign"

+      }

+    },

+    {

+      "TRACE_FUNC": {

+        "debugLevel": "Low",

+        "tag": [

+        	"Baseline",

+        	"TRACE_FUNC"

+        ],

+        "traceType": "CoreDesign"

+      }

+    }

+  ],

+  "traceDefs": [

+    {

+      "KPALV_TR_ILM_WRONG_MSG_ID": {

+        "apiType": "index",

+        "format": "[kpalv] dispatcher_on_ilm(): wrong msg_id(%d)!",

+        "traceClass": "TRACE_ERROR"

+      }

+    },

+    {

+      "KPALV_TR_INIT_ENTRY": {

+        "apiType": "index",

+        "format": "[[kpalv] dispatcher_init()",

+        "traceClass": "TRACE_FUNC"

+      }

+    },

+    

+    {

+      "KPALV_TR_RESET_ENTRY": {

+        "apiType": "index",

+        "format": "[kpalv] dispatcher_reset()",

+        "traceClass": "TRACE_FUNC"

+      }

+    },

+    {

+      "KPALV_TR_ENABLE_REQ_DUPLICATE": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_receive_keep_alive_enable_cmd ERROR: duplicate req!!!",

+        "traceClass": "TRACE_ERROR"

+      }

+    },

+    {

+      "KPALV_TR_ENABLE_REQ_MAX_CONN": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_receive_keep_alive_enable_cmd ERROR: max conn reached!!!",

+        "traceClass": "TRACE_ERROR"

+      }

+    },

+    

+    {

+      "KPALV_TR_ENABLE_REQ_NETIF_FAILED": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_receive_keep_alive_enable_cmd ERROR: ipc query netif failed!!!",

+        "traceClass": "TRACE_ERROR"

+      }

+    },

+    {

+      "KPALV_TR_ENABLE_REQ_SIM_MISMATCH": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_receive_keep_alive_enable_cmd ERROR: atp sim and ps_id different!!!",

+        "traceClass": "TRACE_WARNING"

+      }

+    },

+    {

+      "KPALV_TR_NOTIFY_RSP_TO_ATP": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_send_keep_alive_notify: result:(%d), conn_id(%d), status(%d), ap_dis_req(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+    {

+      "KPALV_TR_NOTIFY_FOR_URC_TO_ATP": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_send_keep_alive_notify_urc: conn_id(%d), status(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+    {

+      "KPALV_TR_START_IDLE_TIMER": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_start_idle_timer: conn_id(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+    {

+      "KPALV_TR_START_RETRY_TIMER": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_start_retry_timer: conn_id(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+    {

+      "KPALV_TR_STOP_IDLE_TIMER": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_stop_idle_timer: conn_id(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+    {

+      "KPALV_TR_STOP_RETRY_TIMER": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_stop_retry_timer: conn_id(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+    {

+      "KPALV_TR_TIMEOUT_IDLE_TIMER": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_idle_poll_tmout_hndlr: conn_id(%d), conn_status(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+    {

+      "KPALV_TR_TIMEOUT_RETRY_TIMER": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_interval_poll_tmout_hndlr: conn_id(%d), retry_attempt(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+    {

+      "KPALV_TR_MAX_RETRY_ATTEMPTED": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv max retries exhausted INACTIVE for conn_id(%d) , notify URC to AP",

+        "traceClass": "TRACE_WARNING"

+      }

+    },

+	{

+      "KPALV_TR_STOP_KEEP_ALIVE_CONN": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_stop_keep_alive_for_connection: conn_id(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_UL_FILTER_CBK": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_ul_filter_cbk: conn_id(%d) , head_gpd(0x%X) tail_gpd(0x%X)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_UL_FILTER_DETAILS": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_ul_filter_cbk, 1st UL packet captured ACTIVE state : conn_id(%d), notify URC to AP",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_UPDATE_KEEP_ALIVE_BUFF": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_update_keep_alive_packet_by_ul_flow: conn_id(%d) is_ipv6(%d) seq_num(%u), ack_num(%u)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_DL_FILTER_CBK": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_dl_filter_cbk: conn_id(%d) , head_gpd(0x%X) tail_gpd(0x%X)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_DL_PACKET_INFO": {

+        "apiType": "index",

+        "format": "[kpalv] recvd DL pkt: DL tcp seg len(%d) ack_num(%u) seq_num(%u) tcp_flag (%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_DL_PACKET_INFO_UPDATE_UL": {

+        "apiType": "index",

+        "format": "[kpalv] recvd DL pkt: update KPLAV buffer by non-keepalive ack pkt with ack_num(%u) seq_num(%u)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_DL_KEEP_ALIVE_ACK": {

+        "apiType": "index",

+        "format": "[kpalv] recvd DL pkt: TCP keep-alive ack recvd from server, return",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_DL_PACKET_FORWARD": {

+        "apiType": "index",

+        "format": "[kpalv] recvd DL pkt: non keep-alive ack: forward head_gpd(0x%X) tail_gpd(0x%X) to netif(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_GPD_ALLOC_FAIL": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_send_keep_alive_packet() : GPD alloc failed at line:(%d)",

+        "traceClass": "TRACE_ERROR"

+      }

+    },

+	{

+      "KPALV_TR_SEND_KEEP_ALIVE_PKT": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_send_keep_alive_packet: conn_id(%d) , pdn_id(%d), head_gpd(0x%X)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_PKT_SEND_FAILED": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_send_keep_alive_packet() failed: %d : ipcore return false",

+        "traceClass": "TRACE_WARNING"

+      }

+    },

+	{

+      "KPALV_TR_SEND_KEEP_ALIVE_PKT_ENTRY": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_send_keep_alive_packet() entry for conn_id(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_SEND_KEEP_ALIVE_PKT_UPDATE": {

+        "apiType": "index",

+        "format": "[kpalv] keep alive update pkt before send DONE",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+	{

+      "KPALV_TR_PREPARE_UDP_KEEP_ALIVE_PKT": {

+        "apiType": "index",

+        "format": "[kpalv] UDP enabled, kpalv_prepare_udp_packet: conn_id(%d) , total_len(%d), ip_hdr_len(%d)",

+        "traceClass": "TRACE_INFO"

+      }

+    },

+    {

+      "KPALV_TR_SEND_UDP_KEEP_ALIVE_PKT": {

+        "apiType": "index",

+        "format": "[kpalv] kpalv_send_udp_keep_alive_packet: conn_id(%d) , pdn_id(%d), head_gpd(0x%X)",

+        "traceClass": "TRACE_FUNC"

+      }

+    }

+  ], 

+  "traceFamily": "PS",

+  "userModule": "MOD_KPALV"

+}

diff --git a/mcu/middleware/kpalv/include/kpalv_ut.h b/mcu/middleware/kpalv/include/kpalv_ut.h
new file mode 100644
index 0000000..13ef181
--- /dev/null
+++ b/mcu/middleware/kpalv/include/kpalv_ut.h
@@ -0,0 +1,65 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   kpalv_ut.h
+ *
+ * Project:
+ * --------
+ *   UMOLY
+ *
+ * Description:
+ * ------------
+ *   UT Api.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *******************************************************************************/
+
+#ifndef __INC_KPALV_UT_H
+#define __INC_KPALV_UT_H
+
+#ifdef ATEST_SYS_KPALV
+void kpalv_ut_send_keep_alive_notify(kal_bool ok, kal_uint8 conn_handle, kpalv_md_kpalive_state_e state, kal_bool ap_dis_flow, kal_uint8 rsp_ps_idx);
+void kpalv_ut_send_keep_alive_notify_urc(kal_uint8 conn_handle, kpalv_md_kpalive_state_e state, kal_uint8 rsp_ps_idx);
+
+
+#endif/* ATEST_SYS_KPALV */
+
+#endif /* __INC_KPALV_UT_H */
diff --git a/mcu/middleware/kpalv/src/kpalv_data.c b/mcu/middleware/kpalv/src/kpalv_data.c
new file mode 100644
index 0000000..968dadf
--- /dev/null
+++ b/mcu/middleware/kpalv/src/kpalv_data.c
@@ -0,0 +1,1266 @@
+/*****************************************************************************
+ *  Copyright Statement:
+ *  --------------------
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2012
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   kpalv_data.c
+ *
+ * Project:
+ * --------
+ *   
+ *
+ * Description:
+ * ------------
+ *  keepalive handling for connection
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ * 09 18 2019 amit.singh
+ * [MOLY00440693] [KPALV] clean task info in VMOLY
+ * 	
+ * 	USIR KPALV task.
+ *
+ *
+ *
+ ****************************************************************************/
+#include "ipc_api.h"
+#include "qmu_bm_util.h"
+#include "kpalv.h"
+#include "kpalv_data.h"
+#include "kpalv_msgid.h"
+#include "atp_msgid.h"
+#include "kpalv_debug.h"
+#include "kpalv_struct.h"
+#include "mw_sap.h"
+
+
+extern kal_uint16 ipc_calc_tcp_checksum(kal_bool is_ipv4, kal_uint8 *src_addr, kal_uint8 *dst_addr, kal_uint8 *tcp_header, kal_uint32 tcp_len);
+extern kal_uint16 ipc_calc_ipv4_checksum(kal_uint8 *ip_header);
+extern kal_uint16 ipc_calc_udp_checksum(kal_bool is_ipv4, kal_uint8 *src_addr, kal_uint8 *dst_addr, kal_uint8 *udp_header, kal_uint32 udp_len);
+
+
+/* context structure of keep-aive*/
+static kpalv_keep_alive_struct keep_alive_cntx[KPALV_MAX_KEEP_ALIVE_CONN];
+
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+
+void kpalv_init(void)
+{
+    int conn_id = 0;
+    kal_mem_set(&keep_alive_cntx, 0, sizeof(kpalv_keep_alive_struct)*KPALV_MAX_KEEP_ALIVE_CONN);
+    
+    for (conn_id = 0; conn_id < KPALV_MAX_KEEP_ALIVE_CONN; conn_id++) {
+        keep_alive_cntx[conn_id].control_info.ul_filter_id = -1;
+        keep_alive_cntx[conn_id].control_info.dl_filter_id = -1;
+        keep_alive_cntx[conn_id].status = KPALV_MD_KEEPALIVE_STATE_INACTIVE;
+    }
+
+    kpalv_timer_init();
+    MD_TRC_KPALV_TR_INIT_ENTRY();
+}
+
+void kpalv_reset(void)
+{   
+    kpalv_stop_reset_all_connections();
+    MD_TRC_KPALV_TR_RESET_ENTRY();
+}
+
+void kpalv_timer_init(void)
+{
+    kal_uint8 i = 0;
+    for (i= 0; i< KPALV_MAX_KEEP_ALIVE_CONN; i++) {
+        keep_alive_cntx[i].control_info.idle_timer_scheduler = evshed_create(
+                                "KPALV_IDEL_TIMER",
+                                MOD_KPALV,
+                                0,
+                                0);
+
+        if (keep_alive_cntx[i].control_info.idle_timer_scheduler) {
+            evshed_set_index(keep_alive_cntx[i].control_info.idle_timer_scheduler, (IDLE_TIMER_INDEX_VALUE_START + i)); 
+        } else {
+            ASSERT(KAL_FALSE);
+        }
+
+        keep_alive_cntx[i].control_info.retry_timer_scheduler = evshed_create(
+                                "KPALV_RETRY_TIMER",
+                                MOD_KPALV,
+                                0,
+                                0);
+
+        if (keep_alive_cntx[i].control_info.retry_timer_scheduler) {
+            evshed_set_index(keep_alive_cntx[i].control_info.retry_timer_scheduler, (RETRY_TIMER_INDEX_VALUE_START + i));
+        } else {
+            ASSERT(KAL_FALSE);
+        }
+    }
+}
+
+void kpalv_update_data_before_sending_keepalive_packet(kal_uint8 *stored_buffer, kal_uint8 ip_type) {
+        
+    kal_uint16 sum16 = 0;
+    kal_uint16 ipid = 0;
+    kal_uint32 ip_header_len = 0;
+    kal_uint8 *ip_header = NULL;
+    kal_uint8 *tcp_header = NULL;
+    kal_uint8 *src_addr = NULL;
+    kal_uint8 *dst_addr = NULL;
+    kal_uint32 tcp_header_len = 0;
+
+    ip_header = stored_buffer;
+    tcp_header_len = IPC_HDR_TCP_HEADER_SIZE;
+    
+    ip_header_len = (ip_type == IPC_IP_TYPE_IPV4) ? IPC_HDR_V4_HEADER_SIZE : IPC_HDR_V6_HEADER_SIZE;
+
+    tcp_header = ip_header + ip_header_len;
+    
+    if (ip_type == IPC_IP_TYPE_IPV4) {
+        ipid = IPC_HDR_V4_GET_IDENTITY(ip_header);
+        src_addr = IPC_HDR_V4_GET_SRC_ADDR(ip_header);
+        dst_addr = IPC_HDR_V4_GET_DST_ADDR(ip_header);
+        IPC_HDR_V4_SET_IDENTITY(ip_header, ipid + 1);//last UL IPID + 1;
+
+        //calc tcp chekcsum
+        IPC_HDR_TCP_SET_CHECKSUM(tcp_header, 0);
+        sum16 = ipc_calc_tcp_checksum(KAL_TRUE, src_addr, dst_addr, tcp_header, (tcp_header_len+KPALV_KEEP_ALIVE_DATA_LENGTH)); //1 byte nil data
+        IPC_HDR_TCP_SET_CHECKSUM(tcp_header, sum16);
+
+        //update the checksum too
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(stored_buffer, 0);
+        sum16 = ipc_calc_ipv4_checksum(stored_buffer);
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(stored_buffer, sum16);
+    } else {
+        //calc tcp chekcsum
+        dst_addr = IPC_HDR_V6_GET_DST_ADDR(ip_header);
+        src_addr = IPC_HDR_V6_GET_SRC_ADDR(ip_header);
+
+        IPC_HDR_TCP_SET_CHECKSUM(tcp_header, 0);
+        sum16 = ipc_calc_tcp_checksum(KAL_TRUE, src_addr, dst_addr, tcp_header, tcp_header_len);
+        IPC_HDR_TCP_SET_CHECKSUM(tcp_header, sum16);
+        
+        /*ipv6 dont have checksum*/
+    }
+    MD_TRC_KPALV_TR_SEND_KEEP_ALIVE_PKT_UPDATE();
+}
+
+void kpalv_send_udp_keep_alive_packet(kal_uint8 conn_id) {
+    ipc_pkt_t ipc_pkt;
+    qbm_gpd *ul_gpd;
+    qbm_gpd *bd;
+    kal_bool result;
+    kal_uint8 *packet_buf;
+    kal_uint32 packet_len;
+    kal_uint8 ip_type;
+    kpalv_keep_alive_at_cmd_info_struct *at_info = NULL;
+    
+
+    at_info = &keep_alive_cntx[conn_id].at_info;
+    ip_type = (at_info->ip_type == KPALV_REQ_IPTYPE_IPV4UDP) ? IPC_IP_TYPE_IPV4 : IPC_IP_TYPE_IPV6;
+
+    if(ip_type == IPC_IP_TYPE_IPV4) {
+        packet_buf = keep_alive_cntx[conn_id].data_info.ipv4_udp_keep_alive_packet;
+        packet_len = sizeof(keep_alive_cntx[conn_id].data_info.ipv4_udp_keep_alive_packet);
+    } else {
+        packet_buf = keep_alive_cntx[conn_id].data_info.ipv6_udp_keep_alive_packet;
+        packet_len = sizeof(keep_alive_cntx[conn_id].data_info.ipv6_udp_keep_alive_packet);
+    }
+    ul_gpd = QBM_ALLOC_ONE(QBM_TYPE_NET_UL_SHRD);
+    if (ul_gpd == NULL)
+    {
+        //log cant send keep-aive as of now
+        MD_TRC_KPALV_TR_GPD_ALLOC_FAIL(__LINE__);
+        return;
+    }
+    
+    bd = QBM_DES_GET_DATAPTR(ul_gpd);
+
+    /*fill GPD for keep-alive packet buffer, this is a ready buffer, no need to update anythig, just copy*/
+    kal_mem_cpy(QBM_DES_GET_DATAPTR(bd), packet_buf, packet_len);
+    QBM_CACHE_FLUSH(QBM_DES_GET_DATAPTR(bd), packet_len);
+    QBM_DES_SET_DATALEN(bd, packet_len);
+    qbm_cal_set_checksum(bd);
+    QBM_DES_SET_DATALEN(ul_gpd, packet_len);
+    qbm_cal_set_checksum(ul_gpd);
+
+    /*Send keep-alive packet to IPCORE */
+    kal_mem_set(&ipc_pkt, 0, sizeof(ipc_pkt));
+    ipc_pkt.isGPD = KAL_TRUE;
+    ipc_pkt.head = ul_gpd;
+    ipc_pkt.tail = ul_gpd;
+    MD_TRC_KPALV_TR_SEND_UDP_KEEP_ALIVE_PKT(conn_id, keep_alive_cntx[conn_id].control_info.pdn_id, ipc_pkt.head); 
+    result = ipc_send_ul_pkt_by_pdn_multiple_ps(&ipc_pkt, NULL, keep_alive_cntx[conn_id].control_info.pdn_id, ip_type, keep_alive_cntx[conn_id].control_info.ps_id);
+    if (KAL_FALSE == result) {
+        MD_TRC_KPALV_TR_PKT_SEND_FAILED(__LINE__);
+        qbmt_dest_q(ul_gpd, ul_gpd);
+    }
+}
+
+void kpalv_send_keep_alive_packet(kal_uint8 conn_id)
+{
+
+    /* in our buffer always keep-alive updated, ready to send same packet*/
+    ipc_pkt_t ipc_pkt;
+    qbm_gpd *ul_gpd;
+    qbm_gpd *bd;
+    kal_uint8 *packet_buf;
+    kal_uint32 packet_len;
+    kal_uint8 ip_type;
+    kal_uint8 *ipv4_keep_alive_buffer = keep_alive_cntx[conn_id].data_info.ipv4_tcp_keep_alive_packet;
+    kal_uint8 *ipv6_keep_alive_buffer = keep_alive_cntx[conn_id].data_info.ipv6_tcp_keep_alive_packet;
+    kal_bool result;
+
+    MD_TRC_KPALV_TR_SEND_KEEP_ALIVE_PKT_ENTRY(conn_id);
+    ul_gpd = QBM_ALLOC_ONE(QBM_TYPE_NET_UL_SHRD);
+    if (ul_gpd == NULL)
+    {
+        //log cant send keep-aive as of now
+        MD_TRC_KPALV_TR_GPD_ALLOC_FAIL(__LINE__);
+        return;
+    }
+    
+    bd = QBM_DES_GET_DATAPTR(ul_gpd);
+    packet_buf = keep_alive_cntx[conn_id].at_info.ip_type == KPALV_REQ_IPTYPE_IPV6TCP ? ipv6_keep_alive_buffer : ipv4_keep_alive_buffer;
+    packet_len = keep_alive_cntx[conn_id].at_info.ip_type == KPALV_REQ_IPTYPE_IPV6TCP ? KPALV_KEEP_ALIVE_V6_PACKET_LENGTH : KPALV_KEEP_ALIVE_V4_PACKET_LENGTH;
+    ip_type = keep_alive_cntx[conn_id].at_info.ip_type == KPALV_REQ_IPTYPE_IPV6TCP ? IPC_IP_TYPE_IPV6 : IPC_IP_TYPE_IPV4;
+
+    /*get the keep-alive ready buffer, but need to update the ID field in IPv4 header , nedd to increment on every UL even for kpalv too*/
+    
+    kpalv_update_data_before_sending_keepalive_packet(packet_buf, ip_type);
+
+    /*fill GPD for keep-alive packet buffer, this is a ready buffer, no need to update anythig, just copy*/
+    kal_mem_cpy(QBM_DES_GET_DATAPTR(bd), packet_buf, packet_len);
+    QBM_CACHE_FLUSH(QBM_DES_GET_DATAPTR(bd), packet_len);
+    QBM_DES_SET_DATALEN(bd, packet_len);
+    qbm_cal_set_checksum(bd);
+    QBM_DES_SET_DATALEN(ul_gpd, packet_len);
+    qbm_cal_set_checksum(ul_gpd);
+
+
+    /*Send keep-alive packet to IPCORE */
+    kal_mem_set(&ipc_pkt, 0, sizeof(ipc_pkt));
+    ipc_pkt.isGPD = KAL_TRUE;
+    ipc_pkt.head = ul_gpd;
+    ipc_pkt.tail = ul_gpd;
+    MD_TRC_KPALV_TR_SEND_KEEP_ALIVE_PKT(conn_id, keep_alive_cntx[conn_id].control_info.pdn_id, ipc_pkt.head);
+    result = ipc_send_ul_pkt_by_pdn_multiple_ps(&ipc_pkt, NULL, keep_alive_cntx[conn_id].control_info.pdn_id, ip_type, keep_alive_cntx[conn_id].control_info.ps_id);
+    if (KAL_FALSE == result) {
+        MD_TRC_KPALV_TR_PKT_SEND_FAILED(__LINE__);
+        qbmt_dest_q(ul_gpd, ul_gpd);
+    }
+}
+
+
+void kpalv_close_connection_notify_urc(kal_uint8 conn_id)
+{
+    kpalv_keep_alive_struct* connection_context = &keep_alive_cntx[conn_id];
+    /*notify to AP via URC for dead connection*/
+    KPALV_SEND_KEEP_ALIVE_NOTIFY_URC(conn_id, KPALV_MD_KEEPALIVE_STATE_INACTIVE, connection_context->control_info.ps_id);
+    kpalv_stop_keep_alive_for_connection(conn_id);
+
+}
+
+void kpalv_idle_poll_tmout_hndlr(void *event_hf_param)
+{
+    kpalv_keep_alive_struct* connection_context = (kpalv_keep_alive_struct*)event_hf_param;
+    kal_uint8 conn_id =  connection_context - &keep_alive_cntx[0];
+
+    ASSERT(connection_context->control_info.eid_idle_timer);
+    connection_context->control_info.eid_idle_timer = NULL;
+
+    MD_TRC_KPALV_TR_TIMEOUT_IDLE_TIMER(conn_id, connection_context->status);
+    if ((connection_context->at_info.ip_type == KPALV_REQ_IPTYPE_IPV6TCP) ||
+        (connection_context->at_info.ip_type == KPALV_REQ_IPTYPE_IPV4TCP)) {
+        if (connection_context->status == KPALV_MD_KEEPALIVE_STATE_ACTIVE) {
+            kpalv_send_keep_alive_packet(conn_id);
+            kpalv_start_retry_timer(conn_id);
+        } else if (connection_context->status == KPALV_MD_KEEPALIVE_STATE_PENDING){
+            //can restart idle timer again to wait for active state
+            kpalv_start_idle_timer(conn_id);
+        } else {
+            ASSERT(0);
+        }
+    } else {
+        /* UPD case falls here*/
+        kpalv_send_udp_keep_alive_packet(conn_id);
+        kpalv_start_idle_timer(conn_id);
+    }
+}
+
+
+void kpalv_interval_poll_tmout_hndlr(void *event_hf_param)
+{
+    kpalv_keep_alive_struct* connection_context = (kpalv_keep_alive_struct*)event_hf_param;
+    kal_uint8 conn_id =  connection_context - &keep_alive_cntx[0];
+    
+    ASSERT(connection_context->control_info.eid_retry_timer);
+    connection_context->control_info.eid_retry_timer = NULL;
+
+    if (connection_context->control_info.curr_retry_attempt < connection_context->at_info.max_retry_cnt) {
+        connection_context->control_info.curr_retry_attempt++;
+        MD_TRC_KPALV_TR_TIMEOUT_RETRY_TIMER(conn_id, connection_context->control_info.curr_retry_attempt);
+        kpalv_send_keep_alive_packet(conn_id);
+        kpalv_start_retry_timer(conn_id);
+        return;
+    }
+
+    /*max retry reached for retry attempt, notify AP via URC & reset this conection info*/
+    MD_TRC_KPALV_TR_MAX_RETRY_ATTEMPTED(conn_id);
+    kpalv_close_connection_notify_urc(conn_id);
+}
+
+void kpalv_start_idle_timer(kal_uint8 conn_id)
+{
+
+    kpalv_keep_alive_struct *kpalv_cntx = &keep_alive_cntx[conn_id];
+    kpalv_cntx->control_info.eid_idle_timer = evshed_set_event(kpalv_cntx->control_info.idle_timer_scheduler,
+            (kal_timer_func_ptr)kpalv_idle_poll_tmout_hndlr,
+             kpalv_cntx, 
+             kpalv_cntx->at_info.idle_time*1000
+             );
+    MD_TRC_KPALV_TR_START_IDLE_TIMER(conn_id);
+
+}
+
+void kpalv_start_retry_timer(kal_uint8 conn_id)
+{
+    kpalv_keep_alive_struct *kpalv_cntx = &keep_alive_cntx[conn_id];
+    kpalv_cntx->control_info.eid_retry_timer  = evshed_set_event(kpalv_cntx->control_info.retry_timer_scheduler,
+        (kal_timer_func_ptr)kpalv_interval_poll_tmout_hndlr,
+         kpalv_cntx, 
+         kpalv_cntx->at_info.probe_interval*1000
+         );
+     MD_TRC_KPALV_TR_START_RETRY_TIMER(conn_id);
+}
+
+
+void kpalv_stop_idle_timer(kal_uint8 conn_id)
+{
+    if (keep_alive_cntx[conn_id].control_info.eid_idle_timer != NULL) {
+        evshed_cancel_event(keep_alive_cntx[conn_id].control_info.idle_timer_scheduler,
+                &keep_alive_cntx[conn_id].control_info.eid_idle_timer);
+        keep_alive_cntx[conn_id].control_info.eid_idle_timer = NULL;
+        MD_TRC_KPALV_TR_STOP_IDLE_TIMER(conn_id);
+    }
+}
+
+void kpalv_stop_retry_timer(kal_uint8 conn_id)
+{
+    if (keep_alive_cntx[conn_id].control_info.eid_retry_timer != NULL) {
+        evshed_cancel_event(keep_alive_cntx[conn_id].control_info.retry_timer_scheduler,
+                &keep_alive_cntx[conn_id].control_info.eid_retry_timer);
+        keep_alive_cntx[conn_id].control_info.eid_retry_timer = NULL;
+        keep_alive_cntx[conn_id].control_info.curr_retry_attempt = 0;
+        MD_TRC_KPALV_TR_STOP_RETRY_TIMER(conn_id);
+    }
+}
+
+void kpalv_receive_keep_alive_req_cmd(ilm_struct *ilm) 
+{
+    atp_kpalv_keepalive_req_struct *at_cmd = (atp_kpalv_keepalive_req_struct *)(ilm->local_para_ptr);
+
+    if (KPALV_REQ_ENABLE == at_cmd->req_type) {
+        kpalv_receive_keep_alive_enable_cmd(ilm);
+    } else if (KPALV_REQ_DISABLE == at_cmd->req_type) {
+        kpalv_receive_keep_alive_disable_cmd(ilm);
+    } else if (KPALV_REQ_QUERY == at_cmd->req_type) {
+        kpalv_receive_keep_alive_query_cmd(ilm);
+    } else {
+        kpalv_receive_keep_alive_invalid_cmd(ilm);
+    }
+}
+
+
+
+
+void kpalv_ilm_handler(ilm_struct *ilm)
+{   
+    switch (ilm->msg_id) {
+        case MSG_ID_ATP_KPALV_KEEPALIVE_REQ:
+            kpalv_receive_keep_alive_req_cmd(ilm);
+            break;
+
+        /*timer expiry*/
+        case MSG_ID_TIMER_EXPIRY:
+            switch (evshed_get_index(ilm)) {
+                case 5:
+                    evshed_timer_handler(keep_alive_cntx[0].control_info.idle_timer_scheduler);
+                    break;
+                case 6:
+                    evshed_timer_handler(keep_alive_cntx[1].control_info.idle_timer_scheduler);
+                    break;
+                case 10:
+                    evshed_timer_handler(keep_alive_cntx[0].control_info.retry_timer_scheduler);
+                    break;
+                case 11:
+                    evshed_timer_handler(keep_alive_cntx[1].control_info.retry_timer_scheduler);
+                    break;
+                }        
+            break;
+
+        default:
+            MD_TRC_KPALV_TR_ILM_WRONG_MSG_ID(ilm->msg_id);
+            break;
+    }
+}
+
+void kpalv_update_keep_alive_packet_by_ul_flow(kal_bool is_ul, kal_uint8 *ip_packet, kal_uint8 conn_id, kal_bool is_ipv6)
+{
+    kal_uint8   *stored_tcp_header = NULL;
+    kal_uint8   *in_tcp_header = NULL;
+    kal_uint32  in_tcp_seq_num =0;
+    kal_uint32  in_tcp_ack_num =0;
+
+    if (KAL_FALSE == is_ipv6) {
+        kal_uint16 ipid = 0;
+        kal_uint8 *stored_full_buffer = keep_alive_cntx[conn_id].data_info.ipv4_tcp_keep_alive_packet;
+        stored_tcp_header = stored_full_buffer + IPC_HDR_V4_HEADER_SIZE;
+        in_tcp_header = ip_packet + IPC_HDR_V4_HEADER_SIZE;
+
+        /*update the recvd ipid */    
+        ipid = IPC_HDR_V4_GET_IDENTITY(ip_packet);
+        IPC_HDR_V4_SET_IDENTITY(stored_full_buffer, ipid); //saved last IPID +1 when sending a new keep-alive packet
+
+        /** for ipv4 header just update totallength */
+        IPC_HDR_V4_SET_TOTAL_LENGTH(stored_full_buffer, KPALV_KEEP_ALIVE_V4_PACKET_LENGTH); 
+
+    } else {
+        kal_uint8 *stored_full_buffer = keep_alive_cntx[conn_id].data_info.ipv6_tcp_keep_alive_packet;
+        stored_tcp_header = stored_full_buffer + IPC_HDR_V6_HEADER_SIZE;
+        in_tcp_header = ip_packet + IPC_HDR_V6_HEADER_SIZE;
+
+        /** for ipv6 header just update payload length */
+        IPC_HDR_V6_SET_LENGTH(stored_full_buffer, (KPALV_KEEP_ALIVE_V6_PACKET_LENGTH - IPC_HDR_V6_HEADER_SIZE));
+
+    }
+
+    /*update tcp part: FLAG, PTR, CHECKSUM at later*/
+    in_tcp_seq_num = IPC_HDR_TCP_GET_SEQ_NUM(in_tcp_header);
+    IPC_HDR_TCP_SET_SEQ_NUM(stored_tcp_header, (in_tcp_seq_num -1));
+
+    in_tcp_ack_num = IPC_HDR_TCP_GET_ACK_NUM(in_tcp_header);
+    IPC_HDR_TCP_SET_ACK_NUM(stored_tcp_header, in_tcp_ack_num);
+
+    MD_TRC_KPALV_TR_UPDATE_KEEP_ALIVE_BUFF(conn_id, is_ipv6, (in_tcp_seq_num-1), in_tcp_ack_num);
+
+    IPC_HDR_TCP_SET_FLAGS(stored_tcp_header, 0);
+    IPC_HDR_TCP_SET_FLAGS(stored_tcp_header, IPC_HDR_TCP_FLAG_ACK);
+    IPC_HDR_TCP_SET_URGENT_PTR(stored_tcp_header, 0);
+    IPC_HDR_TCP_SET_OFFSET(stored_tcp_header, IPC_HDR_TCP_HEADER_SIZE);
+    IPC_HDR_TCP_SET_RESERVED(stored_tcp_header, 0);
+}
+
+/*ipv4 or ipv6 +tcp ul packet matched filter cbk*/
+void kpalv_ul_filter_cbk(ipc_filter_info_t *info_p,
+                            void *context,
+                            kal_int32 filter_id,
+                            qbm_gpd *head_gpd,
+                            qbm_gpd *tail_gpd,
+                            kal_uint32 length)
+{
+ 
+    kal_uint8      *p_packet = NULL;
+    qbm_gpd        *bd;
+    kal_uint8       conn_id;
+    kpalv_keep_alive_struct* connection_context = (kpalv_keep_alive_struct*)context;
+    conn_id =  connection_context - &keep_alive_cntx[0];
+
+    /*this is uplink filter matched packet so we can take full snapshot here*/
+    ASSERT(filter_id == keep_alive_cntx[conn_id].control_info.ul_filter_id);
+
+    MD_TRC_KPALV_TR_UL_FILTER_CBK(conn_id, head_gpd, tail_gpd);
+
+    if (!QBM_DES_GET_BDP(head_gpd)) {
+        p_packet = QBM_DES_GET_DATAPTR(head_gpd);
+    } else {
+        /* get 1st bd data ptr */
+        bd = QBM_DES_GET_DATAPTR(head_gpd);
+
+        /* Loop to trace 1st DL BD with data buffer */
+        while (bd && (QBM_DES_GET_DATALEN(bd) == 0)) {
+            bd = (QBM_DES_GET_EOL(bd))?(NULL):((qbm_gpd*)QBM_DES_GET_NEXT(bd));
+        }
+
+        /* No any BD have data */
+        if (NULL == bd) {
+            qbmt_dest_q(head_gpd, tail_gpd);
+            return;
+        }
+
+        p_packet = QBM_DES_GET_DATAPTR(bd);
+    }
+    if (IPC_HDR_IS_V4(p_packet)) {
+        
+        if (keep_alive_cntx[conn_id].data_info.is_already_updated == KAL_FALSE) {
+            
+            kal_mem_set(keep_alive_cntx[conn_id].data_info.ipv4_tcp_keep_alive_packet, 0, sizeof(keep_alive_cntx[conn_id].data_info.ipv4_tcp_keep_alive_packet));     
+            /*take full snapshot here for 1st dummy UL req from AP*/
+            kal_mem_cpy(keep_alive_cntx[conn_id].data_info.ipv4_tcp_keep_alive_packet, p_packet, KPALV_KEEP_ALIVE_IPV4_PACKET);//1 data byte will remain 00
+            /** always keep the ready buffer non fragmented */
+            IPC_HDR_V4_SET_FLAGS(keep_alive_cntx[conn_id].data_info.ipv4_tcp_keep_alive_packet, 0x2); /* Set Do Not Fragment */
+            IPC_HDR_V4_SET_FRAG_OFFSET(keep_alive_cntx[conn_id].data_info.ipv4_tcp_keep_alive_packet, 0);
+            keep_alive_cntx[conn_id].data_info.is_already_updated = KAL_TRUE;
+            keep_alive_cntx[conn_id].status = KPALV_MD_KEEPALIVE_STATE_ACTIVE;
+            MD_TRC_KPALV_TR_UL_FILTER_DETAILS(conn_id);
+            KPALV_SEND_KEEP_ALIVE_NOTIFY_URC(conn_id, KPALV_MD_KEEPALIVE_STATE_ACTIVE, keep_alive_cntx[conn_id].control_info.ps_id);
+        } 
+        /** any pther UL paket sent by AP ,update this buffer for ready keep-alive message */
+        kpalv_update_keep_alive_packet_by_ul_flow(KAL_TRUE, p_packet, conn_id, KAL_FALSE);
+        
+    }
+
+    if (IPC_HDR_IS_V6(p_packet)) {
+    
+        //ipv6 handling here
+        if(keep_alive_cntx[conn_id].data_info.is_already_updated == KAL_FALSE) {
+            kal_mem_set(keep_alive_cntx[conn_id].data_info.ipv6_tcp_keep_alive_packet, 0, sizeof(keep_alive_cntx[conn_id].data_info.ipv6_tcp_keep_alive_packet));     
+            kal_mem_cpy(keep_alive_cntx[conn_id].data_info.ipv6_tcp_keep_alive_packet, p_packet, KPALV_KEEP_ALIVE_IPV6_PACKET);//IPv6+TCP 1 data byte will remain 00
+            keep_alive_cntx[conn_id].data_info.is_already_updated = KAL_TRUE;
+            keep_alive_cntx[conn_id].status = KPALV_MD_KEEPALIVE_STATE_ACTIVE;
+            MD_TRC_KPALV_TR_UL_FILTER_DETAILS(conn_id);
+            KPALV_SEND_KEEP_ALIVE_NOTIFY_URC(conn_id, KPALV_MD_KEEPALIVE_STATE_ACTIVE, keep_alive_cntx[conn_id].control_info.ps_id);
+        }
+        //any pther UL paket sent by AP ,update this buffer for ready keep-alive message  
+        kpalv_update_keep_alive_packet_by_ul_flow(KAL_TRUE, p_packet, conn_id, KAL_TRUE);
+    }
+  qbmt_dest_q(head_gpd, tail_gpd);   
+}
+
+
+
+void kpalv_register_ul_filter_at_ipc(kal_uint8 conn_id, kpalv_req_ip_type_e ip_type)
+{
+    ipc_filter_rules_t ul_filter_rules;
+    kal_mem_set(&ul_filter_rules, 0, sizeof(ipc_filter_rules_t));
+
+    ul_filter_rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_DST_PORT;
+
+    ul_filter_rules.protocol = IPC_HDR_PROT_TCP;
+    ul_filter_rules.src_port = keep_alive_cntx[conn_id].at_info.src_port;
+    ul_filter_rules.dst_port = keep_alive_cntx[conn_id].at_info.dst_port;
+
+    /*pass the packet to UPCM as callback to filter to update keep-alive packet content*/
+    ul_filter_rules.features |= IPC_FILTER_FEATURE_CLONE;
+           
+    if (ip_type == KPALV_REQ_IPTYPE_IPV6TCP) {
+        ul_filter_rules.valid_fields |= IPC_FILTER_BY_SRC_IPV6 |
+                                        IPC_FILTER_BY_DST_IPV6;
+        ul_filter_rules.ip_type = IPC_IP_TYPE_IPV6;
+        IPC_CP_V6_ADDR(&ul_filter_rules.src_ipv6.addr8, &keep_alive_cntx[conn_id].at_info.src_ipv6_addr);
+        IPC_CP_V6_ADDR(&ul_filter_rules.dst_ipv6.addr8, &keep_alive_cntx[conn_id].at_info.dst_ipv6_addr);
+        
+    } else {
+        ul_filter_rules.valid_fields |= IPC_FILTER_BY_SRC_IPV4 |
+                                        IPC_FILTER_BY_DST_IPV4;
+        ul_filter_rules.ip_type = IPC_IP_TYPE_IPV4;
+        IPC_CP_V4_ADDR(&ul_filter_rules.src_ipv4.addr8, &keep_alive_cntx[conn_id].at_info.src_ipv4_addr);
+        IPC_CP_V4_ADDR(&ul_filter_rules.dst_ipv4.addr8, &keep_alive_cntx[conn_id].at_info.dst_ipv4_addr);
+    }
+    keep_alive_cntx[conn_id].control_info.ul_filter_id = ipc_register_ul_filter_with_info_cbk(
+                                    &ul_filter_rules, kpalv_ul_filter_cbk, &keep_alive_cntx[conn_id]);
+   
+}
+
+void kpalv_keep_alive_rsp_received(kal_uint8 conn_id)
+{
+    //Stop idle timer if running
+    kpalv_stop_idle_timer(conn_id);
+    //stop probe timer if running, along with reset retry count
+    kpalv_stop_retry_timer(conn_id); 
+    //start idle timer again
+    kpalv_start_idle_timer(conn_id);
+}
+
+void kpalv_dl_filter_cbk(ipc_filter_info_t *info_p,
+                        void *context,
+                        kal_int32 filter_id,
+                        qbm_gpd *head_gpd,
+                        qbm_gpd *tail_gpd,
+                        kal_uint32 length)
+{
+
+    /*downlink filter matched for set filter*/
+    /*there could be two case 1. keep-alive ack 2. others*/
+    /* need update to keepalive packet seq & ack number based upon DL recvd from server*/
+    kal_uint8      *p_packet = NULL;
+    qbm_gpd        *bd;
+    kal_bool       is_ipv4 = KAL_FALSE;
+    kal_uint8      *p_tcp_header;
+    kal_uint32     dl_ack_num;
+    kal_uint32     dl_seq_num;
+    kal_uint16     tcp_flags;
+    kal_uint32     data_seg_len = 0;
+    kal_uint8      conn_id;
+    kal_uint8      *stored_full_buffer;
+    kal_uint8      *stored_tcp_header;
+    kal_uint8      tcp_total_header_len = 0;
+
+    kpalv_keep_alive_struct* connection_context = (kpalv_keep_alive_struct*)context;
+    conn_id =  connection_context - &keep_alive_cntx[0];
+   
+    ASSERT(filter_id == keep_alive_cntx[conn_id].control_info.dl_filter_id);
+
+    MD_TRC_KPALV_TR_DL_FILTER_CBK(conn_id, head_gpd, tail_gpd);
+    if (head_gpd == NULL || tail_gpd == NULL) {
+        return;
+    }
+
+    if (!QBM_DES_GET_BDP(head_gpd)) {
+        p_packet = QBM_DES_GET_DATAPTR(head_gpd);
+    } else {
+        /* get 1st bd data ptr */
+        bd = QBM_DES_GET_DATAPTR(head_gpd);
+
+        /* Loop to trace 1st DL BD with data buffer */
+        while (bd && (QBM_DES_GET_DATALEN(bd) == 0)) {
+            bd = (QBM_DES_GET_EOL(bd))?(NULL):((qbm_gpd*)QBM_DES_GET_NEXT(bd));
+        }
+
+        /* No any BD have data */
+        if (NULL == bd) {
+            /*zero length gpd*/
+            qbmt_dest_q(head_gpd, tail_gpd);
+            return;
+        }
+
+        p_packet = QBM_DES_GET_DATAPTR(bd);
+    }
+
+    //got the IP packet start address
+
+    if (IPC_HDR_IS_V4(p_packet)) {    
+        is_ipv4 = KAL_TRUE;
+        p_tcp_header = p_packet + IPC_HDR_V4_HEADER_SIZE;//move to TCP header
+        tcp_total_header_len = IPC_HDR_TCP_GET_OFFSET(p_tcp_header);
+        data_seg_len = IPC_HDR_V4_GET_TOTAL_LENGTH(p_packet) - IPC_HDR_V4_HEADER_SIZE - tcp_total_header_len; // total length - ipv4-total tcp header
+    } else if (IPC_HDR_IS_V6(p_packet)) {       
+        is_ipv4 = KAL_FALSE;
+        p_tcp_header = p_packet + IPC_HDR_V6_HEADER_SIZE;
+        tcp_total_header_len = IPC_HDR_TCP_GET_OFFSET(p_tcp_header);
+        data_seg_len = IPC_HDR_V6_GET_LENGTH(p_packet) - tcp_total_header_len; //payload length - total tcp header
+    } else {
+        qbmt_dest_q(head_gpd, tail_gpd);
+        return;
+    }
+ 
+    dl_ack_num = IPC_HDR_TCP_GET_ACK_NUM(p_tcp_header);
+    dl_seq_num = IPC_HDR_TCP_GET_SEQ_NUM(p_tcp_header);
+    tcp_flags = IPC_HDR_TCP_GET_FLAGS(p_tcp_header);
+
+    if (is_ipv4) {
+        stored_full_buffer = keep_alive_cntx[conn_id].data_info.ipv4_tcp_keep_alive_packet;
+        stored_tcp_header = stored_full_buffer + IPC_HDR_V4_HEADER_SIZE;
+    } else {
+        stored_full_buffer = keep_alive_cntx[conn_id].data_info.ipv6_tcp_keep_alive_packet;
+        stored_tcp_header = stored_full_buffer + IPC_HDR_V6_HEADER_SIZE;
+    }
+
+    MD_TRC_KPALV_TR_DL_PACKET_INFO(data_seg_len, dl_ack_num, dl_seq_num, tcp_flags);
+
+    /*this is only TCP ACK packet, could be Keep-aive ack so just check*/
+    if (tcp_flags == IPC_HDR_TCP_FLAG_ACK) {
+
+        kal_uint32     saved_ul_ack_num;
+        kal_uint32     saved_ul_seq_num;
+
+        saved_ul_ack_num = IPC_HDR_TCP_GET_ACK_NUM(stored_tcp_header);
+        saved_ul_seq_num = IPC_HDR_TCP_GET_SEQ_NUM(stored_tcp_header);
+
+        if ((saved_ul_seq_num == (dl_ack_num-1)) && (saved_ul_ack_num == dl_seq_num)) {
+            //this is the response of TCP keep-alive 
+            kpalv_keep_alive_rsp_received(conn_id);
+            qbmt_dest_q(head_gpd, tail_gpd);
+            MD_TRC_KPALV_TR_DL_KEEP_ALIVE_ACK();
+            return;
+        }
+    }
+
+    /*pkt received  from server so restart idle timer*/
+    kpalv_stop_idle_timer(conn_id);
+    //start idle timer again
+    kpalv_start_idle_timer(conn_id);
+    /*could be the case that retry probe is sent But before that server send some packet*/
+    /*we can assume server conn is active, so can stop retry timer if running*/
+    kpalv_stop_retry_timer(conn_id); 
+
+    /** update tcp header fields for stored keep-alive packet */
+    /** update the TCP fileds when keep-alive Buffer updated by UL(ACTIVE_STATE) */
+    if ((connection_context->data_info.is_already_updated == KAL_TRUE) &&
+        (connection_context->status == KPALV_MD_KEEPALIVE_STATE_ACTIVE)) {
+        IPC_HDR_TCP_SET_SEQ_NUM(stored_tcp_header, dl_ack_num -1);
+        IPC_HDR_TCP_SET_ACK_NUM(stored_tcp_header, dl_seq_num + data_seg_len);
+        MD_TRC_KPALV_TR_DL_PACKET_INFO_UPDATE_UL((dl_seq_num + data_seg_len), (dl_ack_num -1));
+    }
+    
+    /*not a keep-alive ack => update last DL ack & seq to keep-alive buffer & forward to AP*/
+    /* pass to AP via IPCORE*/
+    {
+        ipc_pkt_t pkt;
+        kal_uint32 netif_id = 0;
+
+        pkt.buf_type = IPC_PKT_DES_TYPE_GPD;
+        pkt.head = head_gpd;
+        pkt.tail = tail_gpd;
+
+        netif_id = keep_alive_cntx[conn_id].at_info.netif_id | IPC_NETIF_ID_LHIF_BEGIN;
+        MD_TRC_KPALV_TR_DL_PACKET_FORWARD(head_gpd, tail_gpd, netif_id);
+
+        if (KAL_FALSE == ipc_send_dl_pkt_in_did(&pkt, NULL, netif_id)) {
+            if(qbm_get_used(head_gpd)) {
+                qbmt_dest_q(head_gpd, tail_gpd);
+            }
+        }
+    }
+
+}
+
+
+
+void kpalv_register_dl_filter_at_ipc(kal_uint8 conn_id, kpalv_req_ip_type_e ip_type)
+{
+    ipc_filter_rules_t dl_filter_rules;
+    kal_mem_set(&dl_filter_rules, 0, sizeof(ipc_filter_rules_t));
+    dl_filter_rules.valid_fields = IPC_FILTER_BY_PROTOCOL |
+                                   IPC_FILTER_BY_SRC_PORT |
+                                   IPC_FILTER_BY_DST_PORT |
+                                   IPC_FILTER_BY_PDN_ID;
+
+
+    dl_filter_rules.protocol = IPC_HDR_PROT_TCP;
+    /*reverse port for DL filter*/
+    dl_filter_rules.src_port = keep_alive_cntx[conn_id].at_info.dst_port;
+    dl_filter_rules.dst_port = keep_alive_cntx[conn_id].at_info.src_port;
+
+    dl_filter_rules.pdn_id = keep_alive_cntx[conn_id].control_info.pdn_id;
+           
+   if (ip_type == KPALV_REQ_IPTYPE_IPV6TCP) { 
+       dl_filter_rules.valid_fields |= IPC_FILTER_BY_SRC_IPV6 |
+                                        IPC_FILTER_BY_DST_IPV6;
+        dl_filter_rules.ip_type = IPC_IP_TYPE_IPV6;
+        
+        IPC_CP_V6_ADDR(&dl_filter_rules.src_ipv6.addr8, &keep_alive_cntx[conn_id].at_info.dst_ipv6_addr);
+        IPC_CP_V6_ADDR(&dl_filter_rules.dst_ipv6.addr8, &keep_alive_cntx[conn_id].at_info.src_ipv6_addr);
+        
+   } else {
+        dl_filter_rules.valid_fields |= IPC_FILTER_BY_SRC_IPV4 |
+                                        IPC_FILTER_BY_DST_IPV4;
+        dl_filter_rules.ip_type = IPC_IP_TYPE_IPV4;
+        
+        IPC_CP_V4_ADDR(&dl_filter_rules.src_ipv4.addr8, &keep_alive_cntx[conn_id].at_info.dst_ipv4_addr);
+        IPC_CP_V4_ADDR(&dl_filter_rules.dst_ipv4.addr8, &keep_alive_cntx[conn_id].at_info.src_ipv4_addr);
+   }
+
+   keep_alive_cntx[conn_id].control_info.dl_filter_id = ipc_register_dl_filter_with_info_cbk(
+                                &dl_filter_rules, kpalv_dl_filter_cbk , &keep_alive_cntx[conn_id]);
+}
+
+kal_bool kpalv_get_conn_number(kal_uint8* conn_id)
+{
+    int i = 0;
+    for (i= 0; i< KPALV_MAX_KEEP_ALIVE_CONN; i++) {
+        if(keep_alive_cntx[i].is_cntx_valid == KAL_FALSE) {
+            *conn_id = i;
+            return KAL_TRUE;
+        }
+    }
+    return KAL_FALSE;
+}
+
+void kpalv_send_keep_alive_notify_urc(kal_uint8 conn_handle, kpalv_md_kpalive_state_e state, kal_uint8 rsp_ps_idx)
+{      
+    //MSG_ID_ATP_KPALV_CONNECTION_STATUS_IND
+    atp_kpalv_connection_status_ind_struct *p_ind = NULL;
+    kal_uint16 sap_id = KPALV_SAP;
+
+    p_ind = (atp_kpalv_connection_status_ind_struct *)construct_local_para
+                    (sizeof(atp_kpalv_connection_status_ind_struct), TD_RESET);
+
+    p_ind->conn_id = conn_handle;
+    p_ind->status = state;
+
+    MD_TRC_KPALV_TR_NOTIFY_FOR_URC_TO_ATP(conn_handle, state);
+
+    msg_send6(MOD_KPALV, MOD_ATP + rsp_ps_idx, sap_id, MSG_ID_ATP_KPALV_CONNECTION_STATUS_IND,
+                 (local_para_struct *)p_ind, NULL);
+}
+
+
+void kpalv_send_keep_alive_notify(kal_bool ok, kal_uint8 conn_handle, kpalv_md_kpalive_state_e state, kal_bool ap_dis_flow, kal_uint8 rsp_ps_idx)
+{
+        
+    //MSG_ID_ATP_KPALV_KEEPALIVE_CNF
+    atp_kpalv_keepalive_cnf_struct *p_ind = NULL;
+    kal_uint16 sap_id = KPALV_SAP;
+
+    p_ind = (atp_kpalv_keepalive_cnf_struct *)construct_local_para
+                    (sizeof(atp_kpalv_keepalive_cnf_struct), TD_RESET);
+
+        p_ind->result = ok;
+        p_ind->conn_id = conn_handle;
+        p_ind->status = state;
+        p_ind->is_ap_disable_rsp = ap_dis_flow;
+
+        MD_TRC_KPALV_TR_NOTIFY_RSP_TO_ATP(ok, conn_handle, state, ap_dis_flow);
+
+        msg_send6(MOD_KPALV, MOD_ATP + rsp_ps_idx, sap_id, MSG_ID_ATP_KPALV_KEEPALIVE_CNF,
+                     (local_para_struct *)p_ind, NULL);
+}
+
+
+kal_bool kpalv_check_is_duplicate_req(local_para_struct *local_para_ptr)
+{
+    kal_uint8       i = 0;
+    kal_uint32      result = 0;
+
+    kpalv_keep_alive_at_cmd_info_struct *recvd_at_info = (kpalv_keep_alive_at_cmd_info_struct *)(local_para_ptr + 1);
+    kpalv_keep_alive_at_cmd_info_struct *stored_at_info = NULL;
+    for (i= 0; i<KPALV_MAX_KEEP_ALIVE_CONN; i++) 
+    {
+        stored_at_info = &keep_alive_cntx[i].at_info;
+        result = kal_mem_cmp(stored_at_info, recvd_at_info, sizeof(kpalv_keep_alive_at_cmd_info_struct));
+        if (result == 0) {
+            return KAL_TRUE;
+        }
+    }
+    return KAL_FALSE;
+}
+
+/*
+1. Check duplicate req or not, if yes, return ERROR for this.
+2. get conn_id from pool, if not get return ERROR
+3. get PDNID & SIMID from netif , if FALSE return from IPC API, return ERROR to AP
+4. if SIMID from AP & IPC API are different , return ERROR
+*/
+void kpalv_receive_keep_alive_enable_cmd(ilm_struct *ilm)
+{   
+    kal_uint8                   ip_type = 0;
+    kal_uint32                  pdn_id = 0;
+    kal_uint32                  netif_id = 0;
+    kal_uint8                   ps_id = 0;
+    kal_uint8                   conn_id = 0;
+    kal_bool                    cnf_result = KAL_FALSE;
+    kpalv_md_kpalive_state_e    conn_status = KPALV_MD_KEEPALIVE_STATE_INACTIVE;
+
+    kal_uint8 atp_idx = ilm->src_mod_id - MOD_ATP;
+    atp_kpalv_keepalive_req_struct *at_cmd = (atp_kpalv_keepalive_req_struct *)(ilm->local_para_ptr);
+
+    if (at_cmd->parsing_result == KAL_TRUE) {
+        /** 1. check for only TCP handling for UDP return directly with error*/        
+
+        /** 2.check for duplicate req*/
+        if (kpalv_check_is_duplicate_req(ilm->local_para_ptr)) {
+            MD_TRC_KPALV_TR_ENABLE_REQ_DUPLICATE();
+            goto final_cnf;
+        }
+
+        /** 3.check max conn reached or not*/
+        if (KAL_FALSE == kpalv_get_conn_number(&conn_id)) {
+            MD_TRC_KPALV_TR_ENABLE_REQ_MAX_CONN();
+            goto final_cnf;
+        }
+
+        ip_type = ((at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV6TCP) || (at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV6UDP)) ? IPC_IP_TYPE_IPV6 : IPC_IP_TYPE_IPV4;
+        //cant set DL filter as failed for pdnid
+        /** 4..get PDNID from NETIFID*/
+        netif_id = at_cmd->netif_id | IPC_NETIF_ID_LHIF_BEGIN;
+        if (ipc_find_pdn_id_by_netif_id(netif_id, ip_type, &pdn_id, &ps_id) == KAL_FALSE) {
+            //temp assign for internal testing , return ERROR
+            //pdn_id = 15;
+            //ps_id = 0;
+            MD_TRC_KPALV_TR_ENABLE_REQ_NETIF_FAILED();
+            goto final_cnf;
+        }
+        else 
+        {
+            if (ps_id != atp_idx)
+            {
+                MD_TRC_KPALV_TR_ENABLE_REQ_SIM_MISMATCH();
+                goto final_cnf;
+            }
+        }
+        if ((at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV4TCP) || (at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV6TCP)) {
+            kal_mem_set(&keep_alive_cntx[conn_id].at_info, 0, sizeof(kpalv_keep_alive_at_cmd_info_struct));
+            //reset the data part for new keep-alive ind
+            kal_mem_set(&keep_alive_cntx[conn_id].data_info, 0, sizeof(kpalv_keep_alive_data_struct));
+            
+            /*update current control info all fields*/
+            keep_alive_cntx[conn_id].control_info.pdn_id = pdn_id;
+            keep_alive_cntx[conn_id].control_info.ps_id = ps_id;
+            keep_alive_cntx[conn_id].control_info.curr_retry_attempt = 0;
+            keep_alive_cntx[conn_id].control_info.ul_filter_id = -1;
+            keep_alive_cntx[conn_id].control_info.dl_filter_id = -1;
+
+            keep_alive_cntx[conn_id].at_info.is_enable = KAL_TRUE;
+            keep_alive_cntx[conn_id].at_info.ip_type = at_cmd->ip_type;
+            keep_alive_cntx[conn_id].at_info.netif_id = at_cmd->netif_id;
+            keep_alive_cntx[conn_id].at_info.src_port = at_cmd->src_port;
+            keep_alive_cntx[conn_id].at_info.dst_port = at_cmd->dst_port;
+
+            /*keep-alive parameters*/
+            keep_alive_cntx[conn_id].at_info.idle_time = at_cmd->idle_time;
+            keep_alive_cntx[conn_id].at_info.probe_interval = at_cmd->probe_interval;
+            keep_alive_cntx[conn_id].at_info.max_retry_cnt = at_cmd->retry_cnt;
+            if (at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV6TCP) {
+                kal_mem_cpy(keep_alive_cntx[conn_id].at_info.src_ipv6_addr, at_cmd->src_ipv6_addr, 16);
+                kal_mem_cpy(keep_alive_cntx[conn_id].at_info.dst_ipv6_addr, at_cmd->dst_ipv6_addr, 16);
+            } else {
+                kal_mem_cpy(keep_alive_cntx[conn_id].at_info.src_ipv4_addr, at_cmd->src_ipv4_addr, 4);
+                kal_mem_cpy(keep_alive_cntx[conn_id].at_info.dst_ipv4_addr, at_cmd->dst_ipv4_addr, 4);
+            }
+
+            //register UL/DL filter
+            kpalv_register_ul_filter_at_ipc(conn_id, at_cmd->ip_type);
+            kpalv_register_dl_filter_at_ipc(conn_id, at_cmd->ip_type);
+
+            keep_alive_cntx[conn_id].is_cntx_valid = KAL_TRUE;
+            keep_alive_cntx[conn_id].status = KPALV_MD_KEEPALIVE_STATE_PENDING;
+
+            //start Idle timer
+            kpalv_start_idle_timer(conn_id);
+            conn_status = keep_alive_cntx[conn_id].status;
+            cnf_result = KAL_TRUE;
+        } else if ((at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV4UDP) || (at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV6UDP)) {
+            kal_mem_set(&keep_alive_cntx[conn_id].at_info, 0, sizeof(kpalv_keep_alive_at_cmd_info_struct));
+            //reset the data part for new keep-alive ind
+            kal_mem_set(&keep_alive_cntx[conn_id].data_info, 0, sizeof(kpalv_keep_alive_data_struct));
+             /*update current control info all fields*/
+            keep_alive_cntx[conn_id].control_info.pdn_id = pdn_id;
+            keep_alive_cntx[conn_id].control_info.ps_id = ps_id;
+            keep_alive_cntx[conn_id].control_info.curr_retry_attempt = 0;
+            keep_alive_cntx[conn_id].control_info.ul_filter_id = -1;
+            keep_alive_cntx[conn_id].control_info.dl_filter_id = -1;
+
+            keep_alive_cntx[conn_id].at_info.is_enable = KAL_TRUE;
+            keep_alive_cntx[conn_id].at_info.ip_type = at_cmd->ip_type;
+            keep_alive_cntx[conn_id].at_info.netif_id = at_cmd->netif_id;
+            keep_alive_cntx[conn_id].at_info.src_port = at_cmd->src_port;
+            keep_alive_cntx[conn_id].at_info.dst_port = at_cmd->dst_port;
+
+            /*keep-alive parameters only T1 in UDP*/
+            keep_alive_cntx[conn_id].at_info.idle_time = at_cmd->idle_time;
+
+            if (at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV6UDP) {
+                kal_mem_cpy(keep_alive_cntx[conn_id].at_info.src_ipv6_addr, at_cmd->src_ipv6_addr, 16);
+                kal_mem_cpy(keep_alive_cntx[conn_id].at_info.dst_ipv6_addr, at_cmd->dst_ipv6_addr, 16);
+            } else {
+                kal_mem_cpy(keep_alive_cntx[conn_id].at_info.src_ipv4_addr, at_cmd->src_ipv4_addr, 4);
+                kal_mem_cpy(keep_alive_cntx[conn_id].at_info.dst_ipv4_addr, at_cmd->dst_ipv4_addr, 4);
+            }
+            keep_alive_cntx[conn_id].is_cntx_valid = KAL_TRUE;
+            keep_alive_cntx[conn_id].status = KPALV_MD_KEEPALIVE_STATE_ACTIVE;
+            kpalv_start_idle_timer(conn_id);
+            conn_status = keep_alive_cntx[conn_id].status;
+            cnf_result = KAL_TRUE;
+            kpalv_prepare_udp_keep_alive_packet_buffer(conn_id);
+        } else {
+            cnf_result = KAL_FALSE;
+            conn_id = 0;
+            conn_status = KPALV_MD_KEEPALIVE_STATE_INACTIVE;
+        }      
+    }
+
+final_cnf:
+    KPALV_SEND_KEEP_ALIVE_NOTIFY_CNF(cnf_result, conn_id, conn_status, KAL_FALSE, atp_idx);
+
+
+}
+
+void kpalv_prepare_udp_keep_alive_packet_buffer(kal_uint8 conn_id) {
+    kal_uint8           *ip_header = NULL;
+    kal_uint32          total_len = 0;
+    kal_uint8           *udp_header =  NULL;
+    kal_uint8           *udp_data = NULL;
+    kal_uint16          sum16 = 0;
+    kal_uint8           *src_addr = NULL;
+    kal_uint8           *dst_addr = NULL;
+    kal_uint16          src_port = 0;
+    kal_uint16          dst_port = 0;
+    kal_uint32          ip_header_len = 0;
+    kpalv_keep_alive_at_cmd_info_struct *at_info = NULL;
+    
+
+    at_info = &keep_alive_cntx[conn_id].at_info;
+    if (KPALV_REQ_IPTYPE_IPV4UDP == at_info->ip_type) {
+        ip_header = keep_alive_cntx[conn_id].data_info.ipv4_udp_keep_alive_packet;
+        src_addr = at_info->src_ipv4_addr;
+        dst_addr = at_info->dst_ipv4_addr;
+        ip_header_len = IPC_HDR_V4_HEADER_SIZE;
+    } else {
+        ip_header = keep_alive_cntx[conn_id].data_info.ipv6_udp_keep_alive_packet;
+        src_addr = at_info->src_ipv6_addr;
+        dst_addr = at_info->dst_ipv6_addr;
+        ip_header_len = IPC_HDR_V6_HEADER_SIZE;
+    }
+
+    src_port = at_info->src_port;
+    dst_port = at_info->dst_port;
+
+    total_len = ip_header_len + IPC_HDR_UDP_HEADER_SIZE + 1;
+    udp_header = ip_header + ip_header_len;
+    udp_data = udp_header + IPC_HDR_UDP_HEADER_SIZE;
+
+    MD_TRC_KPALV_TR_PREPARE_UDP_KEEP_ALIVE_PKT(conn_id, total_len, ip_header_len);   
+
+    IPC_HDR_UDP_SET_SRC_PORT(udp_header, src_port);
+    IPC_HDR_UDP_SET_DST_PORT(udp_header, dst_port);
+    IPC_HDR_UDP_SET_LENGTH(udp_header, total_len - ip_header_len);
+    IPC_HDR_UDP_SET_CHECKSUM(udp_header, 0);
+    kal_mem_set(udp_data, 0xff, 1);
+    sum16 = ipc_calc_udp_checksum((KPALV_REQ_IPTYPE_IPV4UDP == at_info->ip_type)?KAL_TRUE:KAL_FALSE,
+                                  src_addr,
+                                  dst_addr,
+                                  udp_header,
+                                  total_len - ip_header_len);
+    IPC_HDR_UDP_SET_CHECKSUM(udp_header, sum16);
+
+    if (KPALV_REQ_IPTYPE_IPV4UDP == at_info->ip_type) {
+        IPC_HDR_V4_RESET_VER_IHL_DSCP_ECN(ip_header);
+         
+        IPC_HDR_V4_SET_TOTAL_LENGTH(ip_header, total_len);
+        IPC_HDR_V4_SET_IDENTITY(ip_header, 0);
+        IPC_HDR_V4_SET_FLAGS(ip_header, 0); /* Set Do Not Fragment */
+        IPC_HDR_V4_SET_FRAG_OFFSET(ip_header, 0);
+        IPC_HDR_V4_SET_TTL(ip_header, IPC_DEF_TTL);
+        IPC_HDR_V4_SET_PROTOCOL(ip_header, IPC_HDR_PROT_UDP);
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, 0);
+        IPC_HDR_V4_SET_SRC_ADDR(ip_header, src_addr);
+        IPC_HDR_V4_SET_DST_ADDR(ip_header, dst_addr);
+        sum16 = ipc_calc_ipv4_checksum(ip_header);
+        IPC_HDR_V4_SET_HEADER_CHECKSUM(ip_header, sum16);
+    } else {
+        //currently no need
+        IPC_HDR_V6_RESET_VER_TC_FL(ip_header);
+        IPC_HDR_V6_SET_TC(ip_header, 0);
+        IPC_HDR_V6_SET_FLOW_LABEL(ip_header, 0);
+        IPC_HDR_V6_SET_LENGTH(ip_header, (total_len-ip_header_len));
+        IPC_HDR_V6_SET_NH_TYPE(ip_header, IPC_HDR_PROT_UDP);
+        IPC_HDR_V6_SET_HOP_LIMIT(ip_header, IPC_DEF_TTL);
+        IPC_HDR_V6_SET_SRC_ADDR(ip_header, src_addr);
+        IPC_HDR_V6_SET_DST_ADDR(ip_header, dst_addr);
+    }
+
+}
+
+void kpalv_stop_reset_all_connections(void)
+{
+    kal_uint8 i = 0;
+
+    for (i= 0; i<KPALV_MAX_KEEP_ALIVE_CONN; i++) 
+    {
+        if (keep_alive_cntx[i].is_cntx_valid) {
+             kpalv_stop_keep_alive_for_connection(i);
+        }
+    }
+}
+
+/** invalid req for keepalive msgid, return ERROR*/
+void kpalv_receive_keep_alive_invalid_cmd(ilm_struct *ilm)
+{
+    kal_uint8 atp_idx = ilm->src_mod_id - MOD_ATP;
+    KPALV_SEND_KEEP_ALIVE_NOTIFY_CNF(KAL_FALSE, 0, KPALV_MD_KEEPALIVE_STATE_INACTIVE, KAL_FALSE, atp_idx);
+}
+
+/** query result for a connection_status*/
+void kpalv_receive_keep_alive_query_cmd(ilm_struct *ilm) {
+    kal_uint8 conn_id = 0xFF;
+    kal_uint8 conn_status = KPALV_MD_KEEPALIVE_STATE_INACTIVE;
+    kal_uint8 atp_idx = ilm->src_mod_id - MOD_ATP;
+    if(KAL_TRUE == kpalv_receive_keep_alive_query_result(ilm, &conn_id, &conn_status)) {
+        /** found a conection with given at paramers, return status */
+        KPALV_SEND_KEEP_ALIVE_NOTIFY_CNF(KAL_TRUE, conn_id, conn_status, KAL_FALSE, atp_idx);
+    } else {
+        /** no such connection found return ERROR */
+        KPALV_SEND_KEEP_ALIVE_NOTIFY_CNF(KAL_FALSE, conn_id, conn_status, KAL_FALSE, atp_idx);
+    }
+
+}
+kal_bool kpalv_receive_keep_alive_query_result(ilm_struct *ilm, kal_uint8 *conn_id, kal_uint8 *conn_status)
+{
+    kal_uint8 i= 0;
+    kal_uint32 cmp;
+    kal_uint32 cmp1;
+    kal_bool result = KAL_FALSE;
+    /** find a conn based upon input parameters*/
+    atp_kpalv_keepalive_req_struct *at_cmd = (atp_kpalv_keepalive_req_struct *)(ilm->local_para_ptr);
+
+    for(i=0; i < KPALV_MAX_KEEP_ALIVE_CONN; i++)
+    {
+        if((keep_alive_cntx[i].is_cntx_valid == KAL_TRUE) &&
+            (keep_alive_cntx[i].at_info.netif_id == at_cmd->netif_id) &&
+            (keep_alive_cntx[i].at_info.src_port == at_cmd->src_port) &&
+            (keep_alive_cntx[i].at_info.dst_port == at_cmd->dst_port) &&
+            (keep_alive_cntx[i].at_info.ip_type == at_cmd->ip_type))
+        {
+            result = KAL_TRUE;
+        }
+        else
+        {
+            result = KAL_FALSE;
+            continue;
+        }
+
+        if ((at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV6TCP) || (at_cmd->ip_type == KPALV_REQ_IPTYPE_IPV6UDP)) {
+            cmp = kal_mem_cmp(keep_alive_cntx[i].at_info.src_ipv6_addr, at_cmd->src_ipv6_addr, 16);
+            cmp1 = kal_mem_cmp(keep_alive_cntx[i].at_info.dst_ipv6_addr, at_cmd->dst_ipv6_addr, 16);
+            if ((cmp == 0) && (cmp1 == 0)) {
+                result = KAL_TRUE;
+            } else {
+                result = KAL_FALSE;
+                continue;
+            }
+        } else {
+            cmp = (keep_alive_cntx[i].at_info.src_ipv4_addr == at_cmd->src_ipv4_addr);
+            cmp1 = (keep_alive_cntx[i].at_info.dst_ipv4_addr == at_cmd->dst_ipv4_addr);
+            if ((cmp == 0) && (cmp1 == 0)) {
+                result = KAL_TRUE;
+            } else {
+                result = KAL_FALSE;
+                continue;
+            }
+        }
+
+        if(result ==  KAL_TRUE) {
+            *conn_id = i;
+            *conn_status = keep_alive_cntx[i].status;
+            return result;
+        }
+    }
+    return result;
+}
+
+void kpalv_receive_keep_alive_disable_cmd(ilm_struct *ilm)
+{
+    kal_uint8   conn_id = 0;
+    kal_uint8   atp_idx = ilm->src_mod_id - MOD_ATP;
+    kal_bool    result = KAL_TRUE;
+    kal_bool    is_ap_disable_req = KAL_TRUE;
+
+    atp_kpalv_keepalive_req_struct *at_cmd = (atp_kpalv_keepalive_req_struct *)(ilm->local_para_ptr);
+    if(at_cmd->parsing_result == KAL_TRUE) {
+        conn_id = at_cmd->conn_id;
+        /** single conection reset */
+        if (conn_id < 0xFF) {
+            if ((conn_id < KPALV_MAX_KEEP_ALIVE_CONN) && (keep_alive_cntx[conn_id].is_cntx_valid)) {
+                kpalv_stop_keep_alive_for_connection(conn_id);
+            } else {    
+               result = KAL_FALSE;
+            }
+        }
+        /** for all conn reset */
+        if (conn_id == 0xFF) {
+            kpalv_stop_reset_all_connections();        
+        }
+    } else {
+        result = KAL_FALSE;
+    }
+    KPALV_SEND_KEEP_ALIVE_NOTIFY_CNF(result, conn_id, KPALV_MD_KEEPALIVE_STATE_INACTIVE, is_ap_disable_req, atp_idx); 
+}
+
+
+void kpalv_unregister_ul_dl_filter_at_ipc(kal_uint8 conn_id)
+{
+    if (keep_alive_cntx[conn_id].control_info.dl_filter_id >= 0) {
+        ipc_deregister_dl_filter(keep_alive_cntx[conn_id].control_info.dl_filter_id);
+        keep_alive_cntx[conn_id].control_info.dl_filter_id = -1;
+    }
+    if (keep_alive_cntx[conn_id].control_info.ul_filter_id >= 0) {
+        ipc_deregister_ul_filter(keep_alive_cntx[conn_id].control_info.ul_filter_id);
+        keep_alive_cntx[conn_id].control_info.ul_filter_id = -1;
+    }
+}
+
+void kpalv_stop_keep_alive_for_connection(kal_uint8 conn_id)
+{
+    MD_TRC_KPALV_TR_STOP_KEEP_ALIVE_CONN(conn_id);   
+    /*reset at info*/
+    kal_mem_set(&keep_alive_cntx[conn_id].at_info, 0, sizeof(kpalv_keep_alive_at_cmd_info_struct));
+
+    /*stop all the running timers for this connection*/
+    kpalv_stop_idle_timer(conn_id);
+    kpalv_stop_retry_timer(conn_id);
+
+    kpalv_unregister_ul_dl_filter_at_ipc(conn_id);
+    keep_alive_cntx[conn_id].control_info.pdn_id = 0;
+    keep_alive_cntx[conn_id].control_info.ps_id = 0;
+    keep_alive_cntx[conn_id].control_info.curr_retry_attempt = 0;
+
+    keep_alive_cntx[conn_id].is_cntx_valid = KAL_FALSE;
+    keep_alive_cntx[conn_id].status = KPALV_MD_KEEPALIVE_STATE_INACTIVE;
+    //reset the data part for new keep-alive ind
+    kal_mem_set(&keep_alive_cntx[conn_id].data_info, 0, sizeof(kpalv_keep_alive_data_struct));
+}
+
+
+void kpalv_module_clean(void)
+{
+    kal_uint8 i = 0;
+    for (i= 0; i<KPALV_MAX_KEEP_ALIVE_CONN; i++) 
+    {
+        if (keep_alive_cntx[i].is_cntx_valid) {
+            /*reset at info*/
+            kal_mem_set(&keep_alive_cntx[i].at_info, 0, sizeof(kpalv_keep_alive_at_cmd_info_struct));
+            kal_mem_set(&keep_alive_cntx[i].data_info, 0, sizeof(kpalv_keep_alive_data_struct));
+        }
+    }
+}
+
+void kpalv_task_clean_handler(void)
+{
+    kpalv_module_clean();
+}
+
+
+#ifdef ATEST_SYS_KPALV 
+void* kpalv_get_connection_address(kal_uint8 conn_id)
+{
+    return (&keep_alive_cntx[conn_id]);
+}
+
+kal_int32 kpalv_get_connection_ul_filter_id(kal_uint8 conn_id) {
+    return keep_alive_cntx[conn_id].control_info.ul_filter_id;
+}
+
+kal_int32 kpalv_get_connection_dl_filter_id(kal_uint8 conn_id) {
+    return keep_alive_cntx[conn_id].control_info.dl_filter_id;
+}
+#endif
diff --git a/mcu/middleware/kpalv/src/kpalv_task.c b/mcu/middleware/kpalv/src/kpalv_task.c
new file mode 100644
index 0000000..3c4279f
--- /dev/null
+++ b/mcu/middleware/kpalv/src/kpalv_task.c
@@ -0,0 +1,122 @@
+/*****************************************************************************
+ *  Copyright Statement:
+ *  --------------------
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2012
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   kpalv.h
+ *
+ * Project:
+ * --------
+ *   
+ *
+ * Description:
+ * ------------
+ *  keepalive task handling function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ *
+ *
+ ****************************************************************************/
+#include "kal_public_api.h"
+#include "syscomp_config.h"
+#include "kpalv.h"
+#include "kpalv_debug.h"
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+
+kal_bool kpalv_task_init(void)
+{
+    kal_bool result = KAL_TRUE;
+    kpalv_init();
+    return result;
+} 
+
+
+kal_bool kpalv_task_reset(void)
+{
+    kal_bool result = KAL_TRUE;
+    kpalv_reset();
+
+    return result;
+}
+
+
+void kpalv_dispatch_ilm(ilm_struct *ilm)
+{  
+    if (MOD_KPALV == ilm->dest_mod_id) {
+        kal_set_active_module_id(MOD_KPALV);
+        kpalv_ilm_handler(ilm);
+    }
+    
+     /*
+     * Free the ILM.
+     */
+    destroy_ilm(ilm);
+}
+
+
+static void kpalv_task_main(task_entry_struct *task_entry_ptr)
+{
+    ilm_struct current_ilm;
+
+     while (1) {
+        if (KAL_TRUE == msg_receive_extq(&current_ilm)) {
+            kpalv_dispatch_ilm(&current_ilm);
+        }
+    }
+}
+ 
+kal_bool kpalv_create(comptask_handler_struct **handle)
+{
+    static const comptask_handler_struct handler_info = 
+    {
+        kpalv_task_main,       /* task entry function */
+        kpalv_task_init,       /* task initialization function */
+        kpalv_task_reset,      /* task reset handler */
+    };
+
+    *handle = (comptask_handler_struct *)&handler_info;
+
+    return KAL_TRUE;
+}
+
diff --git a/mcu/middleware/kpalv/src/kpalv_ut.c b/mcu/middleware/kpalv/src/kpalv_ut.c
new file mode 100644
index 0000000..bfa3ee2
--- /dev/null
+++ b/mcu/middleware/kpalv/src/kpalv_ut.c
@@ -0,0 +1,1028 @@
+/*****************************************************************************
+ *  Copyright Statement:
+ *  --------------------
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2012
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+ *  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+ *
+ *****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   kpalv_data.c
+ *
+ * Project:
+ * --------
+ *   
+ *
+ * Description:
+ * ------------
+ *  keepalive handling for connection
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ *
+ *
+ ****************************************************************************/
+#ifdef ATEST_SYS_KPALV 
+#include "kal_public_api.h"
+#include "sys_test.h"
+#include "kpalv.h"
+#include "kpalv_msgid.h"
+#include "mw_sap.h"
+#include "qmu_bm.h"
+#include "qmu_bm_util.h"
+#include "atp_kpalv_msgs.h"
+/*------------------------------------------------------------------------------
+ * Public fucntions.
+ *----------------------------------------------------------------------------*/
+static kal_uint8 kpalv_ut_ul_packet_1[] = {
+0x45,0x00,0x00,0x4d,
+0x07,0xda,0x40,0x00,
+0x80,0x06,0x00,0x00,
+0xc0,0xa8,0x00,0x02,
+0xdf,0x68,0xd2,0xa3,
+0x1d,0xe6,0x21,0xb9,
+0x9f,0x4b,0x17,0x11,
+0x70,0x15,0x80,0xd6,
+0x50,0x18,0x02,0x02,
+0x72,0xf6,0x00,0x00,
+0x7e,0x00,0x20,0x00,
+0x02,0x5a,0x16,0x49,
+0xa0,0x54,0x42,0x4f,0x58,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
+0x30,0x30,0x30,0x30,0x30,0x35,0x00,0x00,0x03,0x02,0x00,0x04,
+0x00,0x01,0x00,0xc9,0x7e};
+
+
+static kal_uint8 kpalv_ut_ul_packet_2[] = {
+0x45,0x00,
+0x00,0x4d,0x07,0xdb,0x40,0x00,0x80,0x06,0x00,0x00,0xc0,0xa8,0x00,0x02,0xdf,0x68,
+0xd2,0xa3,0x1d,0xe6,0x21,0xb9,0x9f,0x4b,0x17,0x36,0x70,0x15,0x81,0x20,0x50,0x18,
+0x02,0x02,0x72,0xf6,0x00,0x00,0x7e,0x00,0x20,0x00,0x03,0x5a,0x16,0x49,0xa6,0x54,
+0x42,0x4f,0x58,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x35,
+0x00,0x00,0x03,0x02,0x00,0x04,0x00,0x01,0x00,0xce,0x7e
+};
+
+
+static kal_uint8 kpalv_ut_dl_packet_1[] = {
+0x45,0x00,
+0x00,0x28,0x00,0x3e,0x00,0x00,0xed,0x06,0x5a,0xdb,0xdf,0x68,0xd2,0xa3,0xc0,0xa8,
+0x00,0x02,0x21,0xb9,0x1d,0xe6,0x70,0x15,0x80,0xd6,0x9f,0x4b,0x17,0x36,0x50,0x10,
+0xb3,0xdb,0xa2,0x35,0x00,0x00
+};
+
+//for test tcp seg len
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+
+static kal_uint8 kpalv_ut_dl_packet_2[] = {
+0x45,0x00,
+0x00,0x72,0x00,0x3f,0x00,0x00,0xed,0x06,0x5a,0x90,0xdf,0x68,0xd2,0xa3,0xc0,0xa8,
+0x00,0x02,0x21,0xb9,0x1d,0xe6,0x70,0x15,0x80,0xd6,0x9f,0x4b,0x17,0x36,0x50,0x18,
+0xb4,0x00,0xce,0xa0,0x00,0x00,0x7e,0x00,0x45,0x00,0x2a,0x58,0x68,0x64,0xaa,0x54,
+0x42,0x4f,0x58,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x35,
+0x00,0x00,0x03,0x02,0x00,0x03,0x00,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x68,0x64,0xa9,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x7e
+};
+
+static kal_uint8 kpalv_ut_dl_packet_3[] = {
+0x45,0x00,0x00,0x28,0x00,0x40,0x00,0x00,0xed,0x06,0x5a,0xd9,0xdf,0x68,0xd2,0xa3,0xc0,0xa8,
+0x00,0x02,0x21,0xb9,0x1d,0xe6,0x70,0x15,0x81,0x20,0x9f,0x4b,0x17,0x5b,0x50,0x10,
+0xb3,0xdb,0xa1,0xc6,0x00,0x00
+};
+
+
+//customer logs:
+static kal_uint8 kpalv_ut_ul_packet_3[] = {
+0x45,0x00,0x00,0x29,
+0x07,0xdc,0x40,0x00,
+0x80,0x06,0x00,0x00,
+0xc0,0xa8,0x00,0x02, /*src addr = 0200a8c0 = 33597632*/
+0xdf,0x68,0xd2,0xa3, /*dst addr = a3d268df = 2748475615*/
+0x1d,0xe6,0x21,0xb9,
+0x9f,0x4b,0x17,0x5a,
+0x70,0x15,0x81,0x20,
+0x50,0x10,0x02,0x02,
+0x72,0xd2,0x00,0x00,0x00};
+
+
+//customer logs:
+static kal_uint8 kpalv_ut_dl_packet_4[] = {
+0x45,0x00,0x00,0x28,
+0x00,0x42,0x00,0x00,
+0xed,0x06,0x5a,0xd7,
+0xdf,0x68,0xd2,0xa3,
+0xc0,0xa8,0x00,0x02,
+0x21,0xb9,0x1d,0xe6,
+0x70,0x15,0x81,0x20,
+0x9f,0x4b,0x17,0x5b,
+0x50,0x10,0xb4,0x00,
+0xa1,0xa1,0x00,0x00};
+
+#define KPALV_UT_CASE(_func, _param) { #_func, _func, _param }
+typedef struct {
+    kal_bool        result;
+    kal_bool        is_ap_disable_rsp; /**< ap requested to disable keep-alive */
+    kal_uint8       conn_id;
+    kal_uint8       status;
+    kal_uint8       ps_idx;
+} kpalv_ut_latest_at_cmd_result_struct;
+
+typedef struct {
+    kal_uint8       conn_id;
+    kal_uint8       status;
+    kal_uint8       ps_idx;
+} kpalv_ut_latest_urc_notify_struct;
+
+kpalv_ut_latest_at_cmd_result_struct at_result;
+kpalv_ut_latest_urc_notify_struct urc_result; 
+
+void kpalv_ut_send_keep_alive_notify(kal_bool ok, kal_uint8 conn_handle, kpalv_md_kpalive_state_e state, kal_bool ap_dis_flow, kal_uint8 rsp_ps_idx)
+{
+    at_result.result = ok;
+    at_result.is_ap_disable_rsp = ap_dis_flow;
+    at_result.status = state;
+    at_result.conn_id = conn_handle;
+    at_result.ps_idx = rsp_ps_idx;   
+}
+
+void kpalv_ut_send_keep_alive_notify_urc(kal_uint8 conn_handle, kpalv_md_kpalive_state_e state, kal_uint8 rsp_ps_idx)
+{
+    urc_result.conn_id = conn_handle;
+    urc_result.status = state;
+    urc_result.ps_idx = rsp_ps_idx;
+}
+
+
+kal_bool kpalv_ut_test_first(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    /*temp test case*/
+    return KAL_TRUE;
+}
+
+void kpalv_ut_setup_ipv4_connection_3(atp_kpalv_keepalive_req_struct *req_ptr, kal_bool parsing_result, kal_bool is_tcp) {
+    
+    kal_uint8 src_ipv4_addr[4] = {192,168,0,4};
+    kal_uint8 dst_ipv4_addr[4] = {223,104,201,165};
+    req_ptr->req_type = KPALV_REQ_ENABLE;
+    if(is_tcp == KAL_TRUE) {
+        req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV4TCP;
+        req_ptr->idle_time = 900;
+        req_ptr->probe_interval = 10;
+        req_ptr->retry_cnt = 3;
+    } else {
+        req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV4UDP;
+        req_ptr->idle_time = 900;
+    }
+    req_ptr->netif_id = 0;
+    kal_mem_cpy(req_ptr->src_ipv4_addr, src_ipv4_addr, 4);
+
+    kal_mem_cpy(req_ptr->dst_ipv4_addr, dst_ipv4_addr, 4);
+    req_ptr->src_port = 7656;
+    req_ptr->dst_port = 8667;
+
+    req_ptr->parsing_result = parsing_result;
+}
+
+void kpalv_ut_setup_ipv4_connection_2(atp_kpalv_keepalive_req_struct *req_ptr, kal_bool parsing_result, kal_bool is_tcp) {
+    
+    kal_uint8 src_ipv4_addr[4] = {192,168,0,3};
+    kal_uint8 dst_ipv4_addr[4] = {223,104,201,164};
+    req_ptr->req_type = KPALV_REQ_ENABLE;
+    if(is_tcp == KAL_TRUE) {
+        req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV4TCP;
+        req_ptr->idle_time = 900;
+        req_ptr->probe_interval = 10;
+        req_ptr->retry_cnt = 3;
+    } else {
+        req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV4UDP;
+        req_ptr->idle_time = 900;
+    }
+    req_ptr->netif_id = 0;
+    kal_mem_cpy(req_ptr->src_ipv4_addr, src_ipv4_addr, 4);
+
+    kal_mem_cpy(req_ptr->dst_ipv4_addr, dst_ipv4_addr, 4);
+    req_ptr->src_port = 7655;
+    req_ptr->dst_port = 8666;
+
+    req_ptr->parsing_result = parsing_result;
+}
+
+void kpalv_ut_setup_ipv4_connection(atp_kpalv_keepalive_req_struct *req_ptr, kal_bool parsing_result, kal_bool is_tcp) {
+    
+    kal_uint8 src_ipv4_addr[4] = {192,168,0,2};
+    kal_uint8 dst_ipv4_addr[4] = {223,104,201,163};
+    req_ptr->req_type = KPALV_REQ_ENABLE;
+    if(is_tcp == KAL_TRUE) {
+        req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV4TCP;
+        req_ptr->idle_time = 900;
+        req_ptr->probe_interval = 10;
+        req_ptr->retry_cnt = 3;
+    } else {
+        req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV4UDP;
+        req_ptr->idle_time = 900;
+    }
+    req_ptr->netif_id = 0;
+    kal_mem_cpy(req_ptr->src_ipv4_addr, src_ipv4_addr, 4);
+
+    kal_mem_cpy(req_ptr->dst_ipv4_addr, dst_ipv4_addr, 4);
+    req_ptr->src_port = 7654;
+    req_ptr->dst_port = 8663;
+
+    req_ptr->parsing_result = parsing_result;
+}
+
+void kpalv_ut_setup_ipv6_connection(atp_kpalv_keepalive_req_struct *req_ptr, kal_bool parsing_result, kal_bool is_tcp) {
+    
+    kal_uint8 src_ip_address[] = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
+    kal_uint8 dst_ip_address[] = "2001:0db8:85a3:0000:0000:8a2e:0370:7335";
+
+    req_ptr->req_type = KPALV_REQ_ENABLE;
+    if(is_tcp == KAL_TRUE) {
+        req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV6TCP;
+        req_ptr->idle_time = 900;
+        req_ptr->probe_interval = 10;
+        req_ptr->retry_cnt = 3;
+    } else {
+        req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV6UDP;
+        req_ptr->idle_time = 900;
+    }
+    req_ptr->netif_id = 0;
+
+    req_ptr->src_port = 1000;
+    req_ptr->dst_port = 2000;
+    ipv6addr_convert_string_to_bin((kal_char *)src_ip_address, req_ptr->src_ipv6_addr);
+    ipv6addr_convert_string_to_bin((kal_char *)dst_ip_address, req_ptr->dst_ipv6_addr);
+
+    req_ptr->parsing_result = parsing_result;
+}
+
+void kpalv_ut_setup_ipv6_query(atp_kpalv_keepalive_req_struct *req_ptr, kal_bool parsing_result) {
+    
+    kal_uint8 src_ip_address[] = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
+    kal_uint8 dst_ip_address[] = "2001:0db8:85a3:0000:0000:8a2e:0370:7335";
+
+    req_ptr->req_type = KPALV_REQ_QUERY;
+    req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV6TCP;
+    req_ptr->netif_id = 0;
+
+    req_ptr->src_port = 1000;
+    req_ptr->dst_port = 2000;
+    ipv6addr_convert_string_to_bin((kal_char *)src_ip_address, req_ptr->src_ipv6_addr);
+    ipv6addr_convert_string_to_bin((kal_char *)dst_ip_address, req_ptr->dst_ipv6_addr);
+
+    req_ptr->parsing_result = parsing_result;
+}
+
+void kpalv_ut_setup_ipv4_query(atp_kpalv_keepalive_req_struct *req_ptr, kal_bool parsing_result) {
+    kal_uint8 src_ipv4_addr[4] = {192,168,0,2};
+    kal_uint8 dst_ipv4_addr[4] = {223,104,201,163};
+    req_ptr->req_type = KPALV_REQ_QUERY;
+    req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV4TCP;
+    req_ptr->netif_id = 0;
+    kal_mem_cpy(req_ptr->src_ipv4_addr, src_ipv4_addr, 4);
+
+    kal_mem_cpy(req_ptr->dst_ipv4_addr, dst_ipv4_addr, 4);
+    req_ptr->src_port = 7654;
+    req_ptr->dst_port = 8663;
+    req_ptr->parsing_result = parsing_result;
+}
+
+void kpalv_ut_setup_ipv4_query_udp(atp_kpalv_keepalive_req_struct *req_ptr, kal_bool parsing_result) {
+    kal_uint8 src_ipv4_addr[4] = {192,168,0,2};
+    kal_uint8 dst_ipv4_addr[4] = {223,104,201,163};
+    req_ptr->req_type = KPALV_REQ_QUERY;
+    req_ptr->ip_type = KPALV_REQ_IPTYPE_IPV4UDP;
+    req_ptr->netif_id = 0;
+    kal_mem_cpy(req_ptr->src_ipv4_addr, src_ipv4_addr, 4);
+
+    kal_mem_cpy(req_ptr->dst_ipv4_addr, dst_ipv4_addr, 4);
+    req_ptr->src_port = 7654;
+    req_ptr->dst_port = 8663;
+    req_ptr->parsing_result = parsing_result;
+}
+
+void kpalv_ut_disable_keep_alive(atp_kpalv_keepalive_req_struct *req_ptr, kal_uint8 conn_id, kal_bool parsing_result) {
+    
+    req_ptr->req_type = KPALV_REQ_DISABLE;
+    req_ptr->conn_id = conn_id;
+    req_ptr->parsing_result = parsing_result;
+}
+
+void kpalv_ut_send_ilm_to_kpalv(kal_uint8 ps_idx, atp_kpalv_keepalive_req_struct *req_ptr)
+{   
+    ilm_struct        ilm;
+
+    ilm.src_mod_id = MOD_ATP + ps_idx; //0 for SIM1
+    ilm.dest_mod_id = MOD_KPALV;
+    ilm.sap_id = KPALV_SAP;
+    ilm.msg_id = MSG_ID_ATP_KPALV_KEEPALIVE_REQ;
+    ilm.local_para_ptr = (local_para_struct *)req_ptr;
+    ilm.peer_buff_ptr = NULL;
+
+    kpalv_dispatch_ilm(&ilm);
+}
+
+void kpalv_ut_connections_reset(void) {
+    atp_kpalv_keepalive_req_struct *disable_req_ptr;
+    kal_uint8 proto_idx = 0;
+    disable_req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_disable_keep_alive(disable_req_ptr, 255, KAL_TRUE);
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, disable_req_ptr);
+}
+
+void kpalv_ut_reset(void) {
+    kpalv_ut_connections_reset();
+}
+
+void kpalv_ut_enable_conection_3(void) 
+{
+    atp_kpalv_keepalive_req_struct *enable_req_ptr;
+    kal_uint8 proto_idx =0;
+    /*it mus be first connection*/
+    enable_req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_setup_ipv4_connection_3(enable_req_ptr, KAL_TRUE, KAL_TRUE); //Parsing OK, for TCP
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, enable_req_ptr);
+}
+
+void kpalv_ut_enable_conection_2(void) 
+{
+    atp_kpalv_keepalive_req_struct *enable_req_ptr;
+    kal_uint8 proto_idx =0;
+    /*it mus be first connection*/
+    enable_req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_setup_ipv4_connection_2(enable_req_ptr, KAL_TRUE, KAL_TRUE); //Parsing OK, for TCP
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, enable_req_ptr);
+}
+
+void kpalv_ut_enable_conection(void) 
+{
+    atp_kpalv_keepalive_req_struct *enable_req_ptr;
+    kal_uint8 proto_idx =0;
+    /*it mus be first connection*/
+    enable_req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_setup_ipv4_connection(enable_req_ptr, KAL_TRUE, KAL_TRUE); //Parsing OK, for TCP
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, enable_req_ptr);
+}
+
+void kpalv_ut_enable_udp_conection(void) 
+{
+    atp_kpalv_keepalive_req_struct *enable_req_ptr;
+    kal_uint8 proto_idx =0;
+    /*it mus be first connection*/
+    enable_req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_setup_ipv4_connection(enable_req_ptr, KAL_TRUE, KAL_FALSE); //Parsing OK, for TCP
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, enable_req_ptr);
+}
+
+void kpalv_ut_enable_conection_ipv6(void) 
+{
+    atp_kpalv_keepalive_req_struct *enable_req_ptr;
+    kal_uint8 proto_idx =0;
+    /*it mus be first connection*/
+    enable_req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_setup_ipv6_connection(enable_req_ptr, KAL_TRUE, KAL_TRUE); //Parsing OK, for TCP
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, enable_req_ptr);
+}
+
+kal_bool kpalv_ut_keep_alive_enable_setup(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    /*prepare ilm to send KPALV module*/
+
+    kal_uint8 i = 0;
+    kpalv_ut_reset();
+    
+    kpalv_ut_enable_conection();
+    
+
+    /*chekc enable req rsp*/
+    if ((at_result.is_ap_disable_rsp ==  KAL_FALSE) &&
+        (at_result.result == KAL_TRUE) && 
+        (at_result.conn_id == 0) &&
+        (at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING))
+    {
+        return KAL_TRUE;
+    } else {
+        return KAL_FALSE;
+    }
+}
+
+
+
+kal_bool kpalv_ut_keep_alive_enable_setup_ipv6(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint8 i = 0;
+
+    kpalv_ut_reset();
+    kpalv_ut_enable_conection_ipv6();
+
+    /*chekc enable req rsp*/
+    if ((at_result.is_ap_disable_rsp ==  KAL_FALSE) &&
+        (at_result.result == KAL_TRUE) && 
+        (at_result.conn_id == 0) &&
+        (at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING))
+    {
+        return KAL_TRUE;
+    } else {
+        return KAL_FALSE;
+    }
+
+}
+
+void kpalv_ut_query_connection(kal_bool parse_result) {
+    kal_uint8 proto_idx =0;
+    atp_kpalv_keepalive_req_struct *req_ptr;       
+    req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_setup_ipv4_query(req_ptr, parse_result);
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, req_ptr); 
+}
+
+void kpalv_ut_query_connection_udp_ipv4(kal_bool parse_result) {
+    kal_uint8 proto_idx =0;
+    atp_kpalv_keepalive_req_struct *req_ptr;       
+    req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_setup_ipv4_query_udp(req_ptr, parse_result);
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, req_ptr); 
+}
+
+void kpalv_ut_query_connection_ipv6(kal_bool parse_result) {
+    kal_uint8 proto_idx =0;
+    atp_kpalv_keepalive_req_struct *req_ptr;       
+    req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_setup_ipv6_query(req_ptr, parse_result);
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, req_ptr); 
+}
+
+kal_bool kpalv_ut_keep_alive_query(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kpalv_ut_reset();  
+    kpalv_ut_enable_conection();
+
+    kpalv_ut_query_connection(KAL_TRUE);
+    if ((at_result.conn_id == 0) &&
+        (at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING)) {
+        return KAL_TRUE;
+    } else {
+        return KAL_FALSE;
+    }
+}
+
+void kpalv_ut_disable_connection(kal_uint8 conn_id, kal_bool parse_result)
+{
+    kal_uint8 proto_idx =0;
+    kal_bool result = KAL_TRUE;
+
+    atp_kpalv_keepalive_req_struct *req_ptr;       
+    req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_disable_keep_alive(req_ptr, conn_id, parse_result);
+
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, req_ptr);
+}
+
+kal_bool kpalv_ut_keep_alive_disable(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    
+    kpalv_ut_reset();  
+    kpalv_ut_enable_conection();//get conn_id
+    if(at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING) {
+        kpalv_ut_disable_connection(at_result.conn_id, KAL_TRUE);
+    } else {
+        return KAL_FALSE;
+    }
+
+    //disable req sent , check disable AT rsp
+    if ((at_result.is_ap_disable_rsp ==  KAL_TRUE) &&
+        (at_result.result == KAL_TRUE))
+    {
+        return KAL_TRUE;
+    } else {
+        return KAL_FALSE;
+    }
+
+}
+
+kal_bool kpalv_ut_keep_alive_disable_ipv6(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    
+    kpalv_ut_reset();  
+    kpalv_ut_enable_conection_ipv6();//get conn_id
+    if(at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING) {
+        kpalv_ut_disable_connection(at_result.conn_id, KAL_TRUE);
+    } else {
+        return KAL_FALSE;
+    }
+
+    //disable req sent , check disable AT rsp
+    if ((at_result.is_ap_disable_rsp ==  KAL_TRUE) &&
+        (at_result.result == KAL_TRUE))
+    {
+        return KAL_TRUE;
+    } else {
+        return KAL_FALSE;
+    }
+
+}
+
+void kpalv_ut_send_ul_packet(kal_uint8 index) {
+
+    //simulate the packet from filter cbk
+    void* p_bd = NULL;
+    qbm_gpd *head_gpd;
+    qbm_gpd *tail_gpd;
+    kal_uint8 *ip_header = NULL;
+    kal_uint32 length = 0;
+
+    qbmt_alloc_q(QBM_TYPE_NET_UL_SHRD, 1, (void**)&head_gpd, (void**)&tail_gpd);
+
+    p_bd = QBM_DES_GET_DATAPTR(head_gpd);
+    
+    ip_header = QBM_DES_GET_DATAPTR(p_bd);
+    if(index == 1) {
+        length = sizeof(kpalv_ut_ul_packet_1);
+        kal_mem_cpy(ip_header, kpalv_ut_ul_packet_1, length);
+    }
+    if(index == 2) {
+        length = sizeof(kpalv_ut_ul_packet_2);
+        kal_mem_cpy(ip_header, kpalv_ut_ul_packet_2, length);
+    }
+    /*keep-alive packet*/
+    if(index == 3) {
+        length = sizeof(kpalv_ut_ul_packet_3);
+        kal_mem_cpy(ip_header, kpalv_ut_ul_packet_3, length);
+    }
+
+    QBM_CACHE_FLUSH(ip_header, length);
+    QBM_DES_SET_DATALEN(p_bd, length);
+    qbm_cal_set_checksum(p_bd);
+    QBM_DES_SET_DATALEN(head_gpd, length);
+    qbm_cal_set_checksum(head_gpd);
+
+    kpalv_ul_filter_cbk(NULL, kpalv_get_connection_address(0), kpalv_get_connection_ul_filter_id(0), head_gpd, tail_gpd, length);
+
+}
+
+
+void kpalv_ut_send_dl_packet(kal_uint8 index) {
+
+    //simulate the packet from filter cbk
+    void* p_bd = NULL;
+    qbm_gpd *head_gpd;
+    qbm_gpd *tail_gpd;
+    kal_uint8 *ip_header = NULL;
+    kal_uint32 length = 0;
+
+    qbmt_alloc_q(QBM_TYPE_NET_DL, 1, (void**)&head_gpd, (void**)&tail_gpd);
+
+    p_bd = QBM_DES_GET_DATAPTR(head_gpd);
+    
+    ip_header = QBM_DES_GET_DATAPTR(p_bd);
+    if(index == 1) {
+        length = sizeof(kpalv_ut_dl_packet_1);
+        kal_mem_cpy(ip_header, kpalv_ut_dl_packet_1, length);
+    }
+    if(index == 2) {
+        length = sizeof(kpalv_ut_dl_packet_2);
+        kal_mem_cpy(ip_header, kpalv_ut_dl_packet_2, length);
+    }
+    if(index == 3) {
+        length = sizeof(kpalv_ut_dl_packet_3);
+        kal_mem_cpy(ip_header, kpalv_ut_dl_packet_3, length);
+    }
+    /*keep-alive rsp*/
+    if(index == 4) {
+        length = sizeof(kpalv_ut_dl_packet_4);
+        kal_mem_cpy(ip_header, kpalv_ut_dl_packet_4, length);
+    }
+
+    QBM_CACHE_FLUSH(ip_header, length);
+    QBM_DES_SET_DATALEN(p_bd, length);
+    qbm_cal_set_checksum(p_bd);
+    QBM_DES_SET_DATALEN(head_gpd, length);
+    qbm_cal_set_checksum(head_gpd);
+
+    kpalv_dl_filter_cbk(NULL, kpalv_get_connection_address(0), kpalv_get_connection_dl_filter_id(0), head_gpd, tail_gpd, length);
+
+}
+
+//to chekc State & send keep-alive packet
+void kpalv_ut_idle_poll_tmout_hndlr(kal_uint8 conn_id) {
+    kpalv_idle_poll_tmout_hndlr((void*)kpalv_get_connection_address(conn_id));
+}
+
+//to chekc State & send keep-alive packet
+void kpalv_ut_retry_poll_tmout_hndlr(kal_uint8 conn_id) {
+    kpalv_interval_poll_tmout_hndlr((void*)kpalv_get_connection_address(conn_id));
+}
+
+//get keep-alive ack from server by idle timeout hdlr
+kal_bool kpalv_ut_keep_alive_full_run_idle_tmout(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+
+    kpalv_ut_reset();  
+    kpalv_ut_enable_conection(); //get conn_id
+    if ((at_result.conn_id != 0) &&
+        (at_result.status != KPALV_MD_KEEPALIVE_STATE_PENDING)) {
+        return KAL_FALSE;
+    }
+
+    //after this check the conn_status == ACTIVE
+    kpalv_ut_send_ul_packet(1);
+    if ((urc_result.conn_id != 0) &&
+        (urc_result.status != KPALV_MD_KEEPALIVE_STATE_ACTIVE)) {
+        return KAL_FALSE;
+    }
+    kpalv_ut_send_dl_packet(1);
+
+    kpalv_ut_send_dl_packet(2);
+    kpalv_ut_send_ul_packet(2);
+
+    kpalv_ut_send_dl_packet(3);
+
+    //simulat keepa-live sending
+    //simulate keep-alive ack from server
+    kpalv_ut_idle_poll_tmout_hndlr(0);
+    //kpalv_ut_send_ul_packet(3);
+    
+    kpalv_ut_send_dl_packet(4);
+
+    //after this we can make a query to check the connection status
+    kpalv_ut_query_connection(KAL_TRUE);
+    if ((at_result.conn_id != 0) &&
+            (at_result.status == KPALV_MD_KEEPALIVE_STATE_ACTIVE)) {
+        return KAL_FALSE;
+    }
+    return KAL_TRUE;
+}
+
+//get keep-alive ack from server by Retry timeout hdlr
+kal_bool kpalv_ut_keep_alive_full_run_retry_tmout(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint8 conn_id = 255;
+
+    kpalv_ut_reset();  
+    kpalv_ut_enable_conection(); //get conn_id
+    if ((at_result.conn_id != 0) &&
+        (at_result.status != KPALV_MD_KEEPALIVE_STATE_PENDING)) {
+        return KAL_FALSE;
+    } else {
+        conn_id = at_result.conn_id;
+    }
+
+    kpalv_ut_send_ul_packet(1);
+    if ((urc_result.conn_id != conn_id) &&
+        (urc_result.status != KPALV_MD_KEEPALIVE_STATE_ACTIVE)) {
+        return KAL_FALSE;
+    }
+
+    kpalv_ut_send_dl_packet(1);
+
+    kpalv_ut_send_dl_packet(2);
+    kpalv_ut_send_ul_packet(2);
+
+    kpalv_ut_send_dl_packet(3);
+
+    //simulat keepa-live sending
+    //simulate keep-alive ack from server
+    kpalv_ut_idle_poll_tmout_hndlr(conn_id);
+
+    kpalv_ut_retry_poll_tmout_hndlr(conn_id);
+    kpalv_ut_retry_poll_tmout_hndlr(conn_id);
+    kpalv_ut_retry_poll_tmout_hndlr(conn_id);
+    //send DL packet before last retry timer expire
+    kpalv_ut_send_dl_packet(4);
+
+    //after this we can make a query to check the connection status
+    kpalv_ut_query_connection(KAL_TRUE);
+    if ((at_result.conn_id != 0) &&
+            (at_result.status == KPALV_MD_KEEPALIVE_STATE_ACTIVE)) {
+        return KAL_FALSE;
+    }
+    return KAL_TRUE;
+}
+
+
+
+kal_bool kpalv_ut_keep_alive_full_run_conn_inactive(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kal_uint8 conn_id = 255;
+
+    kpalv_ut_reset();  
+    kpalv_ut_enable_conection();
+    if((at_result.result == KAL_TRUE) && (at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING)) {
+        conn_id = at_result.conn_id;
+    } else {
+        return KAL_FALSE;
+    }
+
+    kpalv_ut_send_ul_packet(1);
+
+    if ((urc_result.conn_id != 0) &&
+        (urc_result.status != KPALV_MD_KEEPALIVE_STATE_ACTIVE)) {
+        return KAL_FALSE;
+    }
+
+    kpalv_ut_send_dl_packet(1);
+
+    kpalv_ut_send_dl_packet(2);
+    kpalv_ut_send_ul_packet(2);
+
+    kpalv_ut_send_dl_packet(3);
+
+    //simulate keepa-live sending by idle timeout
+    //simulate keep-alive ack from server
+    kpalv_ut_idle_poll_tmout_hndlr(conn_id);
+
+    kpalv_ut_retry_poll_tmout_hndlr(conn_id); //Idle timer expire, try 1 
+    kpalv_ut_retry_poll_tmout_hndlr(conn_id); //try 1 timer expire , try 2
+    kpalv_ut_retry_poll_tmout_hndlr(conn_id); //try 2 timer expire , try 3
+    kpalv_ut_retry_poll_tmout_hndlr(conn_id); //try 3 timer expire, no respone from server
+
+    //all retries exhausted, so state must be inactive, get from last urc response
+    if ((urc_result.conn_id != conn_id) &&
+        (urc_result.status != KPALV_MD_KEEPALIVE_STATE_INACTIVE)) {
+        return KAL_FALSE;
+    }
+    
+    return KAL_TRUE;
+}
+kal_bool kpalv_enable_req_with_parsing_result_and_ip_type(kal_bool parse_result, kal_bool is_tcp) {
+    //test wrong cases here
+    atp_kpalv_keepalive_req_struct *req_ptr = NULL;
+    kal_uint8 proto_idx = 0;
+    /*it mus be first connection*/
+    req_ptr = (atp_kpalv_keepalive_req_struct *)construct_local_para(sizeof(atp_kpalv_keepalive_req_struct), TD_RESET);
+    kpalv_ut_setup_ipv4_connection(req_ptr, parse_result, is_tcp);
+    kpalv_ut_send_ilm_to_kpalv(proto_idx, req_ptr); 
+    return KAL_TRUE;
+
+}
+
+
+kal_bool kaplav_enable_req_max_conn_reached_error(void) {
+   
+   kal_uint8 max_conn = KPALV_MAX_KEEP_ALIVE_CONN;
+   kal_uint8 success_conn = 0;
+   
+   kpalv_ut_reset(); //delete all connection before
+
+   //setup connection parsing success +TCP ipv4: different conn
+   kpalv_ut_enable_conection();
+   //check latest at result
+   if ((at_result.conn_id == success_conn) &&
+        (at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING)) {
+        success_conn++;
+    } else {
+        return KAL_FALSE;
+    }
+
+
+   //set up connection 2 ipv4 tcp + parsing success : different conn
+   kpalv_ut_enable_conection_2();
+   if ((at_result.conn_id == success_conn) &&
+        (at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING)) {
+        success_conn++;
+    } else {
+        return KAL_FALSE;
+    }
+
+   //try to setup connection 3 ipv4 tcp + parsing success : different conn, must be ERROR
+
+   kpalv_ut_enable_conection_3();
+   if (max_conn == success_conn) {
+        if (at_result.result == KAL_TRUE) {
+           return KAL_FALSE;
+        }
+   }
+
+   kpalv_ut_reset(); //delete all connection after
+   return KAL_TRUE;
+
+}
+
+//check NON TCP
+//check parsing fail
+//max conn reach error
+kal_bool kpalv_ut_keep_alive_enable_fail_setup(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    
+    kal_uint8 success_conn_id = 255;
+    
+    kpalv_ut_reset();
+
+    kpalv_enable_req_with_parsing_result_and_ip_type(KAL_FALSE, KAL_TRUE); //parse fail + TCP
+    if (at_result.result != KAL_FALSE) {
+        return KAL_FALSE;
+    }
+    kpalv_enable_req_with_parsing_result_and_ip_type(KAL_FALSE, KAL_FALSE); //parse fail + UDP
+    if (at_result.result != KAL_FALSE) {
+        return KAL_FALSE;
+    }
+
+    /*this mus be sucess as parsing SUCCESS + TCP */
+    kpalv_enable_req_with_parsing_result_and_ip_type(KAL_TRUE, KAL_TRUE); //parse success + TCP
+    if (!((at_result.result == KAL_TRUE) ||
+        (at_result.conn_id == 0) || 
+        (at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING))) {
+        return KAL_FALSE;
+    }
+    success_conn_id = at_result.conn_id;
+    /*Duplicate req, result must be ERROR*/
+    kpalv_enable_req_with_parsing_result_and_ip_type(KAL_TRUE, KAL_TRUE); //parse success + TCP
+    if (at_result.result != KAL_FALSE) {
+        return KAL_FALSE;
+    }
+    //double confirm by query or disable cmd
+    {
+        kpalv_ut_query_connection(KAL_TRUE);
+        if ((at_result.conn_id == 0) &&
+            (at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING)) {
+
+        } else {
+            return KAL_FALSE;
+        }
+
+        kpalv_ut_disable_connection(at_result.conn_id, KAL_TRUE);
+        if ((at_result.is_ap_disable_rsp ==  KAL_TRUE) &&
+            (at_result.result == KAL_TRUE))
+        {
+
+        } else {
+            return KAL_FALSE;
+        }
+    }
+
+    /*MAX CONN REACH ERROR */
+    if (KAL_TRUE != kaplav_enable_req_max_conn_reached_error()) {
+        return KAL_FALSE;
+    }
+
+    return KAL_TRUE;
+}
+
+
+kal_bool kpalv_ut_keep_alive_query_fail_rsp(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    
+    kpalv_ut_reset();
+
+    //case 1 parsing result is failed, result must be ERROR
+    kpalv_ut_query_connection(KAL_FALSE);
+    if ((at_result.result == KAL_TRUE)) {
+        return KAL_FALSE;
+    }
+
+    //case 2 parsing success but no such connection, result must be ERROR
+    kpalv_ut_query_connection(KAL_TRUE);
+    if ((at_result.result == KAL_TRUE)) {
+        return KAL_FALSE;
+    }
+
+    return KAL_TRUE;
+}
+
+
+kal_bool kpalv_ut_keep_alive_disable_fail_rsp(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    
+    kal_uint8 conn_id = 255;
+    //reset all connections
+    kpalv_ut_reset();
+    
+    //parsing result failed, result must be ERROR
+    kpalv_ut_disable_connection(0, KAL_FALSE);
+    if(at_result.result == KAL_TRUE) {
+        return KAL_FALSE;
+    }
+
+    //no such conection exist(not enabled), result must be ERROR
+    kpalv_ut_disable_connection(0, KAL_TRUE);
+    if(at_result.result == KAL_TRUE) {
+        return KAL_FALSE;
+    }
+
+    //connection_id >max conn, result must be ERROR
+    kpalv_ut_disable_connection(KPALV_MAX_KEEP_ALIVE_CONN, KAL_TRUE);
+    if(at_result.result == KAL_TRUE) {
+        return KAL_FALSE;
+    }
+
+    //now enable a connection & run the test case again for parsing fail or max conn cases.
+    kpalv_ut_enable_conection(); //setup valid connection.
+    if((at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING) &&
+        (at_result.result == KAL_TRUE)) {
+        conn_id = at_result.conn_id;
+    } else {
+        return KAL_FALSE;
+    }
+    kpalv_ut_disable_connection(conn_id, KAL_FALSE); //parsing result failed
+    if(at_result.result == KAL_TRUE) {
+        return KAL_FALSE;
+    }
+
+    //try to disable some unknown conn_id
+    kpalv_ut_disable_connection((conn_id+1), KAL_TRUE); //invalid conn_id
+    if(at_result.result == KAL_TRUE) {
+        return KAL_FALSE;
+    }
+
+    kpalv_ut_disable_connection(KPALV_MAX_KEEP_ALIVE_CONN, KAL_TRUE); //max conn_id
+    if(at_result.result == KAL_TRUE) {
+        return KAL_FALSE;
+    }
+
+    //finally disbale in correct way, result must be success
+    kpalv_ut_disable_connection(conn_id, KAL_TRUE); //max conn_id
+    if(at_result.result == KAL_FALSE) {
+        return KAL_FALSE;
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool kpalv_ut_keep_alive_query_ipv6(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kpalv_ut_reset();  
+    kpalv_ut_enable_conection_ipv6();
+
+    kpalv_ut_query_connection_ipv6(KAL_TRUE);
+    if ((at_result.conn_id == 0) &&
+        (at_result.status == KPALV_MD_KEEPALIVE_STATE_PENDING)) {
+        return KAL_TRUE;
+    } else {
+        return KAL_FALSE;
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool kpalv_ut_keep_alive_udp_setup_query_disable(void *p_param, kal_char *p_ret_err_str, kal_uint32 *p_ret_err_str_sz) {
+    kpalv_ut_reset();  
+    kpalv_ut_enable_udp_conection();
+    if ((at_result.conn_id != 0) ||
+        (at_result.status != KPALV_MD_KEEPALIVE_STATE_ACTIVE)) {
+        return KAL_FALSE;
+    }
+
+    kpalv_ut_query_connection_udp_ipv4(KAL_TRUE);
+    if ((at_result.conn_id != 0) ||
+        (at_result.status != KPALV_MD_KEEPALIVE_STATE_ACTIVE)) {
+        return KAL_FALSE;
+    }
+
+    kpalv_ut_disable_connection(at_result.conn_id, KAL_TRUE);
+    if ((at_result.is_ap_disable_rsp !=  KAL_TRUE) ||
+            (at_result.result != KAL_TRUE))
+    {
+         return KAL_FALSE;
+    }
+
+    return KAL_TRUE;
+}
+
+kal_bool kpalv_ut_st_create(void) {
+    static ST_TCASE_T kpalv_ut_cases_s[] = {
+        KPALV_UT_CASE(kpalv_ut_test_first, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_enable_fail_setup, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_enable_setup, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_query_fail_rsp, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_query, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_disable_fail_rsp, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_disable, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_full_run_idle_tmout, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_full_run_retry_tmout, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_full_run_conn_inactive, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_enable_setup_ipv6, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_query_ipv6, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_disable_ipv6, NULL),
+        KPALV_UT_CASE(kpalv_ut_keep_alive_udp_setup_query_disable, NULL),   
+    };
+    return st_reg_test("KPALV", &(kpalv_ut_cases_s[0]), (sizeof(kpalv_ut_cases_s)/sizeof(ST_TCASE_T)));
+}
+
+#endif /*ATEST_SYS_KPALV*/
\ No newline at end of file
diff --git a/mcu/middleware/media/audio/src/aud_ilm.c b/mcu/middleware/media/audio/src/aud_ilm.c
new file mode 100644
index 0000000..581ee32
--- /dev/null
+++ b/mcu/middleware/media/audio/src/aud_ilm.c
@@ -0,0 +1,662 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ * aud_ilm.c
+ *
+ * Project:
+ * --------
+ *   Maui
+ *
+ * Description:
+ * ------------
+ *   This file includes send-ilm related funcions of audio manager task.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef MED_NOT_PRESENT
+
+/*==== INCLUDES ===========*/
+
+/* system includes */ 
+#include "kal_general_types.h"
+#include "kal_public_defs.h"
+#include "kal_public_api.h"
+#include "mw_sap.h"
+#include "svc_sap.h"
+#include "drv_sap.h"
+#include "med_msgid.h"
+#include "nvram_msgid.h"
+
+/* global includes */
+#include "l1audio.h"
+#include "nvram_struct.h"
+#include "audio_nvram_def.h"
+ 
+/* local includes */
+#include "med_global.h"
+#include "aud_defs.h"
+#include "med_struct.h"
+#include "med_context.h"
+#include "aud_main.h"
+
+
+#include "string.h"
+ 
+/*****************************************************************************
+ * FUNCTION
+ *  aud_send_ilm
+ * DESCRIPTION
+ *  This function is used to send ilm.
+ * PARAMETERS
+ *  dest_id             [IN]        
+ *  msg_id              [IN]        
+ *  local_param_ptr     [?]         
+ *  peer_buf_ptr        [?]         
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void aud_send_ilm(module_type dest_id, kal_uint16 msg_id, void *local_param_ptr, void *peer_buf_ptr)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    module_type src_id;
+    sap_type sap_id;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    
+    /* Check destination module ID */
+    if (dest_id == MOD_NIL)
+    {
+        return;
+    }
+
+    /* Get source module ID */
+    if (kal_if_hisr())
+    {
+//        src_id = MOD_VISUAL_HISR;
+        return;
+    }
+    else
+    {
+        src_id = kal_get_active_module_id();
+    }
+
+    switch (dest_id)
+    {
+        case MOD_MED:
+            sap_id = MED_SAP;
+            break;
+        case MOD_UEM:
+            sap_id = MED_SAP;
+            break;
+        case MOD_NVRAM:
+            sap_id = PS_NVRAM_SAP;
+            break;
+        default:
+            sap_id = MED_SAP;
+            break;
+    }
+    
+    msg_send6(src_id,dest_id,sap_id,msg_id,(local_para_struct*)local_param_ptr,(peer_buff_struct*)peer_buf_ptr);
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  aud_send_msg_to_nvram
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  msg_name        [IN]        
+ *  ef_id           [IN]        
+ *  data_ptr        [?]         
+ *  length          [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void aud_send_msg_to_nvram(msg_type msg_name, kal_uint16 ef_id, void *data_ptr, kal_uint16 length)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    peer_buff_struct *data_stream;
+    local_para_struct *parm_stream;
+    kal_uint16 pdu_len;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    switch (msg_name)
+    {
+        case MSG_ID_NVRAM_WRITE_REQ:
+            switch (ef_id)
+            {
+                case NVRAM_EF_CUST_ACOUSTIC_DATA_LID:
+                case NVRAM_EF_AUDIO_PARAM_LID:
+                case NVRAM_EF_AUDIO_DC_CALIBRATION_LID:
+            #ifdef __AMRWB_LINK_SUPPORT__
+                case NVRAM_EF_AUDIO_WB_SPEECH_INPUT_FIR_LID:
+                case NVRAM_EF_AUDIO_WB_SPEECH_OUTPUT_FIR_LID:
+                case NVRAM_EF_AUDIO_WB_SPEECH_MODE_PARAM_LID:
+            #endif /* __AMRWB_LINK_SUPPORT__ */
+                    parm_stream = construct_local_para(sizeof(nvram_write_req_struct), TD_CTRL);
+                    data_stream = construct_peer_buff(length, 0, 0, TD_CTRL);
+
+                    ((nvram_write_req_struct*) parm_stream)->file_idx = (kal_uint16) ef_id;
+                    ((nvram_write_req_struct*) parm_stream)->para = 1;
+                    ((nvram_write_req_struct*) parm_stream)->access_id = 0;
+
+                    pdu_len = length;
+                    kal_mem_cpy(get_peer_buff_pdu(data_stream, &pdu_len), data_ptr, length);
+
+                    aud_send_ilm(MOD_NVRAM, MSG_ID_NVRAM_WRITE_REQ, parm_stream, data_stream);
+                    break;
+                default:
+                    /* error write */
+                    break;
+            }
+            break;
+        case MSG_ID_NVRAM_READ_REQ:
+            switch (ef_id)
+            {
+                case NVRAM_EF_CUST_ACOUSTIC_DATA_LID:
+                case NVRAM_EF_AUDIO_PARAM_LID:
+                case NVRAM_EF_AUDIO_DC_CALIBRATION_LID:
+            #ifdef __GAIN_TABLE_SUPPORT__
+                case NVRAM_EF_AUDIO_GAIN_TABLE_LID:
+            #endif /* __GAIN_TABLE_SUPPORT__ */
+            #ifdef __SPEECH_MODE_TABLE_SUPPORT__
+                case NVRAM_EF_AUDIO_SPEECH_MODE_TABLE_LID:
+            #endif /* __SPEECH_MODE_TABLE_SUPPORT__ */
+            #ifdef __AMRWB_LINK_SUPPORT__
+                case NVRAM_EF_AUDIO_WB_SPEECH_INPUT_FIR_LID:
+                case NVRAM_EF_AUDIO_WB_SPEECH_OUTPUT_FIR_LID:
+                case NVRAM_EF_AUDIO_WB_SPEECH_MODE_PARAM_LID:
+            #endif /* __AMRWB_LINK_SUPPORT__ */
+            #ifdef __DUAL_MIC_SUPPORT__
+                case NVRAM_EF_AUDIO_DUAL_MIC_PARAM_LID:
+            #endif
+                    parm_stream = construct_local_para(sizeof(nvram_read_req_struct), TD_CTRL);
+
+                    ((nvram_read_req_struct*) parm_stream)->file_idx = (kal_uint16) ef_id;
+                    ((nvram_read_req_struct*) parm_stream)->para = 1;
+
+                    aud_send_ilm(MOD_NVRAM, MSG_ID_NVRAM_READ_REQ, parm_stream, NULL);
+                    break;
+                default:
+                    /* error read */
+                    break;
+            }
+            break;
+        default:
+            break;
+    }   /* End Switch */
+
+    return;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  aud_send_startup_cnf
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  result      [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void aud_send_startup_cnf(kal_uint8 result)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    med_startup_cnf_struct *cnf_p = NULL;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    cnf_p = (med_startup_cnf_struct*) construct_local_para(sizeof(med_startup_cnf_struct), TD_CTRL);
+
+    /* send confirm message to L4 */
+    cnf_p->result = result;
+
+    aud_send_ilm(aud_context_p->src_mod, MSG_ID_MED_STARTUP_CNF, cnf_p, NULL);
+
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  aud_send_set_audio_profile_cnf
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  result      [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void aud_send_set_audio_profile_cnf(kal_uint8 result)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    media_aud_set_audio_profile_cnf_struct *cnf_p = NULL;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    cnf_p = (media_aud_set_audio_profile_cnf_struct*)
+        construct_local_para(sizeof(media_aud_set_audio_profile_cnf_struct), TD_CTRL);
+
+    /* send confirm message to L4 */
+    cnf_p->src_id = aud_context_p->src_id;
+    if(result == 0) /* MED_RES_OK */
+    {
+        cnf_p->result = KAL_TRUE;
+    }
+    else
+    {
+        cnf_p->result = KAL_FALSE;
+    }
+    cnf_p->cause = result;
+
+    aud_send_ilm(aud_context_p->src_mod, MSG_ID_MEDIA_AUD_SET_AUDIO_PROFILE_CNF, cnf_p, NULL);
+
+}
+
+void aud_send_in_proc_call_req(
+        module_type src_mod_id,
+        media_in_proc_call_type func,
+        kal_uint32 func_arg1,
+        void *func_arg2)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    media_in_proc_call_req_struct *msg_p = (media_in_proc_call_req_struct*)
+        construct_local_para(sizeof(media_in_proc_call_req_struct), TD_CTRL);
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    msg_p->func = func;
+    msg_p->func_arg1 = func_arg1;
+    msg_p->func_arg2 = func_arg2;
+
+    //aud_send_msg_to_med((module_type)src_mod_id, (kal_uint16) MSG_ID_MEDIA_IN_PROC_CALL_REQ, (void *)msg_p);
+    aud_send_ilm(MOD_MED, (kal_uint16) MSG_ID_MEDIA_IN_PROC_CALL_REQ, (void *)msg_p, NULL);
+}
+
+#ifdef __AMRWB_LINK_SUPPORT__
+/*****************************************************************************
+ * FUNCTION
+ *  aud_send_set_audio_wb_input_fir_cnf
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  result      [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void aud_send_set_audio_wb_input_fir_cnf(kal_uint8 result)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    media_aud_set_audio_wb_input_fir_param_cnf_struct *cnf_p = NULL;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    cnf_p = (media_aud_set_audio_wb_input_fir_param_cnf_struct*)
+        construct_local_para(sizeof(media_aud_set_audio_wb_input_fir_param_cnf_struct), TD_CTRL);
+
+    /* send confirm message to L4 */
+    cnf_p->src_id = aud_context_p->src_id;
+
+    if(result == 0) /* MED_RES_OK */
+    {
+        cnf_p->result = KAL_TRUE;
+    }
+    else
+    {
+        cnf_p->result = KAL_FALSE;
+    }
+    cnf_p->cause = result;
+
+    aud_send_ilm(aud_context_p->src_mod, MSG_ID_MEDIA_AUD_SET_AUDIO_WB_INPUT_FIR_PARAM_CNF, cnf_p, NULL);
+
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  aud_send_set_audio_wb_output_fir_cnf
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  input       [IN]
+ *  result      [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void aud_send_set_audio_wb_output_fir_cnf(kal_uint8 result)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    media_aud_set_audio_wb_output_fir_param_cnf_struct *cnf_p = NULL;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    cnf_p = (media_aud_set_audio_wb_output_fir_param_cnf_struct*)
+        construct_local_para(sizeof(media_aud_set_audio_wb_output_fir_param_cnf_struct), TD_CTRL);
+
+    /* send confirm message to L4 */
+    cnf_p->src_id = aud_context_p->src_id;
+
+    if(result == 0) /* MED_RES_OK */
+    {
+        cnf_p->result = KAL_TRUE;
+    }
+    else
+    {
+        cnf_p->result = KAL_FALSE;
+    }
+    cnf_p->cause = result;
+
+    aud_send_ilm(aud_context_p->src_mod, MSG_ID_MEDIA_AUD_SET_AUDIO_WB_OUTPUT_FIR_PARAM_CNF, cnf_p, NULL);
+
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  aud_send_set_audio_wb_mode_cnf
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  result      [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void aud_send_set_audio_wb_mode_cnf(kal_uint8 result)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    media_aud_set_audio_wb_mode_param_cnf_struct *cnf_p = NULL;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    cnf_p = (media_aud_set_audio_wb_mode_param_cnf_struct*)
+        construct_local_para(sizeof(media_aud_set_audio_wb_mode_param_cnf_struct), TD_CTRL);
+
+    /* send confirm message to L4 */
+    cnf_p->src_id = aud_context_p->src_id;
+
+    if(result == 0) /* MED_RES_OK */
+    {
+        cnf_p->result = KAL_TRUE;
+    }
+    else
+    {
+        cnf_p->result = KAL_FALSE;
+    }
+    cnf_p->cause = result;
+
+    aud_send_ilm(aud_context_p->src_mod, MSG_ID_MEDIA_AUD_SET_AUDIO_WB_MODE_PARAM_CNF, cnf_p, NULL);
+
+}
+
+#endif /*__AMRWB_LINK_SUPPORT__*/
+
+/*****************************************************************************
+ * FUNCTION
+ *  aud_send_set_audio_param_cnf
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  result      [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void aud_send_set_audio_param_cnf(kal_uint8 result)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    media_aud_set_audio_param_cnf_struct *cnf_p = NULL;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    cnf_p = (media_aud_set_audio_param_cnf_struct*)
+        construct_local_para(sizeof(media_aud_set_audio_param_cnf_struct), TD_CTRL);
+
+    /* send confirm message to L4 */
+    cnf_p->src_id = aud_context_p->src_id;
+    if(result == 0) /* MED_RES_OK */
+    {
+        cnf_p->result = KAL_TRUE;
+    }
+    else
+    {
+        cnf_p->result = KAL_FALSE;
+    }
+    cnf_p->cause = result;
+
+    aud_send_ilm(aud_context_p->src_mod, MSG_ID_MEDIA_AUD_SET_AUDIO_PARAM_CNF, cnf_p, NULL);
+
+}
+
+#else /* MED_NOT_PRESENT */ 
+
+/*==== INCLUDES ===========*/
+
+/* system includes */ 
+#include "kal_general_types.h"
+#include "kal_public_defs.h"
+#include "kal_public_api.h"
+#include "mw_sap.h"
+#include "svc_sap.h"
+#include "drv_sap.h"
+#include "med_msgid.h"
+#include "nvram_msgid.h"
+
+/* global includes */
+#include "l1audio.h"
+#include "nvram_struct.h"
+#include "audio_nvram_def.h"
+ 
+/* local includes */
+#include "med_global.h"
+#include "aud_defs.h"
+#include "med_struct.h"
+#include "med_context.h"
+#include "aud_main.h"
+
+
+#include "string.h"
+ 
+/*****************************************************************************
+ * FUNCTION
+ *  aud_send_ilm
+ * DESCRIPTION
+ *  This function is used to send ilm.
+ * PARAMETERS
+ *  dest_id             [IN]        
+ *  msg_id              [IN]        
+ *  local_param_ptr     [?]         
+ *  peer_buf_ptr        [?]         
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void aud_send_ilm(module_type dest_id, kal_uint16 msg_id, void *local_param_ptr, void *peer_buf_ptr)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    module_type src_id;
+    sap_type sap_id;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    
+    /* Check destination module ID */
+    if (dest_id == MOD_NIL)
+    {
+        return;
+    }
+
+    /* Get source module ID */
+    if (kal_if_hisr())
+    {
+        src_id = MOD_VISUAL_HISR;//MOD_VISUAL_HISR;//MOD_TIMER_HISR �٬O  MOD_GPT_TIMER
+
+       // return;
+    }
+    else
+    {
+        src_id = kal_get_active_module_id();
+    }
+
+    switch (dest_id)
+    {
+        case MOD_MED:
+            sap_id = MED_SAP;
+            break;
+        case MOD_UEM:
+            sap_id = MED_SAP;
+            break;
+        case MOD_NVRAM:
+            sap_id = PS_NVRAM_SAP;
+            break;
+        default:
+            sap_id = MED_SAP;
+            break;
+    }
+    
+    msg_send6(src_id,dest_id,sap_id,msg_id,(local_para_struct*)local_param_ptr,(peer_buff_struct*)peer_buf_ptr);
+}
+
+void aud_send_in_proc_call_req(
+        module_type src_mod_id,
+        media_in_proc_call_type func,
+        kal_uint32 func_arg1,
+        void *func_arg2)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    media_in_proc_call_req_struct *msg_p = (media_in_proc_call_req_struct*)
+        construct_local_para(sizeof(media_in_proc_call_req_struct), TD_CTRL);
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    msg_p->func = func;
+    msg_p->func_arg1 = func_arg1;
+    msg_p->func_arg2 = func_arg2;
+
+    //aud_send_msg_to_med((module_type)src_mod_id, (kal_uint16) MSG_ID_MEDIA_IN_PROC_CALL_REQ, (void *)msg_p);
+    aud_send_ilm(MOD_MED, (kal_uint16) MSG_ID_MEDIA_IN_PROC_CALL_REQ, (void *)msg_p, NULL);
+
+}
+
+
+#endif /* MED_NOT_PRESENT */ 
+
+
+
diff --git a/mcu/middleware/media/common/src/med_ext_smalloc.c b/mcu/middleware/media/common/src/med_ext_smalloc.c
new file mode 100644
index 0000000..d75afff
--- /dev/null
+++ b/mcu/middleware/media/common/src/med_ext_smalloc.c
@@ -0,0 +1,247 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *  med_ext_smalloc.c
+ *
+ * Project:
+ * --------
+ *  MAUI
+ *
+ * Description:
+ * ------------
+ *  
+ *
+ * Author:
+ * -------
+ *  
+ *
+ *==============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+
+#include "kal_public_defs.h"
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "kal_trace.h"
+
+#include "med_trc.h"
+#include "med_global.h"
+#include "med_mem.h"
+#include "med_smalloc.h"
+#include "init.h"
+
+
+typedef struct{
+    KAL_ADM_ID aud_mem_pool_id;
+    kal_uint32 aud_mem_alloc_count;
+    kal_uint32 aud_mem_left_size;
+}med_ext_mem_struct;
+
+med_ext_mem_struct g_med_ext_mem_cntx;
+
+#if defined(__MED_MEM_CACHEABLE_SUPPORT__)
+#define MED_MEM_CACHEABLE_ALIGN_SIZE  32
+#else
+#define MED_MEM_CACHEABLE_ALIGN_SIZE  4
+#endif
+
+#if defined(__MED_MEM_DEBUG_ON__)
+    #define MED_MEM_ALLOC(adm_id,size,f,l)                          kal_adm_alloc_dbg(adm_id,size,f,l)
+    #define MED_MEM_ALLOC_TOPMOST_CACHEABLE(adm_id, size, a, f, l)  kal_adm_alloc_c_topmost_dbg(adm_id, size, a, f, l)
+    #define MED_MEM_ALLOC_TOPMOST(adm_id, size, a, f, l)            kal_adm_alloc_topmost_dbg(adm_id, size, a, f, l)
+    #define MED_MEM_ALLOC_CACHEABLE(adm_id, size, option, f, l)     kal_adm_alloc_cacheable_dbg(adm_id, size, option, f, l)
+    #define MED_MEM_ALLOC_FRAMEBUFFER(adm_id, size, a, f, l)        kal_adm_alloc_align_dbg(adm_id, size, a, f, l)
+#else
+    #define MED_MEM_ALLOC(adm_id,size,f,l)                          kal_adm_alloc(adm_id,size)
+    #define MED_MEM_ALLOC_TOPMOST(adm_id, size, a, f, l)            kal_adm_alloc_topmost(adm_id, size, a)
+    #define MED_MEM_ALLOC_TOPMOST_CACHEABLE(adm_id, size, a, f, l)  kal_adm_alloc_c_topmost(adm_id, size, a)
+    #define MED_MEM_ALLOC_CACHEABLE(adm_id, size, option, f, l)     kal_adm_alloc_cacheable(adm_id, size, option)
+    #define MED_MEM_ALLOC_FRAMEBUFFER(adm_id, size, a, f, l)        kal_adm_alloc_align(adm_id, size, a)
+#endif
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_ext_smalloc_ext
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  size        [IN]        
+ * RETURNS
+ *  
+ *****************************************************************************/
+address_t med_ext_smalloc_ext(size_type size, unsigned short location, const char *file, int line)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    void *ptr;
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    if (size == 0)
+    {
+        return NULL;
+    }
+
+    switch(location)
+    {
+        case MED_EXT_MEMORY_TYPE_AUDIO_NONCACHEABLE:
+        case MED_EXT_MEMORY_TYPE_AUDIO_CACHEABLE:
+            if (g_med_ext_mem_cntx.aud_mem_pool_id == 0)
+                return NULL;
+        break;
+        default:
+            return NULL;
+    }
+
+    if (location == MED_EXT_MEMORY_TYPE_AUDIO_NONCACHEABLE)
+    {
+        ptr = MED_MEM_ALLOC(g_med_ext_mem_cntx.aud_mem_pool_id, size,basename((char *)file), line);
+    }
+    else if (location == MED_EXT_MEMORY_TYPE_AUDIO_CACHEABLE)
+    {
+        ptr = MED_MEM_ALLOC_CACHEABLE(g_med_ext_mem_cntx.aud_mem_pool_id, size, MED_MEM_CACHEABLE_ALIGN_SIZE, basename((char *)file), line);
+    }
+
+    if (ptr!=NULL)
+    {
+        g_med_ext_mem_cntx.aud_mem_alloc_count++;
+        g_med_ext_mem_cntx.aud_mem_left_size = kal_adm_get_total_left_size(g_med_ext_mem_cntx.aud_mem_pool_id);
+        MED_MEM_INFO_AUD(MED_AUD_MEM_SIZE, size, g_med_ext_mem_cntx.aud_mem_left_size, ptr, g_med_ext_mem_cntx.aud_mem_alloc_count);
+    }
+    else
+    {
+
+        if (size < kal_adm_get_total_left_size(g_med_ext_mem_cntx.aud_mem_pool_id))
+        {
+            /* fragmentation */
+            MED_MEM_FRAGMENTATION_AUD(MED_AUD_MEM_SIZE, size, g_med_ext_mem_cntx.aud_mem_left_size,g_med_ext_mem_cntx.aud_mem_alloc_count);
+        }
+        else
+        {
+            /* concurrent */
+            MED_MEM_CONCURRENT_AUD(MED_AUD_MEM_SIZE, size, g_med_ext_mem_cntx.aud_mem_left_size,g_med_ext_mem_cntx.aud_mem_alloc_count);
+        }
+    }
+    return (address_t) ptr;
+}   /* malloc */
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_aud_sfree
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  ptr     [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void med_aud_sfree(address_t ptr)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    if (ptr!=NULL)
+    {
+        kal_adm_free(g_med_ext_mem_cntx.aud_mem_pool_id, ptr);
+        g_med_ext_mem_cntx.aud_mem_alloc_count--;
+        g_med_ext_mem_cntx.aud_mem_left_size = kal_adm_get_total_left_size(g_med_ext_mem_cntx.aud_mem_pool_id);
+        MED_FREE_MEM_INFO_AUD(g_med_ext_mem_cntx.aud_mem_left_size, ptr, g_med_ext_mem_cntx.aud_mem_alloc_count );
+    }
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_set_aud_memory_pool
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  memory      [IN]        
+ *  size        [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void med_set_aud_memory_pool(address_t memory, size_type size)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    g_med_ext_mem_cntx.aud_mem_pool_id = kal_adm_create(
+                                            memory,
+                                            size,
+                                            NULL,
+                                    #if defined(__MED_MEM_DEBUG_ON__)
+                                            KAL_TRUE
+                                    #else                                            
+                                            KAL_FALSE
+                                    #endif
+                                            );
+    g_med_ext_mem_cntx.aud_mem_alloc_count = 0;
+    g_med_ext_mem_cntx.aud_mem_left_size = size;
+}
+
diff --git a/mcu/middleware/media/common/src/med_main.c b/mcu/middleware/media/common/src/med_main.c
new file mode 100644
index 0000000..87b4610
--- /dev/null
+++ b/mcu/middleware/media/common/src/med_main.c
@@ -0,0 +1,892 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   med_main.c
+ *
+ * Project:
+ * --------
+ *   Maui
+ *
+ * Description:
+ * ------------
+ *   This file includes primary functions of media task.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+
+/*==== INCLUDES =========*/
+
+/* system includes */
+
+#include "kal_public_defs.h"
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "kal_trace.h"
+#include "syscomp_config.h"
+#include "task_config.h"
+#include "nvram_msgid.h"
+#include "sysservice_msgid.h"
+#include "tst_msgid.h"
+#include "med_msgid.h"
+#include "drv_msgid.h"
+#include "cmux_msgid.h"
+#include "audio_msgid.h"
+#include "em_msgid.h"
+
+#include "tst_sap.h"
+#include "drv_sap.h"
+
+
+/* global includes */
+#include "l1audio.h"
+#include "nvram_struct.h"
+#include "audio_nvram_def.h"
+#include "nvram_editor_data_item.h"
+// #include "aud_common_config.h"
+
+/* local include */
+#include "med_global.h"
+#include "med_mem.h"
+#include "med_struct.h"
+#include "med_context.h"
+#include "med_utility.h"
+
+#include "aud_main.h"
+#include "med_main.h"
+
+#ifdef __SPEECH_MODE_TABLE_SUPPORT__
+#include "speech_mode_table.h"
+#endif
+
+//Only for AUDIO_DEVICE_MICROPHONE
+#include "device.h"
+
+#include "em_struct.h"
+
+#if defined(__VOLTE_SUPPORT__)
+#include "ltecsr_msgid.h"
+#endif //#if defined(__VOLTE_SUPPORT__)
+
+
+/* global variables */
+med_context_struct med_context;
+med_context_struct *med_context_p = &med_context;
+
+#ifdef __MTK_TARGET__
+   #if defined(__DYNAMIC_SWITCH_CACHEABILITY__)
+      __attribute__ ((section ("DYNAMICCACHEABLEZI_NC_MMIPOOL"))) 
+      __attribute__((aligned(4)))
+      kal_uint8 med_aud_mem[MED_AUD_MEM_SIZE];
+   #else
+      __attribute__ ((section ("LARGEPOOL_ZI"))) 
+      __attribute__((aligned(4)))
+      kal_uint8 med_aud_mem[MED_AUD_MEM_SIZE];
+   #endif
+#else
+    kal_uint8 med_aud_mem[MED_AUD_MEM_SIZE];
+#endif
+
+
+#if !defined(MED_NOT_PRESENT)
+
+/*==== FUNCTIONS ===========*/
+extern void med_timer_expiry_hdlr(ilm_struct *ilm_ptr);
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_nvram_read_data_cnf_hdlr
+ * DESCRIPTION
+ *  This function is to handle nvram read data confirm.
+ * PARAMETERS
+ *  local_para_ptr      [?]     
+ *  peer_buff_ptr       [?]     
+ * RETURNS
+ *  void
+ *****************************************************************************/
+#if 0
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+            #if defined(__SPEECH_MODE_TABLE_SUPPORT__)
+/* under construction !*/
+            #elif defined(__AMRWB_LINK_SUPPORT__)
+/* under construction !*/
+            #elif defined(__DUAL_MIC_SUPPORT__)
+/* under construction !*/
+            #else
+/* under construction !*/
+            #endif
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+    #ifdef __SPEECH_MODE_TABLE_SUPPORT__        
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+            #if defined(__AMRWB_LINK_SUPPORT__)
+/* under construction !*/
+            #elif defined( __DUAL_MIC_SUPPORT__)
+/* under construction !*/
+            #else
+/* under construction !*/
+            #endif
+/* under construction !*/
+/* under construction !*/
+    #endif /* __SPEECH_MODE_TABLE_SUPPORT__ */
+/* under construction !*/
+    #ifdef __AMRWB_LINK_SUPPORT__
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+            #if defined(__DUAL_MIC_SUPPORT__)
+/* under construction !*/
+            #else
+/* under construction !*/
+            #endif
+/* under construction !*/
+/* under construction !*/
+    #endif /* __AMRWB_LINK_SUPPORT__ */
+/* under construction !*/
+    #ifdef __DUAL_MIC_SUPPORT__
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+        #ifdef __AMRWB_LINK_SUPPORT__
+/* under construction !*/
+        #endif
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+        #ifdef __AMRWB_LINK_SUPPORT__
+/* under construction !*/
+        #endif     
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+    #endif
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+    #ifdef __AMRWB_LINK_SUPPORT__
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+    #endif
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif   // #if 0 
+#endif   // #if !defined(MED_NOT_PRESENT)
+
+//#if !defined(MED_NOT_PRESENT)
+//extern void l1audio_console_handler(kal_char *string); 
+//#endif // 
+/*****************************************************************************
+ * FUNCTION
+ *  med_main
+ * DESCRIPTION
+ *  This function is main message dispatching function of media task.
+ * PARAMETERS
+ *  ilm_ptr     [?]     
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void med_main(ilm_struct *ilm_ptr)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+#if defined(__VOLTE_SUPPORT__)
+    if (ilm_ptr->msg_id == MSG_ID_LTECSR_VOICE_UL_DATA_NOTIFY)
+    {
+#ifndef __MTK_TARGET__
+        return;
+#else //#ifndef __MTK_TARGET__
+       void sp4g_fake_loopback(void);
+       sp4g_fake_loopback();
+#endif //#ifndef __MTK_TARGET__
+    }
+    if (ilm_ptr->msg_id == MSG_ID_LTECSR_VOICE_UL_MUTE_NOTIFY)
+    {
+        return;
+    }
+#endif //#if defined(__VOLTE_SUPPORT__)
+
+#if !defined(MED_NOT_PRESENT)
+    if (ilm_ptr->msg_id == MSG_ID_TIMER_EXPIRY)
+    {
+    	  ASSERT(0);
+        //med_timer_expiry_hdlr(ilm_ptr);
+    }
+    /*else if (ilm_ptr->msg_id == MSG_ID_MED_STARTUP_REQ)
+    {
+        med_startup_hdlr(ilm_ptr);
+    }
+    else if (ilm_ptr->msg_id == MSG_ID_NVRAM_READ_CNF)
+    {
+        med_nvram_read_data_cnf_hdlr(ilm_ptr->local_para_ptr, ilm_ptr->peer_buff_ptr);
+    }
+    else if (ilm_ptr->msg_id == MSG_ID_NVRAM_WRITE_CNF)
+    {
+        med_nvram_write_data_cnf_hdlr(ilm_ptr->local_para_ptr, ilm_ptr->peer_buff_ptr);
+    }
+    else if ( (ilm_ptr->msg_id >= MSG_ID_MED_CODE_BEGIN) && (ilm_ptr->msg_id <= MSG_ID_MED_CODE_TAIL) )
+    {
+        aud_main(ilm_ptr);
+    }*/
+    else if(ilm_ptr->msg_id == MSG_ID_MEDIA_AUD_SP_SET_MODE_REQ)
+	  {
+		   meida_aud_sp_set_mode_req_struct *req_p;
+		   req_p = (meida_aud_sp_set_mode_req_struct*) ilm_ptr->local_para_ptr;
+		   if (req_p->speech_on)
+		   {
+	          L1SP_Speech_On(req_p->rat_mode);	   	
+		   }
+		   else
+		   {
+		      L1SP_Speech_Off();
+		   }
+    }
+
+    else 
+#endif    
+    if (ilm_ptr->msg_id == MSG_ID_TST_INJECT_STRING) {
+	 	tst_module_string_inject_struct *tstInj = (tst_module_string_inject_struct *)ilm_ptr->local_para_ptr;
+		if(tstInj->index == 99 ) {
+			void l1audio_console_handler(kal_char *string);
+			l1audio_console_handler((kal_char *)(tstInj->string));
+		} else {
+			kal_prompt_trace(MOD_MED, "unused inject string index = %d ", tstInj->index);
+		}			
+	} else if(ilm_ptr->msg_id == MSG_ID_L4CPS_EM_UPDATE_REQ ) {
+		l4cps_em_update_req_struct * em_update_ptr = (l4cps_em_update_req_struct *) ilm_ptr->local_para_ptr;
+		if(em_update_ptr->em_src == EM_FROM_ELT) {
+			void SP_setEmCodecNotifyOff(kal_bool isOff);
+			if(EM_OFF == em_update_ptr->info_request[EM_SPEECH_INFO_SPH_CODEC]) {
+				SP_setEmCodecNotifyOff(KAL_TRUE);
+			} else if(EM_ON == em_update_ptr->info_request[EM_SPEECH_INFO_SPH_CODEC]) {
+				SP_setEmCodecNotifyOff(KAL_FALSE);
+			} // EM_NC, no change do nothing
+		} // else from AT do nothing
+	}
+
+	 if (ilm_ptr->msg_id ==  MSG_ID_AUDIO_L4C_EPOF_NOTIFY) {
+#if defined( __SMART_PHONE_MODEM__ )	 	
+		kal_prompt_trace(MOD_L1SP, "[EPOF]med_main receive L4C EPOF notify");
+		set_spcGetEpofTimes(ENUM_EPOF_MD1_L4C_NOTIFY, 1);
+		if( 0 == get_spcGetEpofTimes(ENUM_EPOF_DO_FORCEENDALLAPP) )
+		{
+			void Spc_ForceEndAllApp(void);
+			Spc_ForceEndAllApp();
+		}
+		if(get_spcGetEpofTimes(ENUM_EPOF_AP_ACK_NOTIFY))
+		{
+			//Notify L4C: speech driver enter EPOF done
+			msg_send6(MOD_MED, MOD_L4C, AUDIO_SAP, MSG_ID_AUDIO_L4C_EPOF_ACK, (local_para_struct *)NULL, NULL);
+			kal_prompt_trace(MOD_L1SP, "[EPOF]med_main notify L4C done");
+		}
+#else // #if defined( __SMART_PHONE_MODEM__ )
+		//Notify L4C: speech driver enter EPOF done
+		msg_send6(MOD_MED, MOD_L4C, AUDIO_SAP, MSG_ID_AUDIO_L4C_EPOF_ACK, (local_para_struct *)NULL, NULL);
+		kal_prompt_trace(MOD_L1SP, "[EPOF]med_main notify L4C done 2");
+#endif // #if defined( __SMART_PHONE_MODEM__ )	 	
+	 }
+
+#if defined(SHASTA_L)
+	 if (ilm_ptr->msg_id ==  MSG_ID_AUDIO_C2K_EPOF_NOTIFY) {
+#if defined( __SMART_PHONE_MODEM__ )
+		kal_prompt_trace(MOD_L1SP, "[EPOF]med_main receive C2K EPOF notify");
+		set_spcGetEpofTimes(ENUM_EPOF_C2K_NOTIFY, 1);
+		if( 0 == get_spcGetEpofTimes(ENUM_EPOF_DO_FORCEENDALLAPP) )
+		{
+			Spc_ForceEndAllApp();
+		}
+#endif // #if defined( __SMART_PHONE_MODEM__ )
+	 }
+#endif //#if defined(SHASTA_L)
+
+	if(ilm_ptr->msg_id == MSG_ID_AUDIO_CUST_DUMP_REQ) {
+#if defined( __SMART_PHONE_MODEM__ ) 
+		void spc_sendCustomDump(void *ilm);
+		spc_sendCustomDump(ilm_ptr->local_para_ptr);
+#endif 
+	}
+#if !defined(L1_NOT_PRESENT) && !defined(__UE_SIMULATOR__)
+  #if defined( __DATA_CARD_SPEECH__ )
+    if ( ( (ilm_ptr->msg_id >= CMUX_MSG_CODE_BEGIN) && (ilm_ptr->msg_id <= MSG_ID_CMUX_CODE_TAIL) )
+    	   || ( (ilm_ptr->msg_id >= MSG_ID_SPEECH_ON_ACK) && (ilm_ptr->msg_id <= MSG_ID_STRM_SPEECH_UL_DATA_REQUEST ) )
+    	   || ( (ilm_ptr->msg_id >= DRIVER_MSG_CODE_BEGIN) && (ilm_ptr->msg_id <= MSG_ID_DRIVER_CODE_TAIL) ) )
+    {
+        SP_Strm_Audl_Handler(ilm_ptr);
+    }
+  #endif
+  #if defined( __SMART_PHONE_MODEM__ )
+    if (ilm_ptr->msg_id == MSG_ID_AUDIO_A2M_CCCI)
+    {
+        SpcIO_Msg_Handler_inAudL(ilm_ptr);
+    } else if (ilm_ptr->msg_id == MSG_ID_MEDIA_AUD_MUTE_REQ) {
+    	 /*----------------------------------------------------------------*/
+	    /* Local Variables                                                */
+	    /*----------------------------------------------------------------*/
+	    kal_uint16 cnf_msg_id;
+	    void *cnf_p = NULL;
+
+	    media_aud_mute_req_struct *req_p;
+
+	    /*----------------------------------------------------------------*/
+	    /* Code Body                                                      */
+	    /*----------------------------------------------------------------*/
+	    req_p = (media_aud_mute_req_struct*) ilm_ptr->local_para_ptr;
+
+	    switch (req_p->device)
+	    {
+	        case AUDIO_DEVICE_MICROPHONE:
+	            /* call L1AUD to set microphone mute */
+	            L1SP_MuteMicrophone(req_p->mute);
+	            // aud_context_p->audio_mute = req_p->mute;
+	            break;
+	        default:
+	            break;
+	    }
+
+	    cnf_p = (media_aud_mute_cnf_struct*) construct_local_para(sizeof(media_aud_mute_cnf_struct), TD_CTRL);
+
+	    cnf_msg_id = MSG_ID_MEDIA_AUD_MUTE_CNF;
+
+	    // aud_send_ilm(ilm_ptr->src_mod_id, cnf_msg_id, cnf_p, NULL);
+	    msg_send6(kal_get_active_module_id(),ilm_ptr->src_mod_id,AUDIO_SAP,cnf_msg_id,cnf_p, NULL);
+    }
+  #endif
+#endif
+
+    if ((ilm_ptr->msg_id > MSG_ID_AUDIO_M2M_BEGIN) && (ilm_ptr->msg_id < MSG_ID_AUDIO_M2M_TAIL))
+    {
+        #ifdef __MTK_TARGET__
+        void SP_M2M_Handler(ilm_struct *ilm_ptr);
+        SP_M2M_Handler(ilm_ptr);
+        #endif //#ifdef __MTK_TARGET__
+    }
+#if !defined(__L1_STANDALONE__)    
+    if ((ilm_ptr->msg_id > MSG_ID_AUDIO_L2P_BEGIN) && (ilm_ptr->msg_id < MSG_ID_AUDIO_L2P_TAIL))
+    {
+        #ifdef __MTK_TARGET__
+        void SP_L2P_Handler(ilm_struct *ilm_ptr);
+        SP_L2P_Handler(ilm_ptr);
+        #endif //#ifdef __MTK_TARGET__
+    }        
+#endif   
+#if defined(__VOLTE_SUPPORT__)    
+    if ( ilm_ptr->msg_id == MSG_ID_MEDIA_IN_PROC_CALL_REQ )
+    {
+        #ifdef __MTK_TARGET__
+        void aud_util_in_proc_call_req_hdlr(ilm_struct *ilm_ptr);
+        kal_prompt_trace(MOD_L1SP, "[TONEDEBUG]MSG_ID_MEDIA_IN_PROC_CALL_REQ1");
+        aud_util_in_proc_call_req_hdlr(ilm_ptr);
+        #endif //#ifdef __MTK_TARGET__
+    }
+#endif   
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_task_main
+ * DESCRIPTION
+ *  This function is main function of media task.
+ * PARAMETERS
+ *  task_entry_ptr      [?]     
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void med_task_main(task_entry_struct *task_entry_ptr)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    ilm_struct current_ilm;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+
+#if !defined(L1_NOT_PRESENT) && !defined(__UE_SIMULATOR__)
+    SP_Drv_Init_Task();
+#endif
+
+    while (1)
+    {
+        msg_receive_extq(&current_ilm);
+        
+        kal_set_active_module_id(current_ilm.dest_mod_id);
+
+        med_main((void*)&current_ilm);
+
+        destroy_ilm(&current_ilm);
+    }
+
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_init
+ * DESCRIPTION
+ *  This function is used to init media task.
+ * PARAMETERS
+ *  task_indx       [IN]        
+ * RETURNS
+ *  
+ *****************************************************************************/
+kal_bool med_init(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+#if !defined(MED_NOT_PRESENT)
+    med_context_p->aud_mem_p = med_aud_mem;
+
+    /*if (!aud_init())
+    {
+        return KAL_FALSE;
+    }*/
+#else //#if !defined(MED_NOT_PRESENT)
+    #if defined(__MCU_DTMF_SUPPORT__) 
+    med_context_p->aud_mem_p = med_aud_mem;
+    #endif //#if defined(__MCU_DTMF_SUPPORT__) 
+#endif //#if !defined(MED_NOT_PRESENT)
+
+    if (!med_utility_init())
+    {
+        return KAL_FALSE;
+    }
+
+#if !defined(L1_NOT_PRESENT) && !defined(__UE_SIMULATOR__)
+    if (!SP_Drv_Init_Bootup())
+    {
+        return KAL_FALSE;
+    }
+#endif
+
+    return KAL_TRUE;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_reset
+ * DESCRIPTION
+ *  This function is used to reset media task.
+ * PARAMETERS
+ *  task_indx       [IN]        
+ * RETURNS
+ *  
+ *****************************************************************************/
+kal_bool med_reset(void)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    return KAL_TRUE;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_create
+ * DESCRIPTION
+ *  This function is used to create media task configuration info.
+ * PARAMETERS
+ *  handle      [IN]        
+ * RETURNS
+ *  
+ *****************************************************************************/
+kal_bool med_create(comptask_handler_struct **handle)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    static const comptask_handler_struct med_handler_info = 
+    {
+        med_task_main,  /* task entry function */
+        med_init,       /* task initialization function */
+        med_reset       /* task reset handler */
+    };
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    *handle = (comptask_handler_struct*) & med_handler_info;
+
+    return KAL_TRUE;
+}
+
diff --git a/mcu/middleware/media/common/src/med_utility.c b/mcu/middleware/media/common/src/med_utility.c
new file mode 100644
index 0000000..f85efd1
--- /dev/null
+++ b/mcu/middleware/media/common/src/med_utility.c
@@ -0,0 +1,288 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ * med_utility.c
+ *
+ * Project:
+ * --------
+ *   Maui
+ *
+ * Description:
+ * ------------
+ *   This file includes common used functions of media task.
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *------------------------------------------------------------------------------
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
+ *==============================================================================
+ *******************************************************************************/
+
+/*==== INCLUDES =========*/
+#include "kal_public_defs.h"
+#include "kal_public_api.h"
+#include "kal_general_types.h"
+#include "kal_trace.h"
+
+/* global includes */
+#include "l1audio.h"
+
+/* local includes */
+#include "med_main.h"
+#include "med_global.h"
+#include "med_mem.h"
+#include "med_struct.h"
+#include "med_context.h"
+#include "med_smalloc.h"
+#include "med_utility.h"
+#include "med_trc.h"
+#include "aud_main.h"
+
+kal_mutexid med_mem_mutex;
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_alloc_ext_mem
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  size        [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void *med_alloc_ext_mem_ext(kal_int32 size, kal_uint8 location, char* file_p, long line_p)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    void *p = NULL;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    kal_take_mutex(med_mem_mutex);
+    p = (void*)med_ext_smalloc_ext((size_type) size, location, file_p, line_p);
+    kal_give_mutex(med_mem_mutex);
+
+    return p;
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_free_aud_mem_ext
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  pointer     [IN]        
+ * RETURNS
+ *  void
+ *****************************************************************************/
+void med_free_aud_mem_ext(void **pointer,char* file_p, long line_p)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    kal_take_mutex(med_mem_mutex);
+    med_aud_sfree((address_t) * pointer);
+    kal_give_mutex(med_mem_mutex);
+    *pointer = NULL;
+}
+
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_util_alloc_aud_mem
+ * DESCRIPTION
+ *  This function is to allocate memory from audio memory pool.
+ * PARAMETERS
+ *  size        [IN]        Memory size to be allocated.
+ *  file_p      [IN]        File name.
+ *  line        [IN]        Line number in the file.
+ * RETURNS
+ *  Allocated memory address
+ *****************************************************************************/
+static void* med_util_alloc_aud_mem(kal_uint32 size, char* file_p, long line)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/ 
+    return med_alloc_ext_mem_ext(size, MED_EXT_MEMORY_TYPE_AUDIO_NONCACHEABLE, file_p, line);
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_util_alloc_aud_cacheable_mem
+ * DESCRIPTION
+ *  This function is to allocate cacheable memory from audio memory pool.
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  Allocated memory address
+ *****************************************************************************/
+static void* med_util_alloc_aud_cacheable_mem(kal_uint32 size, char* file_p, long line)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/ 
+    return med_alloc_ext_mem_ext(size, MED_EXT_MEMORY_TYPE_AUDIO_CACHEABLE, file_p, line);
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_util_free_aud_mem
+ * DESCRIPTION
+ *  This function is to free audio memory.
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  Allocated memory address
+ *****************************************************************************/
+static void med_util_free_aud_mem(void** mem_p, char* file_p, long line)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    med_free_aud_mem_ext(mem_p, file_p, line);
+}
+
+/*****************************************************************************
+ * FUNCTION
+ *  med_utility_init
+ * DESCRIPTION
+ *  
+ * PARAMETERS
+ *  void
+ * RETURNS
+ *  
+ *****************************************************************************/
+kal_bool med_utility_init(void)
+{
+
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    Media_Func_Reg_Type media_func;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    
+    med_mem_mutex = kal_create_mutex("MED MEM");
+    
+    /* Register callback functions to L1audio */
+    media_func.alloc_mem           = med_util_alloc_aud_mem;
+    media_func.alloc_mem_cacheable = med_util_alloc_aud_cacheable_mem;
+    media_func.free_mem            = med_util_free_aud_mem;
+    media_func.set_path_volume     = NULL;
+    media_func.get_active_mode     = NULL;
+#if defined(__VOLTE_SUPPORT__)    
+    media_func.send_proc_call      = aud_send_in_proc_call_req;   // is only used in VoLTE DTMF MCU destroy functions
+#else
+    media_func.send_proc_call      = NULL;   
+#endif    
+    media_func.send_proc_call2     = NULL;
+    media_func.get_meta_file       = NULL;
+    media_func.get_meta_array      = NULL;
+    
+#if !defined(L1_NOT_PRESENT)
+    Audio_MedFuncReg(&media_func);
+#endif
+
+    /* init audio memory */
+    med_set_aud_memory_pool((unsigned char*)med_context_p->aud_mem_p, MED_AUD_MEM_SIZE);
+
+    return KAL_TRUE;
+}
+
+
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_aux.h b/mcu/middleware/meta/ft/inc/ft_fnc_aux.h
new file mode 100644
index 0000000..b8f1aa9
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_aux.h
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_aux.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  Auxiliary Function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+ 
+#if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+#ifndef _FT_FNC_AUX_H_
+#define _FT_FNC_AUX_H_
+// added in RHR first round
+#include "kal_public_api.h"
+
+void FT_Aux_Operation(ilm_struct *ptrMsg);
+void FT_Handle_FTA_CNF(ilm_struct *ptrMsg);
+
+
+#endif //#ifndef _FT_FNC_MISC_H_
+
+#endif // end of #if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_c2krf.h b/mcu/middleware/meta/ft/inc/ft_fnc_c2krf.h
new file mode 100644
index 0000000..8a3220e
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_c2krf.h
@@ -0,0 +1,83 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2016
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2016
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_c2krf.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT private API definition (Category: C2KRF)
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *        HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __FT_FNC_C2KRF_H__
+#define __FT_FNC_C2KRF_H__
+#if defined(__C2K_RAT__)
+#include "ft_msg.h"
+void FT_Crf_Operation(ilm_struct *ptrMsg);
+void FT_Crf_ConfirmHandler(ilm_struct* crfMessage);
+#endif // #if defined(__C2K_RAT__)
+#endif // #ifndef __FT_FNC_C2KRF_H__
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_custom.h b/mcu/middleware/meta/ft/inc/ft_fnc_custom.h
new file mode 100644
index 0000000..1d41569
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_custom.h
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_custom.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  Customer Function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#ifndef _FT_FNC_CUSTOM_H_
+#define _FT_FNC_CUSTOM_H_
+// added in RHR first round
+#include "kal_public_api.h"
+
+void FT_Custom_Operation(ilm_struct *ptrMsg);
+void FT_Handle_FTC_CNF(ilm_struct *ptrMsg);
+
+
+#endif //#ifndef _FT_FNC_MISC_H_
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_fat.h b/mcu/middleware/meta/ft/inc/ft_fnc_fat.h
new file mode 100644
index 0000000..7f81341
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_fat.h
@@ -0,0 +1,123 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_fat.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT FAT operation header file
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef _FT_FNC_FAT_H_
+#define _FT_FNC_FAT_H_
+#include "ft_msg.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+*
+*  FAT directory structure traverse
+*
+*******************************************************************************/
+#define FT_FAT_FIND_NOT_FOUND	0xFF
+
+typedef	enum {
+	FT_FAT_FIND_FILE = 0,
+	FT_FAT_FIND_FILE_RECURSIVE,
+	FT_FAT_FIND_DIR_RECURSIVE
+}FT_FAT_FIND_MODE;
+
+typedef	kal_int8 (*FT_FAT_FIND_CALLBACK)(const WCHAR *fullpath, const FS_DOSDirEntry  *dos_info, void *usr_arg);
+
+extern kal_uint8 ft_fat_find(const WCHAR *base_path, const WCHAR *find_pattern, FT_FAT_FIND_MODE  mode, FT_FAT_FIND_CALLBACK  cb, void *usr_arg);
+
+/* FAT */
+#define FT_FAT_ASSERT_UNKNOWN_OP	0
+#define FT_FAT_MAX_FULLPATH			FS_MAX_PATH
+#define FT_FAT_MAX_FILENAME		 (FS_MAX_PATH-20)
+#define FT_FAT_MAX_DIR_DEPTH		300
+
+typedef struct {
+	FS_HANDLE	fs_handle;
+}ft_fat_dir_info;
+
+extern void FT_FAT_Operation(FT_FAT_OPERATION *ft_fat_op, peer_buff_struct *peer_buff_in);
+kal_int32 FT_GetDiskFreeSpace(const WCHAR* pathname);
+kal_int32 ft_CreateFullDirectory(const WCHAR *pathname);
+kal_int16 FT_GetAvailableDrive(kal_int32 size);
+
+#ifdef __cplusplus
+}
+#endif // #ifdef __cplusplus
+
+#endif // #ifndef _FT_FNC_FAT_H_
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_l1rf.h b/mcu/middleware/meta/ft/inc/ft_fnc_l1rf.h
new file mode 100644
index 0000000..8ba7b0c
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_l1rf.h
@@ -0,0 +1,154 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_l1rf.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT private API definition (Category: L1RF)
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __FT_FNC_L1RF_H__
+#define __FT_FNC_L1RF_H__
+#if defined(__MTK_GL1_GSM__) || defined(__L1SIM_NR_SM__) || defined(__NR_L1SIM__)
+#include "ft_msg.h"
+extern kal_uint8 FT_UTIL_SendCnf(const FT_UTILITY_COMMAND_CNF  *cnf, peer_buff_struct *p_peer_buff);
+void FT_Rf_Operation(ilm_struct *ptrMsg);
+void FT_Rf_ConfirmHandler(ilm_struct* rfMessage);
+void FT_RfCheckFunctionSupported(kal_uint32 query_op_code);
+#endif // #if defined(__MTK_GL1_GSM__)
+#endif // #ifndef __FT_FNC_L1RF_H__
+
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_l4.h b/mcu/middleware/meta/ft/inc/ft_fnc_l4.h
new file mode 100644
index 0000000..42bb645
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_l4.h
@@ -0,0 +1,6 @@
+
+#ifndef __FT_FNC_L4_H__
+#define __FT_FNC_L4_H__
+#include "ft_msg.h"
+void FT_L4_Operation(ilm_struct *ptrMsg);
+#endif // #ifndef __FT_FNC_L4_H__
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_lterf.h b/mcu/middleware/meta/ft/inc/ft_fnc_lterf.h
new file mode 100644
index 0000000..2dd04ee
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_lterf.h
@@ -0,0 +1,108 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_lterf.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT private API definition (Category: LTERF)
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __FT_FNC_LTERF_H__
+#define __FT_FNC_LTERF_H__
+#include "ft_msg.h"
+extern kal_uint8 FT_UTIL_SendCnf(const FT_UTILITY_COMMAND_CNF  *cnf, peer_buff_struct *p_peer_buff);
+void FT_Erf_Operation(ilm_struct *ptrMsg);
+void FT_PhyTool_Operation(ilm_struct *ptrMsg);
+void FT_Erf_ConfirmHandler(ilm_struct* erfMessage);
+void FT_ErfCheckFunctionSupported(kal_uint32 query_op_code);
+#endif // #ifndef __FT_FNC_LTERF_H__
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_misc.h b/mcu/middleware/meta/ft/inc/ft_fnc_misc.h
new file mode 100644
index 0000000..7b7cc2e
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_misc.h
@@ -0,0 +1,113 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_misc.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  Misc Function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#ifndef _FT_FNC_MISC_H_
+#define _FT_FNC_MISC_H_
+#include "kal_public_defs.h"
+#include "kal_public_api.h"
+#include "nvram_struct.h"
+
+#define FT_SML_VALID        0x00
+#define FT_SML_INVALID      0x01
+#define FT_SML_NO_FILENAME  0x02
+
+kal_uint32 FT_MiscCheckFunctionSupported(kal_uint32 query_op_code);
+void FT_MISC_Operation(ilm_struct *ptrMsg);
+kal_uint8  FT_MISC_SendCnf(FT_MISC_CNF *ft_misc_ret, peer_buff_struct *peer_buff);
+
+extern kal_uint16 ft_gl_misc_token; 
+
+void FT_Misc_CalDataInTargetAddOneRequestHandler(ilm_struct *ptrMsg);
+kal_bool FT_Misc_CalDataRecordItemProcess(kal_uint16 fileIdx, kal_uint16 recordId);
+
+#endif  // end of #ifndef _FT_FNC_MISC_H_
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_misc_ex.h b/mcu/middleware/meta/ft/inc/ft_fnc_misc_ex.h
new file mode 100644
index 0000000..496766f
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_misc_ex.h
@@ -0,0 +1,111 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_misc.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  Misc Function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#ifndef _FT_FNC_MISC_EX_H_
+#define _FT_FNC_MISC_EX_H_
+#include "kal_public_api.h"
+
+#define FT_MISC_EX_DATA_FRAME_SIZE 1800
+
+kal_uint32 FT_MiscExCheckFunctionSupported(kal_uint32 query_op_code);
+void FT_MISC_EX_Operation(ilm_struct *ptrMsg);
+void FT_MiscEx_NvramConfirmHandler(ilm_struct* ptrMsgCnf);
+extern kal_uint16 ft_gl_misc_ex_token;
+
+enum META_BP_AREA_STATUS_E
+{
+	META_BP_AREA_STATUS_OK = 0
+   ,META_BP_AREA_STATUS_EMPTY
+   ,META_BP_AREA_STATUS_BROKEN
+   ,META_BP_AREA_STATUS_NO_SYNC
+   ,META_BP_AREA_STATUS_UNKNOWN
+
+};
+
+#endif  // end of #ifndef _FT_FNC_MISC_H_
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_mmrf.h b/mcu/middleware/meta/ft/inc/ft_fnc_mmrf.h
new file mode 100644
index 0000000..1ebf256
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_mmrf.h
@@ -0,0 +1,101 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_mmrf.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT private API definition (Category: MMRF)
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __FT_FNC_MMRF_H__
+#define __FT_FNC_MMRF_H__
+#include "kal_public_defs.h"
+extern kal_uint8 FT_UTIL_SendCnf(const FT_UTILITY_COMMAND_CNF  *cnf, peer_buff_struct *p_peer_buff);
+void FT_Mmrf_Operation(ilm_struct* ptrMsg);
+void FT_Mmrf_ConfirmHandler(ilm_struct* mmrfMessage);
+void FT_MmrfCheckFunctionSupported(kal_uint32 query_op_code);
+void FT_Mmrf_UpdateRuntimeConfirmHandler(ilm_struct *ptrMsg);
+void FT_Mmrf_UpdateRuntimeHandler(peer_buff_struct* peer_buff, kal_uint16 lid, kal_uint16 rid);
+kal_bool FT_Mmrf_PollUpdateRuntimeReady();
+#endif // #ifndef __FT_FNC_MMRF_H__
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_nrf.h b/mcu/middleware/meta/ft/inc/ft_fnc_nrf.h
new file mode 100644
index 0000000..e2ea164
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_nrf.h
@@ -0,0 +1,70 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_nr.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT private API definition (Category: NR)
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __FT_FNC_NRF_H__
+#define __FT_FNC_NRF_H__
+#include "kal_public_defs.h"
+void FT_Nrf_Operation(ilm_struct* ptrMsg);
+void FT_Nrf_ConfirmHandler(ilm_struct* nrMessage);
+#endif // #ifndef __FT_FNC_NRF_H__
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_nvram.h b/mcu/middleware/meta/ft/inc/ft_fnc_nvram.h
new file mode 100644
index 0000000..641b1f9
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_nvram.h
@@ -0,0 +1,128 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_nvram.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT NVRAM operation header file
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef _FT_FNC_NVRAM_H_
+#define _FT_FNC_NVRAM_H_
+#include "ft_msg.h"
+#include "nvram_struct.h"
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef void (*fp_nvram_read_handler_t)(ft_nvram_read_req_struct_T* req, kal_uint8 ftAccessId);
+typedef void (*fp_nvram_read_confirm_handler_t)(nvram_read_cnf_struct*, peer_buff_struct*);
+typedef void (*fp_nvram_write_handler_t)(ft_nvram_write_req_struct_T* req, peer_buff_struct* peer_buff, kal_uint8 ftAccessId);
+typedef void (*fp_nvram_write_confirm_handler_t)(nvram_write_cnf_struct*);
+
+extern fp_nvram_read_handler_t FT_ReadFrom_NVRAM;
+extern fp_nvram_read_confirm_handler_t FT_ReadFrom_NVRAM_CNF;
+extern fp_nvram_write_handler_t FT_WriteTo_NVRAM;
+extern fp_nvram_write_confirm_handler_t FT_WriteTo_NVRAM_CNF;
+void FT_Nvram_SendReadRequestToNvram(kal_uint16, kal_uint16, kal_uint8 accessId);
+void FT_Nvram_ReadNvramHandler(ft_nvram_read_req_struct_T* req, kal_uint8 accessId);
+void FT_NvramSec_ReadNvramHandler(ft_nvram_read_req_struct_T* req, kal_uint8 accessId);
+void FT_Nvram_ReadNvramConfirmHandler(nvram_read_cnf_struct*, peer_buff_struct*);
+void FT_Nvram_WriteNvramHandler(ft_nvram_write_req_struct_T* req, peer_buff_struct* peer_buff, kal_uint8 accessId);
+void FT_NvramSec_WriteNvramHandler(ft_nvram_write_req_struct_T* req, peer_buff_struct* peer_buff, kal_uint8 accessId);
+void FT_Nvram_WriteNvramConfirmHandler(nvram_write_cnf_struct*);
+
+void FT_Nvram_SendReadResponseToHost(nvram_read_cnf_struct* nvramReadCnf, peer_buff_struct* nvramReadCnfPeerBuf, kal_bool holdBufferForRelay);
+void FT_Nvram_SendWriteResponseToHost(nvram_write_cnf_struct* nvramWriteCnf);
+kal_bool FT_Nvram_IsModNvramRespnose(ilm_struct* ilm_ptr);
+void FT_Nvram_SendWriteCommandToNvram(peer_buff_struct* peer_buff, kal_uint16 lid, kal_uint16 rid, kal_uint8 ftAccessId, kal_bool holdBufferForRelay);
+void FT_Nvram_SendReadCommandToNvram(kal_uint16 lid, kal_uint16 rid, kal_uint8 ftAccessId);
+
+#define FT_NVRAM_ACCESS_ID_CAL_INTEGRITY_OP 0x1
+#ifdef __cplusplus
+}
+#endif // #ifdef __cplusplus
+
+#endif // #ifndef _FT_FNC_NVRAM_H_
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_tdscdma.h b/mcu/middleware/meta/ft/inc/ft_fnc_tdscdma.h
new file mode 100644
index 0000000..93c1f61
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_tdscdma.h
@@ -0,0 +1,81 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_tdscdma.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  TD-SCDMA Function header
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#ifndef _FT_FNC_TDSCDMA_H_
+#define _FT_FNC_TDSCDMA_H_
+#if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+
+//20130206
+/*************************************************************************
+ * Include Statements for MAUI
+ *************************************************************************/ 
+#include "tl1_struct.h"
+#include "tl1_cc_public.h"
+
+#endif // #if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+#endif // #ifndef _FT_FNC_TDSCDMA_H_
diff --git a/mcu/middleware/meta/ft/inc/ft_fnc_wcdma.h b/mcu/middleware/meta/ft/inc/ft_fnc_wcdma.h
new file mode 100644
index 0000000..4f80bbb
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_fnc_wcdma.h
@@ -0,0 +1,137 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_wcdma.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  WCDMA Function header
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#ifndef _FT_FNC_WCDMA_H_
+#define _FT_FNC_WCDMA_H_
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#include "ft_msg.h"
+/*************************************************************************
+ * Include Statements for MAUI
+ *************************************************************************/ 
+extern kal_uint8 FT_UTIL_SendCnf(const FT_UTILITY_COMMAND_CNF  *cnf, peer_buff_struct *p_peer_buff);
+void FT_UL1RfCheckFunctionSuppported(kal_uint32 query_op_code);
+void FT_FtURfTestReq(ilm_struct *ptrMsg);
+void FT_UL1TST_SEND_CNF_BACK(ilm_struct *ptrMsg_ul1tst);
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#endif // #ifndef _FT_FNC_WCDMA_H_
diff --git a/mcu/middleware/meta/ft/inc/ft_mem.h b/mcu/middleware/meta/ft/inc/ft_mem.h
new file mode 100644
index 0000000..32afadd
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_mem.h
@@ -0,0 +1,84 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_mem.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT memory management functions
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#ifndef __FT_MEM_H__
+#define __FT_MEM_H__
+void  FtInitMemoryPool(void);
+void* FtAllocExtMemory(kal_uint32 size);
+void  FtFreeExtMemory(void* ptr);
+kal_uint32 FtGetLeftExtMemory(void);
+#endif // #ifndef __FT_MEM_H__
diff --git a/mcu/middleware/meta/ft/inc/ft_private.h b/mcu/middleware/meta/ft/inc/ft_private.h
new file mode 100644
index 0000000..3a9f9c6
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_private.h
@@ -0,0 +1,302 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_private.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT private stuff
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef FT_PRIVATE_H
+#define FT_PRIVATE_H
+
+#include "ft_msg.h"
+#include "kal_public_api.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_config.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_msgs.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_common.h"
+#ifndef L1_SIM
+#include "nvram_struct.h"
+#include "fs_type.h"
+#endif // #ifndef L1_SIM
+#include "kal_general_types.h"
+#include "kal_public_defs.h"
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#include "ul1cal.h"
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+/***********************
+ * TST module APIs
+ **********************/
+#include "kal_trace.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+extern kal_uint16   ft_gl_token;
+extern kal_uint16   ft_gl_rf_token;
+extern kal_uint16   ft_gl_l4aud_token;
+extern kal_uint16	ft_gl_l4aud_ind_token;
+extern kal_uint16	ft_gl_l4aud_current_volume;
+extern peer_buff_struct	*ft_gl_l4aud_peer_buf;
+extern kal_uint16   ft_gl_nvram_token;
+
+//extern kal_bool		g_META_DLL_Version_Incorrect;
+extern kal_bool   g_b_ft_assert_check_enable;
+extern kal_bool   g_b_ver_Incorrect;
+extern kal_uint8  g_u1_msg_recv_times;
+
+#ifndef L1_SIM
+/*  for build warning */
+extern void FT_FtPMICRegisterRead(ft_PMICRegisterRead_req_T* req, unsigned char RegType);
+extern void FT_FtPMICRegisterWrite(ft_PMICRegisterWrite_req_T* req, unsigned char RegType);
+#endif // #ifndef L1_SIM
+
+/* for backup and restore calibration data */
+extern kal_uint8  ft_gl_path_check_flag;
+/* for ft event group pointer */
+#define FT_EVENT_TIMEOUT                5000       // 10 sec
+extern kal_uint32 ft_event_group_ptr;              // event bit map in ft_public.h
+/* ------------------------------------------------------------------------- */
+/*******************************************************************************
+*
+*  ft_fnc.c
+*
+*******************************************************************************/
+void FT_DispatchMessage(ilm_struct* ptrMsg);
+void FT_InitCalibrationData(task_entry_struct *task_entry_ptr);
+void FT_InitFtData(void);
+#ifndef L1_SIM
+/* BaseBand Testing */
+void FT_FtRegisterRead         (ft_RegisterRead_req_T       *req, unsigned char RegType);
+void FT_FtRegisterWrite        (ft_RegisterWrite_req_T      *req, unsigned char RegType);
+void FT_FtADC_GetMeaData       (ft_FtADC_GetMeaData_req_T   *req);
+#endif // #ifndef L1_SIM
+/* Version Info */
+extern void FT_GetVersionInfo(void);
+
+/* FT task test alive */
+extern void FT_TestAlive(void);
+
+#ifndef L1_SIM
+/* FT task Power Off */
+extern void FT_PowerOff(void);
+
+/* SLA */
+extern void FT_GetSlaStatus(void);
+extern void FT_CheckSlaVer(FT_CHECK_SLA_VER_REQ *ft_check_sla_ver_op);
+extern void FT_GetSlaPara(void);
+extern void FT_VerifySla(FT_VERIFY_SLA_RND_REQ *ft_verify_sla_op);
+extern kal_bool FT_MetaSLA_Is_Enabled(void);
+
+#endif // #ifndef L1_SIM
+
+
+/* FT task utility command */
+extern void FT_UtilityCommand(ilm_struct *ptrMsg);
+
+/*******************************************************************************
+*
+*  other module's api
+*
+*******************************************************************************/
+extern kal_uint32 SaveAndSetIRQMask(void);
+/***************************
+ * FT task self message API
+ **************************/
+typedef void (*ft_in_proc_call_type) (kal_uint32 arg1, void *arg2);
+typedef struct
+{
+    LOCAL_PARA_HDR
+    ft_in_proc_call_type func;
+    kal_uint32 func_arg1;
+    void *func_arg2;
+} ft_in_proc_call_req_struct;
+typedef enum
+{
+    MSG_ID_FT_IN_PROC_CALL_REQ,
+    MSG_ID_FT_IN_PROC_CALL_CNF
+}FT_TASK_MESSAGE_TYPE;
+void ft_send_in_proc_call_req(ft_in_proc_call_type func, kal_uint32 func_arg1, void *func_arg2);
+void ft_in_proc_call_handler(ilm_struct *ilm_ptr);
+extern kal_char g_FT_debug_buf[128];
+#ifndef L1_SIM
+/***********************
+ * NVRAM module APIs
+ **********************/
+extern kal_bool nvram_get_disk_file_info(kal_uint32 *diskfilesize, kal_uint32 *freespace, kal_uint32 *overhead);
+/***********************
+ * CCT module APIs
+ **********************/
+kal_uint8 ft_cct_check_op_is_support(kal_uint32 query_op_code);
+#endif // #ifndef L1_SIM
+
+#ifdef __cplusplus
+}
+#endif // #ifdef __cplusplus
+
+#endif // #ifndef FT_PRIVATE_H
+
diff --git a/mcu/middleware/meta/ft/inc/ft_report.h b/mcu/middleware/meta/ft/inc/ft_report.h
new file mode 100644
index 0000000..e549d6f
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_report.h
@@ -0,0 +1,82 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_report.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT report API definition (Category: L1RF)
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef __FT_REPORT_H__
+#define __FT_REPORT_H__
+
+#endif // #ifndef __FT_REPORT_H__
diff --git a/mcu/middleware/meta/ft/inc/ft_trace_def.h b/mcu/middleware/meta/ft/inc/ft_trace_def.h
new file mode 100644
index 0000000..78ea7f2
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_trace_def.h
@@ -0,0 +1,71 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2012
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_trace_def.h
+ *
+ * Project:
+ * --------
+ *   MOLY
+ *
+ * Description:
+ * ------------
+ *   FT trace definition
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ * ==========================================================================
+ * $Log$
+ *
+ * 08 18 2015 jenny.lin
+ * [MOLY00137504] [Jade][Security] Phase-in secure NVRAM interface
+ * [New Feature]NVRAM read/write by NVRAM secure API not by ILM message
+ *
+ ****************************************************************************/
+#ifndef _FT_TRACE_DEF_H
+#define _FT_TRACE_DEF_H
+#ifndef GEN_FOR_PC
+ #include "kal_public_defs.h"
+#endif /* GEN_FOR_PC */
+#include "kal_trace.h"
+#if !defined(GEN_FOR_PC)
+#endif
+#if !defined(GEN_FOR_PC)
+#include"ft_trace_def_mod_ft_utmd.h"
+#endif
+#endif /* _FT_TRACE_DEF_H */
diff --git a/mcu/middleware/meta/ft/inc/ft_trace_def_mod_ft_utmd.json b/mcu/middleware/meta/ft/inc/ft_trace_def_mod_ft_utmd.json
new file mode 100644
index 0000000..4af67ed
--- /dev/null
+++ b/mcu/middleware/meta/ft/inc/ft_trace_def_mod_ft_utmd.json
@@ -0,0 +1,221 @@
+{
+  "legacyParameters": {}, 
+  "module": "MOD_FT", 
+  "startGen": "Legacy", 
+  "endGen": "-",      
+  "traceClassDefs": [
+    {
+      "FT_OP_INFO": {
+        "debugLevel": "Medium", 
+        "tag": [
+          "FT_OP"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }, 
+    {
+      "FT_OP_FUNC": {
+        "debugLevel": "High", 
+        "tag": [
+          "FT_OP"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }, 
+    {
+      "FT_CAL_INFO": {
+        "debugLevel": "Medium", 
+        "tag": [
+          "FT_CAL"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }, 
+    {
+      "FT_CAL_FUNC": {
+        "debugLevel": "High", 
+        "tag": [
+          "FT_CAL"
+        ], 
+        "traceType": "DesignInfo"
+      }
+    }, 
+    {
+      "FT_NVRAM_INFO": {
+        "debugLevel": "High", 
+        "tag": [
+          "FT_NVRAM"
+        ], 
+        "traceType": "Public"
+      }
+    }
+  ], 
+  "traceDefs": [
+    {
+      "FT_MISC_OP_CHECK_SIM_HW_TEST_ENTER_DRV": {
+        "apiType": "index", 
+        "format": "[FT] Calling usim_iftest_for_smt", 
+        "traceClass": "FT_OP_INFO"
+      }
+    }, 
+    {
+      "FT_MISC_OP_CHECK_SIM_HW_TEST_LEAVE_DRV": {
+        "apiType": "index", 
+        "format": "[FT] Exit usim_iftest_for_smt: status (%d)", 
+        "traceClass": "FT_OP_INFO"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_INIT_PROCESS": {
+        "apiType": "index", 
+        "format": "[FT] Init Cal Data Integrity Check recording procedure", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_GET_NVRAM_ITEM_CHECKSUM": {
+        "apiType": "index", 
+        "format": "[FT] Get Nvram item checksum file_idx(%d), rec_idx(%d) checksum(%d) valid(%d)", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_RECORD_NVRAM_ITEM_PROCESS": {
+        "apiType": "index", 
+        "format": "[FT] Process NVRAM item with Cal Data Check Flow file_idx(%d), rec_idx(%d) enabled(%d)", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_ALLOCATE_BUFFER": {
+        "apiType": "index", 
+        "format": "[FT] Allocate Cal Data Integrity Check internal buffer", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_FREE_BUFFER": {
+        "apiType": "index", 
+        "format": "[FT] Free Cal Data Integrity Check internal buffer", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_ADD_RECORD": {
+        "apiType": "index", 
+        "format": "[FT] Add Cal Data Integrity Check internal buffer file_idx(%d), rec_idx(%d), checksum(%d)", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_ADD_RECORD_BUFFER_EMPTY": {
+        "apiType": "index", 
+        "format": "[FT] Cal Data Integrity internal buffer is NULL", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_ADD_RECORD_INSERT_ONE": {
+        "apiType": "index", 
+        "format": "[FT] Add Cal Data Integrity to specific index (%d) current valid num after inserttion (%d)", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_ADD_RECORD_OUT_OF_BOUND": {
+        "apiType": "index", 
+        "format": "[FT] Exceeds the Cal Data Integrity internal buffer boundary (%d)", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_ADD_RECORD_UPDATE_EXISTING_ONE": {
+        "format": "[FT] Add Cal Data Integrity to existing record in index (%d)", 
+        "traceClass": "FT_CAL_INFO"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_ADD_RECORD_INSERT_FLOW_START": {
+        "apiType": "index", 
+        "format": "[FT] Insert the Cal Data Integrity", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_DEL_RECORD": {
+        "apiType": "index", 
+        "format": "[FT] Remove Cal Data Integrity Check internal buffer file_idx(%d), rec_idx(%d), is one record(%d)", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_CHECK_RECORD": {
+        "apiType": "index", 
+        "format": "[FT] Check Cal Data Integrity Check internal buffer file_idx(%d), rec_idx(%d), is one record(%d)", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_SYNC_BUFFER": {
+        "apiType": "index", 
+        "format": "[FT] Sync Cal Data Integrity Check buffer", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_CAL_DATA_SYNC_BUFFER_RESPONSE_HANDLER": {
+        "apiType": "index", 
+        "format": "[FT] Cal Data Integrity Check sync buffer response handler current op(%d)", 
+        "traceClass": "FT_CAL_FUNC"
+      }
+    }, 
+    {
+      "FT_MISC_OP_FUNC": {
+        "apiType": "index", 
+        "format": "[FT] FT_MISC_Operation type(%d)", 
+        "traceClass": "FT_OP_FUNC"
+      }
+    }, 
+    {
+      "FT_NVRAM_SEND_WRITE_CMD_TO_NVRAM": {
+        "format": "[FT][NVRAM] Send Write Request to NVRAM holdBufferForRelay(%d)", 
+        "traceClass": "FT_NVRAM_INFO"
+      }
+    }, 
+    {
+      "FT_NVRAM_SEND_READ_CMD_TO_NVRAM": {
+        "format": "[FT][NVRAM] Send Read Request to NVRAM", 
+        "traceClass": "FT_NVRAM_INFO"
+      }
+    }, 
+    {
+      "FT_NVRAM_SEND_WRITE_RESPONSE_TO_HOST": {
+        "apiType": "index", 
+        "format": "[FT][NVRAM] Send Write Response to Host", 
+        "traceClass": "FT_NVRAM_INFO"
+      }
+    }, 
+    {
+      "FT_NVRAM_SEND_READ_RESPONSE_TO_HOST": {
+        "apiType": "index", 
+        "format": "[FT][NVRAM] Send Read Response to Host holdBufferForRelay(%d)", 
+        "traceClass": "FT_NVRAM_INFO"
+      }
+    }, 
+    {
+      "FT_NVRAM_CALL_READ_NVRAM_API": {
+        "apiType": "index", 
+        "format": "[FT][NVRAM] NVRAM API read data result = [%d] (result = 0 --> NVRAM_ERRNO_SUCCESS)", 
+        "traceClass": "FT_NVRAM_INFO"
+      }
+    }, 
+    {
+      "FT_NVRAM_CALL_WRITE_NVRAM_API": {
+        "apiType": "index", 
+        "format": "[FT][NVRAM] NVRAM API write data result = [%d] (result = 0 --> NVRAM_ERRNO_SUCCESS)", 
+        "traceClass": "FT_NVRAM_INFO"
+      }
+    }
+  ], 
+  "traceFamily": "PS"
+}
\ No newline at end of file
diff --git a/mcu/middleware/meta/ft/src/ft_dummy.c b/mcu/middleware/meta/ft/src/ft_dummy.c
new file mode 100644
index 0000000..095cb91
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_dummy.c
@@ -0,0 +1,160 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_dummy.c
+ *
+ * Project:
+ * --------
+ *   Maui_Software
+ *
+ * Description:
+ * ------------
+ *   Dummy function for ft lib in MAUI only configuration
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+/*************************************************************************
+ * Include Statements for task config
+ *************************************************************************/
+#include "syscomp_config.h"
+/*************************************************************************
+ * Include Statements for KAL
+ *************************************************************************/
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "kal_public_defs.h"
+/*************************************************************************
+ * Include Statements for L1
+ *************************************************************************/
+#include "l1_types_public.h"
+/*************************************************************************
+ * FUNCTION
+ *  ft_create
+ *
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *  None
+ *
+ * GLOBALS AFFECTED
+ *
+ *************************************************************************/
+kal_bool
+ft_create(comptask_handler_struct **handle)
+{
+    static const comptask_handler_struct ft_handler_info =
+    {
+        NULL,  /* task entry function */
+        NULL,  /* task initialization function */
+        NULL,  /* task configuration function */
+        NULL,  /* task reset handler */
+        NULL,  /* task termination handler */
+    };
+
+    *handle = (comptask_handler_struct *)&ft_handler_info;
+    return KAL_TRUE;
+}
+/*******************************************************************************
+* FUNCTION
+*   FT_DispatchReports
+*
+* DESCRIPTION
+*   Dispatch report
+*
+* CALLS
+*   FT_ReportPowerScanDone
+*   FT_ReportFCB
+*
+* PARAMETERS
+*   None
+*
+* RETURNS
+*   None
+*
+* GLOBALS AFFECTED
+*   None
+*******************************************************************************/
+void FT_DispatchReports( Report_FT *report )
+{
+}
+/*******************************************************************************
+ * FUNCTION
+ *   FT_META_IsBasicOperation
+ *
+ * DESCRIPTION
+ *   Check the message ID belongs to one of the basic META mode operation
+ *
+ * CALLS
+ *   none
+ *
+ * PARAMETERS
+ *   msg_id the message ID of the request message
+ *
+ * RETURNS
+ *   The indicator of the operation is basic META mode operation cross any state (MODE_ENTRY_SRC)
+ *
+ *******************************************************************************/
+kal_bool FT_META_IsBasicOperation(kal_uint16 msg_id)
+{
+    return KAL_FALSE;
+}
diff --git a/mcu/middleware/meta/ft/src/ft_fnc.c b/mcu/middleware/meta/ft/src/ft_fnc.c
new file mode 100644
index 0000000..a75aac4
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc.c
@@ -0,0 +1,2505 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_r.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   Factory testing function library
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ *
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+/*************************************************************************
+* Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h" //MSBB change #include "stack_common.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_msgs.h"
+#ifndef L1_SIM
+#include "task_config.h"
+#endif // #ifndef L1_SIM
+#include "svc_sap.h"
+#include "ft_msgid.h"
+/*************************************************************************
+* Include Statements for MAUI
+ *************************************************************************/
+/**************************************************************************
+ * System Service header
+ *************************************************************************/
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "kal_public_defs.h"
+#include "string.h"
+#ifndef L1_SIM
+#include "fs_type.h"
+#include "fs_func.h"
+#include "fs_errcode.h"
+#endif // #ifndef L1_SIM
+#include "kal_public_defs.h" //MSBB change #include "stack_config.h"
+#ifndef L1_SIM
+#include "init.h"
+#endif // #ifndef L1_SIM
+/**************************************************************************
+ * HAL header
+ *************************************************************************/
+#ifndef L1_SIM
+#include "dcl.h"
+#include "drv_comm.h"
+#include "l1audio.h"
+// include the device.h for the GPIO_DEV_LED_KEY definition
+// (Baseband tool LED, vibrator definitions)
+#include "device.h"
+#endif // #ifndef L1_SIM
+#include "tst_hal_internal_wrapper_defs.h"
+/**************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_public.h"
+#include "ft_private.h"
+#ifndef L1_SIM
+#include "ft_fnc_misc.h"
+#endif //#ifndef L1_SIM
+#include "ft_fnc_l1rf.h"
+#include "ft_fnc_wcdma.h"
+/**************************************************************************
+ * custom header
+ *************************************************************************/
+#ifndef L1_SIM
+#include "meta_customize.h"
+#include "custom_em.h"
+//#include "usb_custom.h"
+#include "custom_equipment.h"
+#endif // #ifndef L1_SIM
+/**************************************************************************
+ * UL1 RF header
+ *************************************************************************/
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#include "ul1cal.h"
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+//MSBB remove #include "fctycomp_config.h"
+/**************************************************************************
+ * NVRAM header
+ *************************************************************************/
+#ifndef L1_SIM
+#include "nvram_data_items.h"
+#include "ft_nvram_def.h"
+#endif // #ifndef L1_SIM
+/**************************************************************************
+ * audio (MED) header
+ *************************************************************************/
+#ifndef MED_NOT_PRESENT
+#include "aud_defs.h"
+#include "med_struct.h"
+#endif // MED_NOT_PRESENT
+#include "tst_def.h"
+/**************************************************************************
+ * SLA header
+ *************************************************************************/
+#include "meta_sec_support.h"
+/*************************************************************************
+ * Non-MODEM BSP
+ *************************************************************************/
+kal_uint32 ft_event_group_ptr; /**< \brief ft event group pointer */
+
+extern kal_bool Drv_ReadReg(kal_uint32 addr, kal_uint16 *data);
+extern kal_bool Drv_WriteReg(kal_uint32 addr, kal_uint16 data);
+extern void tst_log_primitive_without_filter_check(ilm_struct*,
+        kal_uint8,
+        kal_uint32);
+extern void dhl_FT_log_primitive(ilm_struct *ilm);
+/*******************************************************************************
+ *
+ *  Utility Functions
+ *
+ *******************************************************************************/
+void _FT_ALLOC_MSG(ilm_struct* ilm_ptr, kal_uint16 size, kal_bool IsFtMsg, kal_bool IsCcMsg)
+{
+    if( ilm_ptr == NULL )
+    {
+        ASSERT(0); // assert it!
+    }
+    
+    ilm_ptr->local_para_ptr = NULL;
+    ilm_ptr->peer_buff_ptr = NULL;
+    if( 0 < size ) {
+        if( KAL_TRUE == IsCcMsg ) {
+            if( NULL == (ilm_ptr->local_para_ptr=construct_cc_non_cached_local_para(size, TD_RESET)) ) {
+                ASSERT(0); // assert it!
+            }
+        }
+        else {
+            if( NULL == (ilm_ptr->local_para_ptr=construct_local_para(size, TD_RESET)) ) {
+                ASSERT(0); // assert it!
+            }
+        }
+    }
+    if( KAL_TRUE == IsFtMsg ) {
+        // reset content of FT primitive first
+		if(size > sizeof(FT_H) && NULL != ((char *)ilm_ptr->local_para_ptr)+sizeof(FT_H))
+		{
+			kal_mem_set(((char *)ilm_ptr->local_para_ptr)+sizeof(FT_H), 0, size-sizeof(FT_H));
+		}
+    }
+}
+
+void _FT_CONSTRUCT_CC_MSG(const ilm_struct* ilm_ptr, ilm_struct* ilm_cc_ptr)
+{
+    if(ilm_ptr == NULL || ilm_cc_ptr == NULL)
+    {
+        ASSERT(0);
+    }
+    _FT_ALLOC_MSG(ilm_cc_ptr, ilm_ptr->local_para_ptr->msg_len, KAL_FALSE, KAL_TRUE);
+    kal_mem_cpy(ilm_cc_ptr->local_para_ptr, ilm_ptr->local_para_ptr, ilm_ptr->local_para_ptr->msg_len);
+    if( ilm_ptr->peer_buff_ptr != NULL )
+    {
+        kal_uint8 *pdu_ptr, *pdu_cc_ptr;
+        kal_uint16 size;     
+        if( NULL == (ilm_cc_ptr->peer_buff_ptr=construct_cc_non_cached_peer_buff(ilm_ptr->peer_buff_ptr->pdu_len,
+                                                                               0,
+                                                                               0,
+                                                                               TD_RESET)) ) {
+            ASSERT(0); // assert it!
+        }
+        pdu_ptr = (kal_uint8*) get_peer_buff_pdu(ilm_ptr->peer_buff_ptr, &size);
+        pdu_cc_ptr = (kal_uint8*) get_peer_buff_pdu(ilm_cc_ptr->peer_buff_ptr, &size);
+        kal_mem_cpy(pdu_cc_ptr, pdu_ptr, size);
+    }
+}
+
+void _FT_SendFtMsgToPcByToken(ilm_struct  *ilm_ptr, kal_uint16  token)
+{
+#if !defined(__DHL_MODULE__)
+    _FT_SendFtMsgByToken(MOD_FT, MOD_TST, FT_TST_SAP, MSG_ID_FT_TO_TST, ilm_ptr, token);
+#else
+    _FT_SendFtMsgByToken(MOD_FT, MOD_DHL, FT_TST_SAP, MSG_ID_FT_TO_TST, ilm_ptr, token);
+#endif // #if !defined(__DHL_MODULE__)
+}
+
+void _FT_SendFtMsgByToken(module_type  src_mod, module_type  dest_mod, sap_type  sap, msg_type  msg, ilm_struct  *ilm_ptr, kal_uint16  token)
+{
+    ilm_ptr->src_mod_id  = src_mod;
+    ilm_ptr->dest_mod_id = dest_mod;
+    ilm_ptr->msg_id = msg;
+    ilm_ptr->sap_id = sap;
+#if !defined(__DHL_MODULE__)
+    if (dest_mod == MOD_TST) {
+#else
+    if (dest_mod == MOD_DHL) {
+#endif // #if !defined(__DHL_MODULE__)
+        ((FT_H *)(ilm_ptr->local_para_ptr))->token=token;
+        tst_log_primitive(ilm_ptr);
+        ilm_ptr->src_mod_id  = (module_type)0xA1;
+        ilm_ptr->dest_mod_id = (module_type)0;
+        ilm_ptr->sap_id      = (sap_type)0xA3;
+        ilm_ptr->msg_id      = (msg_type)2;
+#if !defined(__DHL_MODULE__)
+        // directly copy primitive to TST ring buffer
+        tst_log_primitive_without_filter_check(
+                ilm_ptr,
+                RS232_LOGGED_PRIMITIVE_TYPE,
+                MSG_ID_LOGGED_PRIMITIVE);
+#else
+        dhl_FT_log_primitive(ilm_ptr);                
+#endif // #if !defined(__DHL_MODULE__)
+        // cancel ilm, because we directly access TST ring buffer, no need to send primitive to TST
+        destroy_ilm(ilm_ptr);
+        return;
+    }
+    msg_send6(src_mod, dest_mod, sap, msg, ilm_ptr->local_para_ptr, ilm_ptr->peer_buff_ptr);
+}
+
+void FT_SendDeniedMsgIdCnf(kal_uint16 deniedMsgId, kal_uint32 status)
+{
+    ilm_struct    ilm_ptr;
+    FT_DENIED_MSG_ID_CNF *ft_cnf;
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_DENIED_MSG_ID_CNF));
+    ft_cnf = (FT_DENIED_MSG_ID_CNF *)ilm_ptr.local_para_ptr;
+    ft_cnf->header.ft_msg_id = FT_CMD_DENIED_CNF_ID;
+    ft_cnf->deniedMsgId = deniedMsgId;
+    ft_cnf->status = status;
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+
+/*******************************************************************************
+ *
+ *  FT Module Initialization Functions
+ *
+ *******************************************************************************/
+/*******************************************************************************
+ * FUNCTION
+ *   FT_InitFtData
+ *
+ * DESCRIPTION
+ *
+ * CALLS
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *******************************************************************************/
+#ifndef L1_SIM
+extern kal_int8 FT_FAT_Handle_Clear(void);
+#endif //#ifndef L1_SIM
+void FT_InitFtData()
+{
+#ifndef L1_SIM
+    FT_FAT_Handle_Clear();
+#endif //#ifndef L1_SIM
+    // init event group
+    ft_event_group_ptr = (kal_uint32) kal_create_event_group("FtEvent");
+}
+#ifndef L1_SIM
+/**
+ * This function calls Dcl PMU interface to read PMIC register
+ * @register_index the index of the register to be written
+ */
+kal_bool ft_pmic_reg_read(kal_uint16 *data, kal_uint16 register_index)
+{
+    kal_bool status;
+    DCL_HANDLE handle;
+    PMU_CTRL_MISC_GET_REGISTER_VALUE val;
+    val.offset=register_index;
+    handle=DclPMU_Open(DCL_PMU, FLAGS_NONE);
+    if(DclPMU_Control(handle, MISC_GET_REGISTER_VALUE, (DCL_CTRL_DATA_T *)&val) != STATUS_OK)
+    {
+        // in this case, there might be not supported (if the driver did not support yet, usually in development phase)
+        status = KAL_FALSE;
+    }
+    else
+    {
+        status = KAL_TRUE;
+    }
+    DclPMU_Close(handle);
+    *data = val.value;
+    return status;
+}
+/**
+ * This function calls Dcl PMU interface to read PMIC register
+ * @param data the register value to be written to PMIC
+ * @param register_index the index of the register to be written
+ */
+kal_bool ft_pmic_reg_write(kal_uint16 data, kal_uint16 register_index)
+{
+    kal_bool status;
+    DCL_HANDLE handle;
+    PMU_CTRL_MISC_SET_REGISTER_VALUE val;
+    val.offset=register_index;
+    val.value=data;
+    handle=DclPMU_Open(DCL_PMU, FLAGS_NONE);
+    if(DclPMU_Control(handle, MISC_SET_REGISTER_VALUE, (DCL_CTRL_DATA_T *)&val) != STATUS_OK)
+    {
+        // in this case, there might be not supported (if the driver did not support yet, usually in development phase)
+        status = KAL_FALSE;
+    }
+    else
+    {
+        status = KAL_TRUE;
+    }
+    DclPMU_Close(handle);
+    return status;
+}
+/**
+ * This function handles the PMIC register read operation
+ * @param req FT task PMIC register read request
+ * @param Regtype register type
+ */
+void FT_FtPMICRegisterRead(ft_PMICRegisterRead_req_T* req,unsigned char RegType) // for build warning
+{
+    ilm_struct  ilm_ptr;
+    ft_PMICRegisterRead_cnf_T* ptrMsg;
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(ft_PMICRegisterRead_cnf_T));
+    ptrMsg = (ft_PMICRegisterRead_cnf_T *)ilm_ptr.local_para_ptr;
+    ptrMsg->status = KAL_FALSE;
+    if(RegType ==FT_PMICReg)
+    {
+        ptrMsg->header.ft_msg_id = FT_PMIC_REG_READ_CNF_ID;
+        /*
+         * Note: The custom_pmic_reg_read interface is changed due to HAL,
+         * the reference is changed to ft_pmic_reg_read
+         */
+        ptrMsg->status = ft_pmic_reg_read(&(ptrMsg->value), (kal_uint16)req->addr);
+    }
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+/**
+ * This function handles the PMIC register write operation
+ * @param req FT task PMIC register write request
+ * @param Regtype register type
+ */
+void FT_FtPMICRegisterWrite(ft_PMICRegisterWrite_req_T* req,unsigned char RegType)
+{
+    ilm_struct  ilm_ptr;
+    ft_PMICRegisterWrite_cnf_T *ptrMsg ;
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(ft_PMICRegisterWrite_cnf_T));
+    ptrMsg = (ft_PMICRegisterWrite_cnf_T *)ilm_ptr.local_para_ptr;
+    ptrMsg->status = KAL_FALSE;
+    if(RegType ==FT_PMICReg)
+    {
+        ptrMsg->header.ft_msg_id = FT_PMIC_REG_WRITE_CNF_ID;
+        /*
+         * Note: The custom_pmic_reg_write interface is changed due to HAL,
+         * the reference is changed to ft_pmic_reg_write
+         */
+        ptrMsg->status = ft_pmic_reg_write(req->value, (kal_uint16)req->addr);
+    }
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+
+/*******************************************************************************
+ * FUNCTION
+ *   FT_FtRegisterRead()
+ *
+ * DESCRIPTION
+ *   Handle the request of reading Register Req
+ *
+ * CALLS
+ *   Drv_ReadReg(.)
+ *
+ * PARAMETERS
+ *   *req
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+void FT_FtRegisterRead(ft_RegisterRead_req_T* req,unsigned char RegType)
+{
+    kal_uint8 status;
+    ilm_struct  ilm_ptr;
+    ft_RegisterRead_cnf_T* ptrMsg;
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(ft_RegisterRead_cnf_T));
+    /* if ptrMsg != NULL*/
+    ptrMsg = (ft_RegisterRead_cnf_T *)ilm_ptr.local_para_ptr;
+    status = KAL_FALSE; // for build warning
+    if(RegType ==FT_BaseBandReg)
+    {
+        ptrMsg->header.ft_msg_id = FT_REG_READ_CNF_ID;
+        status=Drv_ReadReg(req->addr,&ptrMsg->value);
+    }
+    if(status==KAL_TRUE)
+    { status=FT_CNF_OK; }
+    else
+    { status=FT_CNF_FAIL; }
+    ptrMsg->status = status;
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+
+
+/*******************************************************************************
+ * FUNCTION
+ *   FT_FtRegisterWrite()
+ *
+ * DESCRIPTION
+ *   Handle the request of Writing Register Req
+ *
+ * CALLS
+ *   Drv_WriteReg(.)
+ *
+ * PARAMETERS
+ *   *req
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+void FT_FtRegisterWrite(ft_RegisterWrite_req_T* req,unsigned char RegType)
+{
+    kal_uint8 status;
+    ilm_struct  ilm_ptr;
+    ft_RegisterWrite_cnf_T *ptrMsg ;
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(ft_RegisterWrite_cnf_T));
+    status = KAL_FALSE; // for build warning
+    /* if ptrMsg != NULL*/
+    ptrMsg = (ft_RegisterWrite_cnf_T *)ilm_ptr.local_para_ptr;
+    if(RegType ==FT_BaseBandReg)
+    {
+        ptrMsg->header.ft_msg_id = FT_REG_WRITE_CNF_ID;
+        status=Drv_WriteReg(req->addr,req->value);
+    }
+    if(status==KAL_TRUE)
+    { status=FT_CNF_OK; }
+    else
+    { status=FT_CNF_FAIL; }
+    ptrMsg->status = status;
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+
+/*******************************************************************************
+ * FUNCTION
+ *   FT_FtADC_GetMeaData()
+ *
+ * DESCRIPTION
+ *   Handle the request of Getting MeaData
+ *
+ * CALLS
+ *   ADC_GetData2Meta(.)
+ *
+ * PARAMETERS
+ *   *req
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+void  FT_FtADC_GetMeaData(ft_FtADC_GetMeaData_req_T* req)
+{
+    ilm_struct  ilm_ptr;
+    ft_FtADC_GetMeaData_cnf_T *ptrMsg ;
+    ADC_CTRL_GET_DATA_2_META_T data2meta;
+    DCL_HANDLE adc_handle;
+    memset(&data2meta, 0, sizeof(ADC_CTRL_GET_DATA_2_META_T));
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(ft_FtADC_GetMeaData_cnf_T));
+    ptrMsg = (ft_FtADC_GetMeaData_cnf_T *)ilm_ptr.local_para_ptr;
+    ptrMsg->status=FT_CNF_OK;
+    ptrMsg->header.ft_msg_id = FT_ADC_GETMEADATA_CNF_ID;
+    adc_handle = DclHADC_Open(DCL_ADC, FLAGS_NONE);
+    data2meta.u1Channel = req->Sel;
+    data2meta.u2MeaCount = req->Meacount;
+    if(DclHADC_Control(adc_handle, ADC_CMD_GET_DATA_2_META, (DCL_CTRL_DATA_T *)& data2meta) != STATUS_OK)
+    {
+        ptrMsg->status = FT_CNF_FAIL;
+    }
+    ptrMsg->value = data2meta.u4ADCData;
+    if(DclHADC_Close(adc_handle) != STATUS_OK)
+    {
+        ptrMsg->status = FT_CNF_FAIL;
+    }
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+#endif // #ifndef L1_SIM
+/*******************************************************************************
+ *
+ *  Version Info functionality
+ *
+ *******************************************************************************/
+void FT_GetVersionInfo(void) {
+
+    ilm_struct           ilm_ptr;
+    FT_VER_INFO_CNF     *ptrMsg;
+	
+	FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_VER_INFO_CNF));
+    // if ptrMsg != NULL
+    ptrMsg = (FT_VER_INFO_CNF *)ilm_ptr.local_para_ptr;
+    // assign primitive id
+    ptrMsg->header.ft_msg_id = FT_VER_INFO_CNF_ID;
+
+ #ifndef L1_SIM
+    version_struct       ver_struct;
+	memset(&ver_struct, 0, sizeof(version_struct));
+
+    // get version info
+    INT_VersionNumbers(&ver_struct);
+    // check
+    if( NULL == ver_struct.bb_chip ) {
+        ver_struct.bb_chip = "Unknown";
+    }
+    if( NULL == ver_struct.dsp_fw ) {
+        ver_struct.dsp_fw = "Unknown";
+    }
+    if( NULL == ver_struct.dsp_ptch ) {
+        ver_struct.dsp_ptch = "Unknown";
+    }
+    if( NULL == ver_struct.mcu_sw ) {
+        ver_struct.mcu_sw = "Unknown";
+    }
+    if( NULL == ver_struct.bb_board ) {
+        ver_struct.bb_board = "Unknown";
+    }
+    if( NULL == ver_struct.mcu_sw_flavor ) {
+        ver_struct.mcu_sw_flavor = "Unknown";
+    }
+    // assign BaseBand chip version string
+    strncpy((kal_char *)ptrMsg->bb_chip, ver_struct.bb_chip, 64);
+    // assign ECO version
+    kal_mem_set(ptrMsg->eco_ver, 0, 4);
+    // assign DSP firmware version string
+    strncpy((kal_char *)ptrMsg->dsp_fw, ver_struct.dsp_fw, 64);
+    // assign DSP patch version string
+    strncpy((kal_char *)ptrMsg->dsp_patch, ver_struct.dsp_ptch, 64);
+    // assign S/W version string
+    strncpy((kal_char *)ptrMsg->sw_ver, ver_struct.mcu_sw, 64);
+    // assign H/W version string
+    strncpy((kal_char *)ptrMsg->hw_ver, ver_struct.bb_board, 64);
+    // assign Melody version string
+    strncpy((kal_char *)ptrMsg->melody_ver, "Unknown", 64);
+    // assign S/W flavor version string
+    strncpy((kal_char *)ptrMsg->sw_flavor, ver_struct.mcu_sw_flavor, 64);
+#else //  #ifndef L1_SIM
+	strcpy((kal_char *)ptrMsg->bb_chip, "Unknown");
+	kal_mem_set(ptrMsg->eco_ver, 0, 4);
+	kal_mem_set(ptrMsg->dsp_fw, 0, 64);
+	kal_mem_set(ptrMsg->dsp_patch, 0, 64);
+	strcpy((kal_char *)ptrMsg->sw_ver, "xl1 Sim");
+	kal_mem_set(ptrMsg->hw_ver, 0, 64);
+	kal_mem_set(ptrMsg->melody_ver, 0, 64);
+	strcpy((kal_char *)ptrMsg->sw_flavor, "Unknown");
+#endif //  #ifdef L1_SIM
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+/*******************************************************************************
+ *
+ *  FT task test alive
+ *
+ *******************************************************************************/
+void FT_TestAlive(void) {
+
+    FT_IS_ALIVE_CNF *pMsg;
+    ilm_struct       ilm_ptr;
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_IS_ALIVE_CNF));
+    pMsg=(FT_IS_ALIVE_CNF *)ilm_ptr.local_para_ptr;
+    pMsg->header.ft_msg_id = FT_IS_ALIVE_CNF_ID;
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+#ifndef L1_SIM
+/**
+ * This api calls the DCL interface to check and clear the PDN1 bit 7 set by flashtool
+ * and scrambles theh powerkey1
+ */
+ #if (!defined(__SMART_PHONE_MODEM__))
+static kal_bool FT_ClearPowerKey(void)
+{
+    /// Driver RTC FT Power Off request
+    RTC_CTRL_FT_POWEROFF_T ft_cmd_data;
+    DCL_HANDLE rtc_handle = DclRTC_Open(DCL_RTC, FLAGS_NONE);
+    memset(&ft_cmd_data, 0, sizeof(RTC_CTRL_FT_POWEROFF_T));
+    DclRTC_Control(rtc_handle, RTC_CMD_FT_POWEROFF, (DCL_CTRL_DATA_T *) &ft_cmd_data);
+    DclRTC_Close(rtc_handle);
+    return (kal_bool)ft_cmd_data.fgMetaReset;
+}
+ #endif
+/*******************************************************************************
+ *
+ * FUNCTION
+ *   FT_PowerOff
+ *
+ * DESCRIPTION
+ *   Power off sequence in META mode
+ *
+ * CALLS
+ *   custom_ft_util_check_if_usb_enable_support for check the USB_ENABLE compile option
+ *   USB_PowerControl
+ *   DclRTC_Open/DclRTC_Control (RTC_CMD_FT_POWEROFF command)/DclRTC_Close for RTC power off sequence (scramble PDN1 bit 7 for flashtool entering META mode)
+ *   DclPW_Open/DclPW_Control (PW_CMD_POWEROFF command)/DclPW_Close for Driver power off sequence
+ *   DclWDT_Open/DclWDT_Control (WDT_CMD_DRV_RESET command)/DclWDT_Close for Driver reset sequence
+ *
+ * PARAMETERS
+ *   void
+ *
+ * RETURNS
+ *   void
+ *
+ * GLOBALS AFFECTED
+ *   N/A
+ *
+ *******************************************************************************/
+void FT_PowerOff(void)
+{
+#if (!defined(__SMART_PHONE_MODEM__))
+    if(KAL_TRUE == custom_ft_util_check_if_usb_enable_support())
+    {
+         // shutdown USB module
+         /**
+          * USB_PowerControl(KAL_FALSE) is no longer 
+          * to disable the usb power anymore.
+          **/
+    }
+    Custom_META_USBVirtualComDisconnect();
+    FT_ClearPowerKey();
+#endif // #if (!defined(__SMART_PHONE_MODEM__))
+}
+#endif // #ifndef L1_SIM
+#ifndef L1_SIM
+/***********************************************
+ * FT task self message API
+ * This API is called in other task context
+ * or HISR conext!
+ **********************************************/
+void ft_send_in_proc_call_req(ft_in_proc_call_type func, kal_uint32 func_arg1, void *func_arg2)
+{
+    ft_in_proc_call_req_struct *ptrMsg;
+    ptrMsg = (ft_in_proc_call_req_struct *)construct_local_para(sizeof(ft_in_proc_call_req_struct), TD_RESET);
+    if(NULL == ptrMsg)
+    {
+        ASSERT(0);    
+    }    
+    ptrMsg->func = func;
+    ptrMsg->func_arg1 = func_arg1;
+    ptrMsg->func_arg2 = func_arg2;    
+    msg_send5(kal_get_active_module_id(), MOD_FT, FT_TST_SAP, (msg_type)MSG_ID_FT_IN_PROC_CALL_REQ, (local_para_struct*)ptrMsg);
+}
+/***********************************************
+ * FT task self message (In Proc Call handler)
+ **********************************************/
+void ft_in_proc_call_handler(ilm_struct *ilm_ptr)
+{
+    /*----------------------------------------------------------------*/
+    /* Local Variables                                                */
+    /*----------------------------------------------------------------*/
+    ft_in_proc_call_req_struct *ptrMsg = (ft_in_proc_call_req_struct*) ilm_ptr->local_para_ptr;
+
+    /*----------------------------------------------------------------*/
+    /* Code Body                                                      */
+    /*----------------------------------------------------------------*/
+    ASSERT(ptrMsg->func != NULL);
+    ptrMsg->func(ptrMsg->func_arg1, ptrMsg->func_arg2);
+}
+
+
+/*******************************************************************************
+ *
+ *  SLA functionality
+ *
+ *******************************************************************************/
+kal_bool FT_MetaSLA_Is_Enabled(void)
+{
+    return MetaSLA_Is_Enabled();
+}
+
+void FT_GetSlaStatus(void)
+{
+    ilm_struct              ilm_ptr;
+    FT_GET_SLA_STATUS_CNF   *ptrMsg;
+
+	FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_GET_SLA_STATUS_CNF));
+    // if ptrMsg != NULL
+    ptrMsg = (FT_GET_SLA_STATUS_CNF *)ilm_ptr.local_para_ptr;
+    // assign primitive id
+    ptrMsg->header.ft_msg_id = FT_GET_SLA_STATUS_CNF_ID;
+    ptrMsg->sla_config = (kal_uint16) FT_MetaSLA_Is_Enabled();
+    ptrMsg->sla_verified= (kal_uint16) MetaSLA_Is_Verified();
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+
+extern kal_uint16 Custom_META_CheckSlaVer(kal_uint32 sla_ver_from_pc);
+void FT_CheckSlaVer(FT_CHECK_SLA_VER_REQ *ft_check_sla_ver_op)
+{
+    ilm_struct              ilm_ptr;
+    FT_CHECK_SLA_VER_CNF   *ptrMsg;
+
+	FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_CHECK_SLA_VER_CNF));
+    // if ptrMsg != NULL
+    ptrMsg = (FT_CHECK_SLA_VER_CNF *)ilm_ptr.local_para_ptr;
+    // assign primitive id
+    ptrMsg->header.ft_msg_id = FT_CHECK_SLA_VER_CNF_ID;
+    ptrMsg->status = Custom_META_CheckSlaVer(ft_check_sla_ver_op->sla_ver_from_pc);
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+
+extern kal_bool Custom_META_GetSlaPara(kal_uint8* para, kal_uint32 para_len);
+void FT_GetSlaPara(void)
+{
+    ilm_struct              ilm_ptr;
+    FT_GET_SLA_PARA_CNF     *ptrMsg;
+    kal_uint8   para[META_SLA_RND_LEN];
+    kal_uint32  ret = 0;
+    kal_uint8   cust_para[256];
+    kal_bool    bRet = 0;
+
+	FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_GET_SLA_PARA_CNF));
+
+    ptrMsg = (FT_GET_SLA_PARA_CNF *)ilm_ptr.local_para_ptr;
+    ptrMsg->header.ft_msg_id = FT_GET_SLA_PARA_CNF_ID;
+
+    if (META_SLA_RND_LEN > RND_BUF_LEN)
+    {
+        // ft message buffer is not enough
+        ptrMsg->status = FT_CNF_FAIL;
+        FT_SEND_MSG_TO_PC(&ilm_ptr);
+        return;
+    }
+
+    kal_mem_set(para, 0, META_SLA_RND_LEN);
+
+    ret = MetaSLA_Rnd_Gen(para, RND_BUF_LEN);
+    if (0 == ret)
+    {
+        kal_mem_cpy(ptrMsg->rand_num, para, META_SLA_RND_LEN);
+        ptrMsg->rand_num_len = META_SLA_RND_LEN;
+    }
+    else
+    {
+        ptrMsg->status = ret;
+        ptrMsg->rand_num_len = 0;
+    }
+
+    bRet = Custom_META_GetSlaPara(cust_para, 256);
+    if (true == bRet)
+    {
+        kal_mem_cpy(ptrMsg->cust_para, cust_para, 256);
+    }
+    else
+    {
+        ptrMsg->status = -1;
+    }
+
+    if (ret == 0 && bRet == true)
+    {
+        ptrMsg->status = FT_CNF_OK;
+    }
+
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+
+void FT_VerifySla(FT_VERIFY_SLA_RND_REQ *ft_verify_sla_op)
+{
+    ilm_struct              ilm_ptr;
+    FT_VERIFY_SLA_RND_CNF     *ptrMsg;
+    kal_uint32 ret = 0;
+
+	FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_VERIFY_SLA_RND_CNF));
+
+    ptrMsg = (FT_VERIFY_SLA_RND_CNF *)ilm_ptr.local_para_ptr;
+    ptrMsg->header.ft_msg_id = FT_VERIFY_SLA_RND_CNF_ID;
+
+    ret = MetaSLA_Rnd_Verify(ft_verify_sla_op->encrypted, ft_verify_sla_op->encrypted_len);
+    if (ret == 0)
+    {
+        if (FT_MetaSLA_Is_Enabled())
+        {
+            ptrMsg->status = FT_CNF_OK;
+        }
+        else
+        {
+            ptrMsg->status = -1;
+        }
+    }
+    else
+    {
+        ptrMsg->status = ret;
+    }
+
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+
+#endif // #ifndef L1_SIM
+
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_aux.c b/mcu/middleware/meta/ft/src/ft_fnc_aux.c
new file mode 100644
index 0000000..dca6dad
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_aux.c
@@ -0,0 +1,200 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_aux.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  Auxiliary Function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+ 
+/*************************************************************************
+ * Include Statements for KAL
+ *************************************************************************/
+#if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+ 
+#include "kal_public_defs.h" //MSBB change #include "stack_common.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_msgs.h"
+
+#include "md_mw_sap.h"
+#include "svc_sap.h"
+#include "ft_msgid.h"
+
+#ifdef __MTK_TARGET__
+#include <stdio.h>
+
+#endif
+
+/*************************************************************************
+ * Include Statements for MAUI
+ *************************************************************************/
+
+#include "fta_msg.h"
+#include "ft_private.h"
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "kal_public_defs.h"
+
+void FT_Aux_Operation(ilm_struct *ptrMsg)
+{
+    ilm_struct    ilm_ptr;
+    kal_uint16    pdu_length;
+    kal_uint8	   *pdu_ptr = NULL;
+    //peer_buff_struct *p_peer_buff_ptr;
+    // for debug   
+
+    kal_uint16	pdu_length_new;
+    kal_uint8	*pdu_ptr_new;
+    peer_buff_struct *peer_buff_new;
+
+    FT_AUX_REQ  *p_req = (FT_AUX_REQ *)ptrMsg->local_para_ptr;
+
+    if(ptrMsg->peer_buff_ptr == NULL)  // do nothing
+        return; 
+
+    switch(p_req->type)
+    {
+        case FT_AUX_OP_BASIC:
+        {
+
+            pdu_ptr = get_peer_buff_pdu( ptrMsg->peer_buff_ptr, &pdu_length );
+
+            // construct a peer buffer to send to NVRAM
+            if( NULL != (peer_buff_new=construct_peer_buff(pdu_length, 0, 0, TD_CTRL)) ) 
+            {
+                pdu_ptr_new = get_peer_buff_pdu( peer_buff_new, &pdu_length_new );
+                kal_mem_cpy(pdu_ptr_new, pdu_ptr, pdu_length);
+                peer_buff_new->pdu_len = pdu_length;
+            }
+            FT_ALLOC_OTHER_MSG(&ilm_ptr, sizeof(fta_basic_req_struct) );
+            ilm_ptr.peer_buff_ptr = peer_buff_new;
+
+            FT_SEND_MSG(MOD_FT, MOD_FTA, FT_FTA_SAP , (msg_type)MSG_ID_FTA_BASIC_REQ, &ilm_ptr);
+
+            peer_buff_new=NULL;/* make sure FTA will release the mem*/
+
+            break;
+        }
+        default:
+            break;
+    } 
+}
+
+void FT_Handle_FTA_CNF(ilm_struct *ptrMsg)
+{
+    ilm_struct	 ilm_ptr;
+    FT_AUX_CNF  *ptrMsg2;  // send back to PC
+
+    switch (ptrMsg->msg_id)
+    {
+        case MSG_ID_FTA_BASIC_CNF:
+        {
+            fta_basic_cnf_struct *tmp_local_para = NULL;  // from FTA Task
+            tmp_local_para = (fta_basic_cnf_struct*)ptrMsg->local_para_ptr;
+
+            FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_AUX_CNF) );
+
+            ilm_ptr.peer_buff_ptr = ptrMsg->peer_buff_ptr;
+            ptrMsg2 = (FT_AUX_CNF*)ilm_ptr.local_para_ptr;  
+
+            ptrMsg2->header.ft_msg_id = FT_AUX_CNF_ID;
+            ptrMsg2->type = FT_AUX_OP_BASIC; 
+            ptrMsg2->status = tmp_local_para->status; //FTA_CNF_OK;
+            break;
+        }
+        default:
+            return;
+
+    }
+    // send confirm to PC
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+
+#endif // end of #if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_c2krf.c b/mcu/middleware/meta/ft/src/ft_fnc_c2krf.c
new file mode 100644
index 0000000..5a911ff
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_c2krf.c
@@ -0,0 +1,109 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2016
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2016
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_c2krf.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   Factory testing function for C2K
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#if defined(__C2K_RAT__)
+/*************************************************************************
+* Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h"
+#include "svc_sap.h"
+#include "tst_msgid.h"
+#include "ft_msgid.h"
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_c2krf.h"
+
+/**
+ * @param metaMessage the input message from META tool for CRF test command processing
+ */
+void FT_Crf_Operation(ilm_struct* ptrMsg)
+{
+    ilm_struct crfMessage;
+    FT_CONSTRUCT_CC_MSG(ptrMsg, &crfMessage);
+    FT_SEND_MSG(MOD_FT, MOD_CL1TST, DHL_CL1TST_SAP, MSG_ID_DHL_TO_CL1TST, &crfMessage);   
+}
+
+/**
+ * Confirm message handler for MOD_CL1TST
+ */
+void FT_Crf_ConfirmHandler(ilm_struct* crfMessage)
+{
+    FT_SEND_MSG_TO_PC(crfMessage);
+}
+
+#endif // #if defined(__C2K_RAT__)
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_custom.c b/mcu/middleware/meta/ft/src/ft_fnc_custom.c
new file mode 100644
index 0000000..0f5d054
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_custom.c
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_custom.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  Misc Function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+ 
+/*************************************************************************
+ * Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h" //MSBB change #include "stack_common.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_msgs.h"
+#include "md_mw_sap.h"
+#include "svc_sap.h"
+#include "ft_msgid.h"
+#include "nvram_msgid.h"
+#ifdef __MTK_TARGET__
+#include <stdio.h>
+#endif
+/*************************************************************************
+ * Include Statements for MAUI
+ *************************************************************************/
+#include "ftc_msg.h"
+#include "ft_private.h"
+#include "kal_public_api.h"
+#include "kal_general_types.h"
+#include "kal_public_defs.h"
+void FT_Custom_Operation(ilm_struct *ptrMsg)
+{
+    ilm_struct        ilm_ptr;
+    FT_CUSTOMER_REQ  *p_req = (FT_CUSTOMER_REQ *)ptrMsg->local_para_ptr;
+    if(ptrMsg->peer_buff_ptr == NULL)
+    {
+        return;
+    }
+    switch(p_req->type)
+    {
+        case FT_CUSTOMER_OP_BASIC:
+        {
+            FT_ALLOC_OTHER_MSG(&ilm_ptr, sizeof(ftc_basic_req_struct));
+            ilm_ptr.peer_buff_ptr = ptrMsg->peer_buff_ptr;
+            /* hold this peer buffer so that we don't need to duplicate the buffer */
+            hold_peer_buff(ptrMsg->peer_buff_ptr);
+            FT_SEND_MSG(MOD_FT, MOD_FTC, FT_FTC_SAP , (msg_type)MSG_ID_FTC_BASIC_REQ, &ilm_ptr);
+            break;
+        }
+        default:
+            break;
+    } 
+}
+void FT_Handle_FTC_CNF(ilm_struct *ptrMsg)
+{
+    ilm_struct		ilm_ptr;
+    FT_CUSTOMER_CNF  *ptrMsg2;
+    switch (ptrMsg->msg_id)
+    {
+        case MSG_ID_FTC_BASIC_CNF:
+        {
+            ftc_basic_cnf_struct *tmp_local_para = NULL;
+            tmp_local_para = (ftc_basic_cnf_struct*)ptrMsg->local_para_ptr;
+
+            FT_ALLOC_MSG(&ilm_ptr ,sizeof(FT_CUSTOMER_CNF));
+
+            ilm_ptr.peer_buff_ptr = ptrMsg->peer_buff_ptr;
+            ptrMsg2 = (FT_CUSTOMER_CNF*)ilm_ptr.local_para_ptr;  
+
+            ptrMsg2->header.ft_msg_id = FT_CUSTOM_CNF_ID;
+            ptrMsg2->type = FT_CUSTOMER_OP_BASIC; 
+            ptrMsg2->status = tmp_local_para->status;
+            break;
+        }
+        default:
+            return;
+    }
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_fat.c b/mcu/middleware/meta/ft/src/ft_fnc_fat.c
new file mode 100644
index 0000000..5b0e9d5
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_fat.c
@@ -0,0 +1,1400 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_fat.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT FAT operations
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_fat.h"
+#include "svc_sap.h"
+#include "ft_msgid.h"
+/*************************************************************************
+ * NVRAM header
+ *************************************************************************/
+#include "nvram_interface.h"
+#include "fs_gprot.h"
+/*******************************************************************************
+ *
+ *  Dynamic allocated stack
+ *
+ *******************************************************************************/
+#define FT_STACK_MAGIC  12345
+
+typedef void (*FT_STACK_RELEASE_CALLBACK)(void *data, void *usr_arg);
+
+typedef struct {
+    kal_uint8   *stack;  // used to remember the FindNext calling times,not FS_HANDLE
+
+    kal_uint16  max_node_size;
+    kal_uint16  max_depth;
+    kal_uint16  depth; // 1 ~ N , 0 -> empty
+
+    kal_uint16  magic;  // used to mark if the stack is created or not.
+
+}ft_stack_handle;
+
+kal_uint8 ft_stack_destroy(ft_stack_handle  *p_ft_stack_hdl)
+{
+
+    if( NULL==p_ft_stack_hdl)
+    {
+        return 1;
+    }
+
+    // free buffer
+    free_ctrl_buffer(p_ft_stack_hdl->stack);
+    // reset
+    kal_mem_set(p_ft_stack_hdl, 0, sizeof(ft_stack_handle));
+
+    return 0;
+}
+
+kal_uint8 ft_stack_create(ft_stack_handle *p_ft_stack_hdl, kal_uint16  max_node_size, kal_uint16  max_depth) {
+
+    if( NULL==p_ft_stack_hdl || 0==max_node_size || 0==max_depth ) {
+        return 1;
+    }
+
+    // if un-release handle, destroy first
+    if( FT_STACK_MAGIC == p_ft_stack_hdl->magic ) {
+        if(ft_stack_destroy(p_ft_stack_hdl))
+        {
+            return 2;
+        }
+    }
+
+    // allocate memory
+    if( NULL == (p_ft_stack_hdl->stack=(kal_uint8 *)get_ctrl_buffer(max_node_size*max_depth)) ) {
+        return 2;
+    }
+
+    // initialize
+    p_ft_stack_hdl->max_node_size = max_node_size;
+    p_ft_stack_hdl->max_depth = max_depth;
+    p_ft_stack_hdl->depth = 0;
+    p_ft_stack_hdl->magic = FT_STACK_MAGIC;
+
+    return 0;
+}
+
+kal_uint8 ft_stack_push(ft_stack_handle *p_ft_stack_hdl, kal_uint16 cur_width) {
+
+    if( NULL==p_ft_stack_hdl || FT_STACK_MAGIC!=p_ft_stack_hdl->magic)
+    {
+        return 1;
+    }
+
+    /*
+       if( data_size > p_ft_stack_hdl->max_node_size ) {
+       return 2;
+       }
+       */
+    if( (p_ft_stack_hdl->depth+1) > p_ft_stack_hdl->max_depth ) {
+        return 3;
+    }
+
+    p_ft_stack_hdl->depth++;
+
+    //kal_mem_cpy(p_ft_stack_hdl->stack+p_ft_stack_hdl->max_node_size*(p_ft_stack_hdl->depth-1), data, data_size);
+
+    (*(p_ft_stack_hdl->stack+p_ft_stack_hdl->max_node_size*(p_ft_stack_hdl->depth-1))) = cur_width;
+    return 0;
+}
+
+kal_uint8 ft_stack_pop(ft_stack_handle *p_ft_stack_hdl, kal_uint16 *pWidth) {
+
+    if( NULL==p_ft_stack_hdl || FT_STACK_MAGIC!=p_ft_stack_hdl->magic || NULL == pWidth)
+    {
+        return 1;
+    }
+    /*
+       if( data_size > p_ft_stack_hdl->max_node_size ) {
+       return 2;
+       }
+       */
+    if( 1 > p_ft_stack_hdl->depth ) {
+        return 3;
+    }
+
+    //kal_mem_cpy(data, p_ft_stack_hdl->stack+p_ft_stack_hdl->max_node_size*(p_ft_stack_hdl->depth-1), data_size);
+    (*pWidth) = (*(p_ft_stack_hdl->stack+p_ft_stack_hdl->max_node_size*(p_ft_stack_hdl->depth-1)));
+
+    p_ft_stack_hdl->depth--;
+
+    return 0;
+}
+
+kal_uint16 ft_stack_get_cur_depth(ft_stack_handle *p_ft_stack_hdl) {
+    if( NULL==p_ft_stack_hdl || FT_STACK_MAGIC!=p_ft_stack_hdl->magic ) {
+        return 0;
+    }
+
+    return p_ft_stack_hdl->depth;
+}
+/*******************************************************************************
+ *
+ *  FAT functionality
+ *
+ *******************************************************************************/
+#define FT_FAT_MAX_PEER_SIZE        2048
+#define FT_FAT_MAX_FRAME_SIZE       FT_FAT_MAX_PEER_SIZE/64*56
+
+/**
+ * Get Disk free space
+ */
+kal_int32 FT_GetDiskFreeSpace(const WCHAR* pathname)
+{
+    FS_DiskInfo fs_diskinfo;
+    kal_int32 status;
+    kal_int32 cluster_size = FS_GetClusterSize(pathname[0]);
+    if(FS_DRIVE_NOT_FOUND == cluster_size)
+    {
+        return cluster_size;
+    }
+    if( (status=FS_GetDiskInfo(pathname, &fs_diskinfo, FS_DI_BASIC_INFO|FS_DI_FREE_SPACE)) < 0 )
+    {
+        return status;
+    }
+    return cluster_size * fs_diskinfo.FreeClusters;
+}
+kal_uint8  FT_FAT_SendCnf(FT_FAT_OPERATION *ft_fat_ret, peer_buff_struct *peer_buff) {
+
+    ilm_struct          ilm_ptr;
+    FT_FAT_OPERATION    *ptrMsg;
+
+    FT_ALLOC_MSG(&ilm_ptr,sizeof(FT_FAT_OPERATION));
+
+    /* if ptrMsg != NULL*/
+    ptrMsg = (FT_FAT_OPERATION *)ilm_ptr.local_para_ptr;
+
+    // assign primitive id
+    ptrMsg->header.ft_msg_id = FT_FAT_OPERATION_ID;
+
+    // assign return structure
+    ptrMsg->fs_handle = ft_fat_ret->fs_handle;
+    ptrMsg->fat_op = ft_fat_ret->fat_op;
+    ptrMsg->offset = ft_fat_ret->offset;
+    ptrMsg->last_frame = ft_fat_ret->last_frame;
+    ptrMsg->status = ft_fat_ret->status;
+
+    // assign peer buffer
+    if( NULL != peer_buff ) {
+        ilm_ptr.peer_buff_ptr = peer_buff;
+    }
+
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+    return 0;
+}
+
+WCHAR * ft_wstrnpbrk(const WCHAR *s, const WCHAR *char_set) {
+    const WCHAR *p;
+    kal_int32 char_set_len;
+    kal_int32 i;
+
+    if( NULL == s || NULL == char_set ) {
+        return NULL;
+    }
+
+    char_set_len = kal_wstrlen(char_set);
+    p = s;
+
+    while( 0 != *p ) {
+        for(i=0; i<char_set_len; i++) {
+            if( *p == char_set[i] ) {
+                break;
+            }
+        }
+        // if no char match in char_set
+        if( i == char_set_len ) {
+            return (WCHAR *)p;
+        }
+        p++;
+    }
+
+    return NULL;
+}
+
+WCHAR *ft_wstrichr(const WCHAR *s, int c)
+{
+    WCHAR   tmp;
+
+    // to upper case
+    if( 0x61<=c && 0x7a>=c ) {
+        // a(0x61)~z(0x7a) --> A(0x41)~Z(0x5a)
+        c -= 0x20;
+    }
+
+    do
+    {
+        tmp = *s;
+
+        // to upper case
+        if( 0x61<=tmp && 0x7a>=tmp ) {
+            // a(0x61)~z(0x7a) --> A(0x41)~Z(0x5a)
+            tmp -= 0x20;
+        }
+
+        if (tmp == c)
+            return (WCHAR*)s;
+
+    } while (*s++);
+
+    return (0);
+}
+
+/*-----------------------------------*/
+/* Return : 0 s1 = s2                */
+/*         <0 s1 is less than s2     */
+/*         >0 s1 is greater than s2  */
+/*-----------------------------------*/
+int ft_wstrnicmp(const WCHAR *s1, const WCHAR *s2, int n)
+{
+    WCHAR   c1, c2;
+
+    for(; 0!=*s1 && 0!=*s2 && n>0; s1++, s2++, n--) {
+
+        c1 = *s1;
+        c2 = *s2;
+
+        // to upper case
+        if( 0x61<=c1 && 0x7a>=c1 ) {
+            // a(0x61)~z(0x7a) --> A(0x41)~Z(0x5a)
+            c1 -= 0x20;
+        }
+
+        // to upper case
+        if( 0x61<=c2 && 0x7a>=c2 ) {
+            // a(0x61)~z(0x7a) --> A(0x41)~Z(0x5a)
+            c2 -= 0x20;
+        }
+
+        if( c1 != c2 ) {
+            // not match
+            break;
+        }
+    }
+
+    return (0>=n ? 0 : (*s1 - *s2));
+}
+
+const WCHAR * ft_wstristr(const WCHAR *s, const WCHAR *ptn) {
+
+    if( NULL == s || NULL == ptn ) {
+        return NULL;
+    }
+
+    while( NULL != (s=ft_wstrichr(s, ptn[0])) ) {
+        if(!ft_wstrnicmp(s, ptn, kal_wstrlen(ptn))) {
+            return s;
+        }
+        s++;
+    }
+
+    return NULL;
+}
+
+kal_bool  ft_IsDirectoryExist(const WCHAR *dir) {
+
+    kal_int32   ret;
+
+    if( NULL == dir ) {
+        return KAL_FALSE;
+    }
+
+#if defined(__LOW_COST_SUPPORT_ULC__)
+    if( 0 > (ret = FS_Open(dir, FS_OPEN_DIR|FS_READ_ONLY))){
+        return KAL_FALSE;
+    }else{
+        if( FS_NO_ERROR != FS_Close(ret)){
+            ASSERT(0);
+        }
+    }
+#else
+    if( 0 >= (ret=FS_GetAttributes(dir)) ) {
+        return KAL_FALSE;
+    }
+
+    if(!(FS_ATTR_DIR&((kal_uint32)ret))) {
+        return KAL_FALSE;
+    }
+#endif
+
+    return KAL_TRUE;
+}
+
+kal_int32 ft_CreateFullDirectory(const WCHAR *pathname) {
+
+    kal_int32   ret;
+    WCHAR   *buf, *p, ch;
+
+    if( NULL == pathname ) {
+        return 1;
+    }
+
+    if( NULL == (buf=(WCHAR *)get_ctrl_buffer(sizeof(WCHAR)*(kal_wstrlen(pathname)+1))) ) {
+        return 2;
+    }
+    kal_wstrcpy(buf, pathname);
+    p = buf;
+
+    if( KAL_TRUE != ft_IsDirectoryExist(p) ) {
+
+        // skip drive letter
+        if(!kal_wstrncmp(p+1, L":\\", 2)) {
+            p += 3; // skip "C:\"
+        }
+
+        // skip '\' and '.' to find the first directory name
+        while( NULL != (p=ft_wstrnpbrk(p, L"\\.")) ) {
+
+            // find the first '\' after directory name
+            if( NULL == (p=kal_wstrchr(p, L'\\')) ) {
+                // no more '\' all sub directories are created.
+                break;
+            }
+
+            // temporarily replace with 0
+            ch = *p;
+            *p = 0;
+
+            // create directory
+            if(!ft_IsDirectoryExist(buf)) {
+                if( FS_NO_ERROR != (ret=FS_CreateDir(buf)) ) {
+                    free_ctrl_buffer(buf);
+                    return ret;
+                }
+            }
+
+            // restore char
+            *p = ch;
+        }
+    }
+
+    free_ctrl_buffer(buf);
+
+    return 0;
+}
+
+kal_uint8  ft_fat_fullpath_concatenate(WCHAR *fullpath, kal_uint32 fullpath_len_of_bytes, const WCHAR *subname) {
+
+    kal_uint32  total_length;
+    kal_bool    end_with_backslash;
+
+    // get base_path length first
+    total_length = kal_wstrlen(fullpath);
+
+    // check if end with backslash
+    if( L'\\' == fullpath[total_length-1] ) {
+        end_with_backslash = KAL_TRUE;
+    }
+    else {
+        end_with_backslash = KAL_FALSE;
+        total_length += 1; // add '\' length
+    }
+
+    // calculate total length
+    total_length += kal_wstrlen(subname) + 1; // including 0 terminator char
+
+    if( (fullpath_len_of_bytes/sizeof(WCHAR)) < total_length ) {
+        return 1;
+    }
+
+    if(!end_with_backslash) {
+        kal_wstrcat(fullpath, L"\\");
+    }
+    kal_wstrcat(fullpath, subname);
+
+    return 0;
+}
+
+kal_uint8  ft_fat_fullpath_extract(WCHAR *fullpath, WCHAR **pp_subname) {
+
+    WCHAR *p;
+
+    if( NULL == (p=kal_wstrrchr(fullpath, L'\\')) ) {
+        return 1;
+    }
+
+    *p = 0;
+
+    if( NULL != pp_subname ) {
+        *pp_subname = p+1;
+    }
+
+    return 0;
+}
+/*  for build warning
+    static void ft_fat_find_close_handle(ft_fat_dir_info  *dir_info, void *arg) {
+    FS_FindClose(dir_info->fs_handle);
+    }
+    */
+void ft_fat_free_buffer(ft_stack_handle *p_stack,WCHAR  *fullpath, WCHAR    *found)
+{
+    if(NULL != p_stack)
+        ft_stack_destroy(p_stack);//, (FT_STACK_RELEASE_CALLBACK)ft_fat_find_close_handle, NULL);
+    p_stack = NULL;
+
+    // free fullpath
+    if( NULL != fullpath ) {
+        free_ctrl_buffer(fullpath);
+        fullpath = NULL;
+    }
+
+    // free found
+    if( NULL != found ) {
+        free_ctrl_buffer(found);
+        found = NULL;
+    }
+}
+
+kal_uint8 ft_fat_find_file_only(ft_stack_handle *p_stack,
+        const WCHAR *find_pattern,
+        WCHAR   *fullpath,
+        WCHAR   *found,
+        FT_FAT_FIND_CALLBACK  cb, void *usr_arg)
+{
+    FS_HANDLE               fs_handle;
+    FS_DOSDirEntry      fileinfo;
+    kal_uint8           ret = FT_FAT_FIND_NOT_FOUND;
+
+
+    // concatenate fullpath with file search pattern
+    if(ft_fat_fullpath_concatenate(fullpath, FT_FAT_MAX_FULLPATH, find_pattern)) {
+        ret = 10;
+        ft_fat_free_buffer(p_stack,fullpath,found);
+        return ret;
+    }
+
+    // find first file
+    fs_handle = FS_FindFirst(fullpath, 0, FS_ATTR_DIR, &fileinfo, found, FT_FAT_MAX_FILENAME);
+
+    // remove find_pattern from fullpath
+    if(ft_fat_fullpath_extract(fullpath, NULL)) {
+        ret = 11;
+        ft_fat_free_buffer(p_stack,fullpath,found);
+        return ret;
+    }
+
+    // keep finding file
+    if( 0 <= fs_handle ) {
+
+        do {
+            // file found!
+            ret = 0;
+
+            // concatenate fullpath with found filename
+            if(ft_fat_fullpath_concatenate(fullpath, FT_FAT_MAX_FULLPATH, found)) {
+                ret = 12;
+                ft_fat_free_buffer(p_stack,fullpath,found);
+                return ret;
+            }
+
+            // callback
+            if( 0 != cb(fullpath, &fileinfo, usr_arg) ) {
+                ret = 13;
+                ft_fat_free_buffer(p_stack,fullpath,found);
+                return ret;
+            }
+
+            // extract path
+            if(ft_fat_fullpath_extract(fullpath, NULL)) {
+                ret = 14;
+                ft_fat_free_buffer(p_stack,fullpath,found);
+                return ret;
+            }
+        }while( FS_NO_ERROR == FS_FindNext(fs_handle, &fileinfo, found, FT_FAT_MAX_FILENAME) );
+
+        // close find handle
+        FS_FindClose(fs_handle);
+    }
+
+    return ret;
+
+}
+kal_uint8 ft_fat_find_first_dir(ft_stack_handle *p_stack,
+        ft_fat_dir_info *p_dir_info,
+        WCHAR   *fullpath,
+        WCHAR   *found,
+        FS_DOSDirEntry  *p_fileinfo,
+        kal_bool *p_IsDirSearchGoOn)
+{
+    kal_uint8           ret = FT_FAT_FIND_NOT_FOUND;  // default value
+
+    (*p_IsDirSearchGoOn) = KAL_FALSE;
+
+    // concatenate fullpath with dir search pattern "*"
+    if(ft_fat_fullpath_concatenate(fullpath, FT_FAT_MAX_FULLPATH, L"*")) {
+        ret = 5;
+        ft_fat_free_buffer(p_stack,fullpath,found);
+        return ret;
+    }
+    // find first dir
+    p_dir_info->fs_handle  = FS_FindFirst(fullpath, FS_ATTR_DIR, FS_ATTR_HIDDEN, p_fileinfo, found, FT_FAT_MAX_FILENAME);//update by wayne
+
+    //  p_dir_info->fs_handle = FS_FindFirst(fullpath, FS_ATTR_DIR, 0, p_fileinfo, found, FT_FAT_MAX_FILENAME);
+
+
+    //cur_width=0;
+
+
+    // remove dir search pattern "*" from fullpath
+    if(ft_fat_fullpath_extract(fullpath, NULL)) {
+        ret = 6;
+        ft_fat_free_buffer(p_stack,fullpath,found);
+        return ret;
+    }
+
+    return ret;
+}
+
+kal_uint8 ft_fat_find(const WCHAR *base_path, const WCHAR *find_pattern, FT_FAT_FIND_MODE  mode, FT_FAT_FIND_CALLBACK  cb, void *usr_arg) {
+
+    ft_stack_handle     stack;
+    ft_fat_dir_info     dir_info;
+    //  FS_HANDLE           fs_handle;  // for build warning
+    FS_DOSDirEntry      fileinfo;
+
+    kal_uint16    cur_width;
+    kal_uint16    get_width;
+    kal_uint16    i;
+
+    kal_uint8           ret = FT_FAT_FIND_NOT_FOUND;
+    kal_bool            IsDirSearchGoOn;
+    kal_bool            IsSearchSubDirGoOn;
+    WCHAR               *fullpath = NULL;
+    WCHAR               *found = NULL;
+
+    kal_uint8    test_ret = 0;
+
+
+    if( NULL==base_path || 0==base_path[0] || NULL==find_pattern || 0==find_pattern[0] || NULL==cb ) {
+        return 1;
+    }
+
+    // create fullpath buffer
+    if( NULL == (fullpath=(WCHAR *)get_ctrl_buffer(FT_FAT_MAX_FULLPATH)) ) {
+        ret = 2;
+        goto free_buffer;
+    }
+
+    // create found buffer
+    if( NULL == (found=(WCHAR *)get_ctrl_buffer(FT_FAT_MAX_FILENAME)) ) {
+        ret = 3;
+        goto free_buffer;
+    }
+
+    // create stack for depth first dir search
+    //if(ft_stack_create(&stack, sizeof(ft_fat_dir_info), FT_FAT_MAX_DIR_DEPTH)) { //FT_FAT_MAX_DIR_DEPTH
+	memset(&stack, 0, sizeof(ft_stack_handle));
+    if(ft_stack_create(&stack,sizeof(kal_uint16), FT_FAT_MAX_DIR_DEPTH)) { //FT_FAT_MAX_DIR_DEPTH
+        ret = 4;
+        goto free_buffer;
+    }
+
+    // copy base_path to fullpath
+    kal_wstrcpy(fullpath, base_path);
+
+    // check find mode
+    if( FT_FAT_FIND_FILE == mode ) {
+        //goto file_search;
+        ret = ft_fat_find_file_only(&stack,find_pattern,fullpath,found,cb,usr_arg);
+    }
+    else // FT_FAT_FIND_FILE_RECURSIVE  or FT_FAT_FIND_DIR_RECURSIVE
+    {
+        // search the first directory in the base_path == lable: dir_search
+        ret = ft_fat_find_first_dir(&stack, &dir_info, fullpath, found, &fileinfo, &IsDirSearchGoOn);
+        cur_width=0;
+        if(ret != FT_FAT_FIND_NOT_FOUND)  goto free_buffer;
+
+        IsSearchSubDirGoOn = KAL_FALSE;
+        for(; ;)
+        {
+
+            if( 0 <= dir_info.fs_handle )
+            {
+                do{
+                    cur_width++;
+
+                    // if dir search go on, FindNext() again first
+                    if(IsDirSearchGoOn) {
+                        IsDirSearchGoOn = KAL_FALSE;
+                        continue;
+                    }
+                    // if found is "." or ".." , skip it
+                    if( !kal_wstrcmp(found, L".") || !kal_wstrcmp(found, L"..") ) {
+                        continue;
+                    }
+                    if( FT_FAT_FIND_DIR_RECURSIVE == mode ) {
+                        // dir found!
+                        ret = 0;
+                    }
+                    //close the file handler before we push it!
+                    FS_FindClose(dir_info.fs_handle);
+
+                    // push current dir
+                    cur_width--;
+                    //test_ret = ft_stack_push(&stack, &dir_info, sizeof(dir_info), cur_width);
+                    test_ret = ft_stack_push(&stack, cur_width);
+                    if(test_ret>0)
+                    {
+                        if(test_ret == 1)      ret = 60;
+                        else if(test_ret ==2)  ret = 61;
+                        else if(test_ret ==3)  ret = 62;
+
+                        goto free_buffer;
+                    }
+
+                    // concatenate with the found sub dir
+                    if(ft_fat_fullpath_concatenate(fullpath, FT_FAT_MAX_FULLPATH, found)) {
+                        ret = 8;
+                        goto free_buffer;
+                    }
+
+                    // callback
+                    if( 0 != cb(fullpath, &fileinfo, usr_arg) ) {
+                        ret = 9;
+                        goto free_buffer;
+                    }
+
+                    // find from sub dir
+                    //goto dir_search;
+                    if(ret != 0)
+                        ret = ft_fat_find_first_dir(&stack, &dir_info, fullpath, found, &fileinfo, &IsDirSearchGoOn);
+                    else
+                        ft_fat_find_first_dir(&stack, &dir_info, fullpath, found, &fileinfo, &IsDirSearchGoOn);
+
+                    cur_width=0;
+                    if(ret != 0 && ret != FT_FAT_FIND_NOT_FOUND)  goto free_buffer;
+
+                    IsSearchSubDirGoOn = KAL_TRUE;
+                    break; // break the while loop
+                    //goto dir_search_go_on;
+
+                }while( FS_NO_ERROR == FS_FindNext(dir_info.fs_handle, &fileinfo, found, FT_FAT_MAX_FILENAME) );
+
+                if(IsSearchSubDirGoOn == KAL_TRUE)
+                {
+                    IsSearchSubDirGoOn = KAL_FALSE;
+                    continue;  // start from the for loop again
+
+                }
+                // close find handle
+                FS_FindClose(dir_info.fs_handle);
+
+
+
+            }// end of if( 0 <= dir_info.fs_handle )
+
+
+            // file_search: find file
+            if(FT_FAT_FIND_FILE_RECURSIVE == mode)
+            {
+                if(ret!= 0)
+                    ret = ft_fat_find_file_only(&stack,find_pattern,fullpath,found,cb,usr_arg);
+                else
+                    ft_fat_find_file_only(&stack,find_pattern,fullpath,found,cb,usr_arg);
+
+                if(ret != 0 && ret != FT_FAT_FIND_NOT_FOUND)  goto free_buffer; // error
+            }
+
+
+            // pop to parent dir
+            if(!ft_stack_pop(&stack, &get_width)) {
+                // extract fullpath to parent dir
+                if(ft_fat_fullpath_extract(fullpath, NULL)) {
+                    ret = 15;
+                    goto free_buffer;
+                }
+
+
+                // open the directory after we pop it  =========================
+                // concatenate fullpath with dir search pattern "*"
+                if(ft_fat_fullpath_concatenate(fullpath, FT_FAT_MAX_FULLPATH, L"*")) {
+                    ret = 70;
+                    goto free_buffer;
+                }
+
+                //dir_info.fs_handle = FS_FindFirst(fullpath, FS_ATTR_DIR, 0, &fileinfo, found, FT_FAT_MAX_FILENAME);
+                dir_info.fs_handle = FS_FindFirst(fullpath, FS_ATTR_DIR, FS_ATTR_HIDDEN , &fileinfo, found, FT_FAT_MAX_FILENAME);
+                for(i=0;i<get_width;i++)
+                {
+                    if(FS_FindNext(dir_info.fs_handle, &fileinfo, found, FT_FAT_MAX_FILENAME) !=FS_NO_ERROR)
+                    {
+                        ret = 73;
+                        goto free_buffer;
+                    }
+                }
+
+                cur_width = get_width;
+
+                // remove dir search pattern "*" from fullpath
+                if(ft_fat_fullpath_extract(fullpath, NULL)) {
+                    ret = 71;
+                    goto free_buffer;
+                }
+                //===========================================================
+
+                // dir search go on
+                IsDirSearchGoOn = KAL_TRUE;
+                //goto dir_search_go_on;
+            }// end of pop up the parent dir
+            else
+            {
+                break;  // exit the for(; ;) loop
+            }
+        } // end of for(; ;)
+
+
+    } // end of else
+free_buffer:
+
+    ft_fat_free_buffer(&stack,fullpath,found);
+    return ret;
+}
+
+static kal_bool ft_fat_check_if_path_restricted(const WCHAR *path)
+{
+    return nvram_check_hidden_file(path, (ft_gl_path_check_flag) ? KAL_FALSE : KAL_TRUE );
+}
+
+typedef struct {
+    FT_FAT_OPERATION    *p_fat_ret;
+    peer_buff_struct    **pp_peer_buff_ret;
+    FT_FAT_FIND_MODE    find_mode;
+}ft_fat_find_cb_arg;
+
+static kal_int8 ft_fat_update_peer_buf(const WCHAR *fullpath, const FS_DOSDirEntry  *dos_info, ft_fat_find_cb_arg *arg) {
+
+    kal_uint32  filesize;
+    kal_uint16  pdu_length;
+    kal_char    *pdu_ptr;
+
+    // check find mode
+    if( FT_FAT_FIND_DIR_RECURSIVE == arg->find_mode ) {
+        // find dir mode, skip all non-dir found items
+        if(!(FS_ATTR_DIR&(dos_info->Attributes))) {
+            return 0;
+        }
+    }
+    else {
+        // find file mode, skip all non-file found items
+        if((FS_ATTR_DIR&(dos_info->Attributes))) {
+            return 0;
+        }
+    }
+
+    // check path restriction
+    if(ft_fat_check_if_path_restricted(fullpath)) {
+        return 0;
+    }
+
+allocate_peer_buf:
+    // if peer buffer is not allocated, allocate it now.
+    if( NULL == *(arg->pp_peer_buff_ret) ) {
+        if( NULL == (*(arg->pp_peer_buff_ret)=construct_peer_buff(FT_FAT_MAX_FRAME_SIZE, 0, 0, TD_CTRL)) ) {
+            return 1;
+        }
+        (*(arg->pp_peer_buff_ret))->pdu_len = 0;
+    }
+
+    // data format: filesize(4bytes) + filepath(string) + '\0'
+
+    // if data exceed limit, flush out.
+    if( FT_FAT_MAX_FRAME_SIZE < ((*(arg->pp_peer_buff_ret))->pdu_len+4+((kal_wstrlen(fullpath)+1)*2)) ) {
+        // set last_frame = 0
+        arg->p_fat_ret->last_frame = 0;
+        arg->p_fat_ret->status = FT_CNF_OK;
+        // send confirm
+        FT_FAT_SendCnf(arg->p_fat_ret, *(arg->pp_peer_buff_ret));
+
+        // sleep to wait for tst flush out data
+        kal_sleep_task(50);
+
+        // allocate peer buffer again
+        *(arg->pp_peer_buff_ret) = NULL;
+        goto allocate_peer_buf;
+    }
+
+    pdu_ptr = get_peer_buff_pdu( *(arg->pp_peer_buff_ret), &pdu_length );
+
+    // store filesize
+    filesize = dos_info->FileSize;
+    kal_mem_cpy(pdu_ptr+pdu_length, &filesize, sizeof(filesize));
+    // copy filepath
+    kal_mem_cpy(pdu_ptr+pdu_length+sizeof(filesize), (void *)fullpath, (kal_wstrlen(fullpath)+1)*2);
+    // update pdu_len
+    (*(arg->pp_peer_buff_ret))->pdu_len += ( sizeof(filesize) + (kal_wstrlen(fullpath)+1)*2 );
+
+    return 0;
+}
+
+#define MAX_OPENED_HANDLE       32
+static FS_HANDLE    g_FAT_HandleArrary[MAX_OPENED_HANDLE];
+
+kal_int8  FT_FAT_Handle_Clear(void) {
+    kal_uint16  i;
+    for(i=0; i<MAX_OPENED_HANDLE; i++) {
+        g_FAT_HandleArrary[i] = -1;
+    }
+    return 0;
+}
+
+kal_int8  FT_FAT_Handle_Add(FS_HANDLE  handle) {
+    kal_uint16  i;
+    for(i=0; i<MAX_OPENED_HANDLE; i++) {
+        if( -1 == g_FAT_HandleArrary[i] ) {
+            g_FAT_HandleArrary[i] = handle;
+            return 0;
+        }
+    }
+    return 1;
+}
+
+
+kal_int8  FT_FAT_Handle_Del(FS_HANDLE  handle) {
+    kal_uint16  i;
+    for(i=0; i<MAX_OPENED_HANDLE; i++) {
+        if( handle == g_FAT_HandleArrary[i] ) {
+            g_FAT_HandleArrary[i] = -1;
+            return 0;
+        }
+    }
+    return 1;
+}
+
+kal_bool  FT_FAT_Handle_IsAvailable(void) {
+    kal_uint16  i;
+    for(i=0; i<MAX_OPENED_HANDLE; i++) {
+        if( -1 == g_FAT_HandleArrary[i] ) {
+            return KAL_TRUE;
+        }
+    }
+    return KAL_FALSE;
+}
+
+#if !defined(__LOW_COST_SUPPORT_ULC__)
+kal_bool  FT_FAT_IsFileAlreadyOpened(const WCHAR  *filename, FS_HANDLE  *handle) {
+    kal_uint16  i;
+    FS_FileInfo     file_info;
+    for(i=0; i<MAX_OPENED_HANDLE; i++) {
+        if( -1 != g_FAT_HandleArrary[i] ) {
+            // get file handel info
+            if( 0 <= FS_GetFileInfo(g_FAT_HandleArrary[i], &file_info) ) {
+
+                // compare full filename
+                if(!ft_wstrnicmp(filename, (WCHAR *)file_info.FullName, kal_wstrlen(filename))) {
+                    // filename is the same, this file is already opened!
+                    if( NULL != handle ) {
+                        *handle = g_FAT_HandleArrary[i];
+                    }
+                    return KAL_TRUE;
+                }
+
+            }
+        }
+    }
+    return KAL_FALSE;
+}
+
+kal_int8  FT_FAT_CloseFileIfAlreadyOpened(const WCHAR  *filename) {
+    FS_HANDLE   handle;
+    // check if handle is already opened
+    if( KAL_TRUE == FT_FAT_IsFileAlreadyOpened(filename, &handle) ) {
+        if( FS_NO_ERROR != FS_Close(handle) ) {
+            return 1;
+        }
+        // delete this handle from opened handle arrary
+        if( 0 != FT_FAT_Handle_Del(handle) ) {
+            return 2;
+        }
+    }
+    return 0;
+}
+#endif
+
+void FT_FAT_Operation(FT_FAT_OPERATION *ft_fat_op, peer_buff_struct *peer_buff_in) {
+
+    kal_uint32  mode;
+    kal_uint16  pdu_length;
+    kal_char    *pdu_ptr;
+    peer_buff_struct *peer_buff_ret;
+    kal_uint32  finish_bytes;
+    FT_FAT_OPERATION    ft_fat_ret;
+    ft_fat_find_cb_arg      ft_fat_update_peer_buf_arg;
+    kal_uint32  filesize;
+    WCHAR *w_filepath_1;
+    WCHAR *w_filepath_2;
+    FT_FAT_DiskInfo_T   DiskInfo;
+    FS_DiskInfo         fs_diskinfo;
+    //kal_uint8 folder_total_amount;
+    //kal_uint8 folder_idx;
+
+    // initialize
+    pdu_length = 0;
+    pdu_ptr = NULL;
+    peer_buff_ret = NULL;
+    kal_mem_set(&ft_fat_ret, '\0', sizeof(FT_FAT_OPERATION));
+
+    if( NULL != peer_buff_in ) {
+        pdu_ptr = get_peer_buff_pdu( peer_buff_in, &pdu_length );
+    }
+
+    ft_fat_ret.fat_op = ft_fat_op->fat_op;
+    ft_fat_ret.status = FT_CNF_FAIL;
+    switch((int)ft_fat_op->fat_op) {
+        case FT_FAT_OP_OPEN|FT_FAT_OP_READ:
+        case FT_FAT_OP_OPEN|FT_FAT_OP_WRITE:
+            if( NULL != peer_buff_in && 0 < pdu_length ) {
+
+                // check if filepath too long
+                if( FT_FAT_MAX_FULLPATH < pdu_length ) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_TOO_LONG;
+                    break;
+                }
+
+                // cast to WCHAR
+                w_filepath_1 = (WCHAR *)pdu_ptr;
+
+                // check path restriction
+                if(ft_fat_check_if_path_restricted(w_filepath_1)) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_RESTRICTION;
+                    break;
+                }
+
+                // create dir
+                if( 0 != (ft_fat_ret.status=ft_CreateFullDirectory(w_filepath_1)) ) {
+                    break;
+                }
+
+                if( (FT_FAT_OP_OPEN+FT_FAT_OP_WRITE) == ft_fat_ret.fat_op ) {
+                    mode = FS_CREATE_ALWAYS;
+                }
+                else {
+                    mode = FS_READ_ONLY;
+                }
+
+#if !defined(__LOW_COST_SUPPORT_ULC__)
+                // close file if it is already opened
+                FT_FAT_CloseFileIfAlreadyOpened(w_filepath_1);
+#endif
+
+                // check if file handle available
+                if( KAL_TRUE != FT_FAT_Handle_IsAvailable() ) {
+                    ft_fat_ret.status = FS_TOO_MANY_FILES;
+                    break;
+                }
+
+                if( 0 <= (ft_fat_ret.status=FS_Open(w_filepath_1, mode)) ) {
+                    // assign file handle
+                    ft_fat_ret.fs_handle = ft_fat_ret.status;
+                    // ok
+                    ft_fat_ret.status = FT_CNF_OK;
+                    // add this handle into opened handle arrary
+                    FT_FAT_Handle_Add(ft_fat_ret.fs_handle);
+                    // send confirm
+                    break;
+                }
+            }
+            break;
+        case FT_FAT_OP_READ:
+            ft_fat_ret.fs_handle = ft_fat_op->fs_handle;
+            ft_fat_ret.offset = ft_fat_op->offset;
+            ft_fat_ret.last_frame = 0;
+            if( 0 <= (ft_fat_ret.status=FS_Seek(ft_fat_ret.fs_handle, ft_fat_ret.offset, FS_FILE_BEGIN))) {
+                finish_bytes = 0;
+                if( NULL != (peer_buff_ret=construct_peer_buff(FT_FAT_MAX_FRAME_SIZE, 0, 0, TD_CTRL)) ) {
+
+                    pdu_ptr = get_peer_buff_pdu( peer_buff_ret, &pdu_length );
+
+                    if( FS_NO_ERROR == (ft_fat_ret.status=FS_GetFileSize(ft_fat_ret.fs_handle, &filesize)) ) {
+
+                        if( FS_NO_ERROR == (ft_fat_ret.status=FS_Read(ft_fat_ret.fs_handle, pdu_ptr, FT_FAT_MAX_FRAME_SIZE, &finish_bytes)) ) {
+                            if( (finish_bytes+ft_fat_ret.offset) >= filesize ) {
+                                ft_fat_ret.last_frame = 1;
+                            }
+                            ft_fat_ret.status = FT_CNF_OK;
+                            peer_buff_ret->pdu_len = finish_bytes;
+                            // send confirm
+                            break;
+                        }
+
+                    }
+
+                    // error, free buffer
+                    free_peer_buff(peer_buff_ret);
+                    peer_buff_ret = NULL;
+                }
+            }
+            break;
+        case FT_FAT_OP_WRITE:
+            ft_fat_ret.fs_handle = ft_fat_op->fs_handle;
+            ft_fat_ret.offset = ft_fat_op->offset;
+            if( NULL != peer_buff_in && 0 < pdu_length ) {
+                if( 0 <= (ft_fat_ret.status=FS_Seek(ft_fat_ret.fs_handle, ft_fat_ret.offset, FS_FILE_BEGIN))) {
+                    finish_bytes = 0;
+                    if( FS_NO_ERROR==(ft_fat_ret.status=FS_Write(ft_fat_ret.fs_handle, pdu_ptr, pdu_length, &finish_bytes)) && pdu_length==finish_bytes ) {
+                        ft_fat_ret.status = FT_CNF_OK;
+                        // send confirm
+                        break;
+                    }
+                }
+            }
+            break;
+        case FT_FAT_OP_CLOSE:
+            ft_fat_ret.fs_handle = ft_fat_op->fs_handle;
+            if( FS_NO_ERROR == (ft_fat_ret.status=FS_Close(ft_fat_ret.fs_handle)) ) {
+                // ok
+                ft_fat_ret.status = FT_CNF_OK;
+                // delete this handle from opened handle arrary
+                FT_FAT_Handle_Del(ft_fat_ret.fs_handle);
+                // send confirm
+                break;
+            }
+            break;
+        case FT_FAT_OP_FILESIZE:
+            ft_fat_ret.fs_handle = ft_fat_op->fs_handle;
+            if( FS_NO_ERROR == (ft_fat_ret.status=FS_GetFileSize(ft_fat_ret.fs_handle, (kal_uint32 *)&(ft_fat_ret.offset))) ) {
+                // ok
+                ft_fat_ret.status = FT_CNF_OK;
+                // send confirm
+                break;
+            }
+            break;
+        case FT_FAT_OP_DELETE:
+            if( NULL != peer_buff_in && 0 < pdu_length ) {
+
+                // check if filepath too long
+                if( FT_FAT_MAX_FULLPATH < pdu_length ) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_TOO_LONG;
+                    break;
+                }
+
+                // cast to WCHAR
+                w_filepath_1 = (WCHAR *)pdu_ptr;
+
+                // check path restriction
+                if(ft_fat_check_if_path_restricted(w_filepath_1)) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_RESTRICTION;
+                    break;
+                }
+
+#if !defined(__LOW_COST_SUPPORT_ULC__)
+                // close file if it is already opened
+                FT_FAT_CloseFileIfAlreadyOpened(w_filepath_1);
+#endif
+                if( FS_NO_ERROR == (ft_fat_ret.status=FS_Delete(w_filepath_1)) ) {
+                    // ok
+                    ft_fat_ret.status = FT_CNF_OK;
+                    // send confirm
+                    break;
+                }
+            }
+            break;
+        case FT_FAT_OP_MOVE:
+#if defined(__LOW_COST_SUPPORT_ULC__)
+            ft_fat_ret.status = FT_FAT_ERR_ACTION_NOT_SUPPORT;
+#else  // non __LOW_COST_SUPPORT_LC__
+            if( NULL != peer_buff_in && 0 < pdu_length ) {
+
+                w_filepath_1 = (WCHAR *)pdu_ptr;
+                w_filepath_2 = w_filepath_1+kal_wstrlen(w_filepath_1)+1;
+
+                // check if src path too long
+                if( FT_FAT_MAX_FULLPATH < (kal_wstrlen(w_filepath_1)+1)*2 ) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_TOO_LONG;
+                    break;
+                }
+
+                // check if dest path too long
+                if( FT_FAT_MAX_FULLPATH < (kal_wstrlen(w_filepath_2)+1)*2 ) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_TOO_LONG;
+                    break;
+                }
+
+                // check path restriction
+                if(ft_fat_check_if_path_restricted(w_filepath_1)) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_RESTRICTION;
+                    break;
+                }
+
+                // check path restriction
+                if(ft_fat_check_if_path_restricted(w_filepath_2)) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_RESTRICTION;
+                    break;
+                }
+
+                // close file if it is already opened
+                FT_FAT_CloseFileIfAlreadyOpened(w_filepath_1);
+                FT_FAT_CloseFileIfAlreadyOpened(w_filepath_2);
+
+                if( FS_NO_ERROR == (ft_fat_ret.status=FS_Rename(w_filepath_1, w_filepath_2)) ) {
+                    // ok
+                    ft_fat_ret.status = FT_CNF_OK;
+                    // send confirm
+                    break;
+                }
+            }
+#endif // non __LOW_COST_SUPPORT_LC__
+            break;
+        case FT_FAT_OP_FIND_FILE:
+        case FT_FAT_OP_FIND_FILE_RECURSIVE:
+        case FT_FAT_OP_FIND_DIR_RECURSIVE:
+            if( NULL != peer_buff_in && 0 < pdu_length ) {
+
+                w_filepath_1 = (WCHAR *)pdu_ptr;
+                w_filepath_2 = w_filepath_1+kal_wstrlen(w_filepath_1)+1;
+
+                // check if base_dir too long
+                if( FT_FAT_MAX_FULLPATH < (kal_wstrlen(w_filepath_1)+1)*2 ) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_TOO_LONG;
+                    break;
+                }
+
+                // check if find_pattern path too long
+                if( FT_FAT_MAX_FULLPATH < (kal_wstrlen(w_filepath_2)+1)*2 ) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_TOO_LONG;
+                    break;
+                }
+
+                // check path restriction in file search case
+                if( (FT_FAT_OP_FIND_DIR_RECURSIVE != ft_fat_op->fat_op) &&
+                        ft_fat_check_if_path_restricted(w_filepath_1) ) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_RESTRICTION;
+                    break;
+                }
+
+                // find
+                peer_buff_ret = NULL;
+                ft_fat_update_peer_buf_arg.p_fat_ret = &ft_fat_ret;
+                ft_fat_update_peer_buf_arg.pp_peer_buff_ret = &peer_buff_ret;
+                switch(ft_fat_op->fat_op) {
+                    case FT_FAT_OP_FIND_FILE:
+                        ft_fat_update_peer_buf_arg.find_mode = FT_FAT_FIND_FILE;
+                        break;
+                    case FT_FAT_OP_FIND_DIR_RECURSIVE:
+                        ft_fat_update_peer_buf_arg.find_mode = FT_FAT_FIND_DIR_RECURSIVE;
+                        break;
+                    case FT_FAT_OP_FIND_FILE_RECURSIVE:
+                    default:
+                        ft_fat_update_peer_buf_arg.find_mode = FT_FAT_FIND_FILE_RECURSIVE;
+                        break;
+                }
+                if( 0 == (ft_fat_ret.status=ft_fat_find(
+                                w_filepath_1,
+                                w_filepath_2,
+                                ft_fat_update_peer_buf_arg.find_mode,
+                                (FT_FAT_FIND_CALLBACK)ft_fat_update_peer_buf,
+                                &ft_fat_update_peer_buf_arg)) )
+                {
+                    // found
+                    ft_fat_ret.last_frame = 1;
+                    ft_fat_ret.status = FT_CNF_OK;
+                }
+            }
+            break;
+        case FT_FAT_OP_GET_DISK_INFO:
+            if( NULL != peer_buff_in && 0 < pdu_length ) {
+
+                // cast to WCHAR
+                w_filepath_1 = (WCHAR *)pdu_ptr;
+
+                /*              // check path restriction
+                                if(ft_fat_check_if_path_restricted(w_filepath_1)) {
+                                ft_fat_ret.status = FT_FAT_ERR_PATH_RESTRICTION;
+                                break;
+                                }*/
+
+                if( NULL != (peer_buff_ret=construct_peer_buff(sizeof(FT_FAT_DiskInfo_T), 0, 0, TD_CTRL)) ) {
+
+                    pdu_ptr = get_peer_buff_pdu( peer_buff_ret, &pdu_length );
+
+                    kal_mem_set(&fs_diskinfo, 0, sizeof(fs_diskinfo));
+                    if( 0 <= (ft_fat_ret.status=FS_GetDiskInfo(w_filepath_1, &fs_diskinfo, FS_DI_BASIC_INFO|FS_DI_FREE_SPACE)) ) {
+                        // ok
+                        ft_fat_ret.status = FT_CNF_OK;
+                        // fill FT_FAT_DiskInfo_T
+                        DiskInfo.Type = fs_diskinfo.FATType;
+                        DiskInfo.SectorsPerCluster = fs_diskinfo.SectorsPerCluster;
+                        DiskInfo.TotalClusters = fs_diskinfo.TotalClusters;
+                        DiskInfo.FreeClusters = fs_diskinfo.FreeClusters;
+                        kal_mem_cpy(pdu_ptr, &DiskInfo, sizeof(FT_FAT_DiskInfo_T));
+                        // send confirm
+                        break;
+                    }
+
+                    // error, free buffer
+                    free_peer_buff(peer_buff_ret);
+                    peer_buff_ret = NULL;
+                }
+            }
+            break;
+        case FT_FAT_OP_RMDIR:
+#if defined(__LOW_COST_SUPPORT_ULC__)
+            ft_fat_ret.status = FT_FAT_ERR_ACTION_NOT_SUPPORT;
+#else   // non __LOW_COST_SUPPORT_ULC__
+            if( NULL != peer_buff_in && 0 < pdu_length ) {
+
+                // check if filepath too long
+                if( FT_FAT_MAX_FULLPATH < pdu_length ) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_TOO_LONG;
+                    break;
+                }
+
+                // cast to WCHAR
+                w_filepath_1 = (WCHAR *)pdu_ptr;
+
+                // check path restriction
+                if(ft_fat_check_if_path_restricted(w_filepath_1)) {
+                    ft_fat_ret.status = FT_FAT_ERR_PATH_RESTRICTION;
+                    break;
+                }
+
+                // check if directory
+                if(!ft_IsDirectoryExist(w_filepath_1)) {
+                    ft_fat_ret.status = FT_FAT_ERR_DIR_NOT_EXIST;
+                    break;
+                }
+
+                // call FS_XDelete
+                if( 0 <= (ft_fat_ret.status=FS_XDelete(w_filepath_1, FS_FILE_TYPE|FS_DIR_TYPE|FS_RECURSIVE_TYPE, NULL, 0)) ) {
+                    ft_fat_ret.status = FT_CNF_OK;
+                }
+            }
+#endif // end non __LOW_COST_SUPPORT_ULC__
+            break;
+        case FT_FAT_OP_GET_DRIVE_TYPE:
+            {
+                // Since FS_GetDevType is not supported
+                ft_fat_ret.status = FT_FAT_ERR_ACTION_NOT_SUPPORT;
+                break;
+            }
+        default:
+            break;
+    }
+
+    // send confirm
+    ft_gl_path_check_flag = KAL_TRUE; // re-enable the path restriction!
+    FT_FAT_SendCnf(&ft_fat_ret, peer_buff_ret);
+}
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_l1rf.c b/mcu/middleware/meta/ft/src/ft_fnc_l1rf.c
new file mode 100644
index 0000000..cce84e4
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_l1rf.c
@@ -0,0 +1,252 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_l1rf.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   Factory testing function for GSM/GPRS/EDGE
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+/*************************************************************************
+* Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h"
+#include "task_config.h"
+#include "svc_sap.h"
+#include "md_sap.h"
+#include "ft_msgid.h"
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_l1rf.h"
+/**
+ * @param metaMessage the input message from META tool for RF test command processing
+ */
+void FT_Rf_Operation(ilm_struct *ptrMsg)
+{
+    ilm_struct rfMessage;
+    FT_CONSTRUCT_CC_MSG(ptrMsg, &rfMessage);
+    FT_SEND_MSG(MOD_FT, MOD_L1, FT_GL1TST_SAP, MSG_ID_FT_TO_GL1TST, &rfMessage);    
+}
+/**
+ * Confirm message handler for MOD_L1
+ */
+void FT_Rf_ConfirmHandler(ilm_struct* rfMessage)
+{
+    ft_rf_test_cnf_T *ptrMsg;
+    ptrMsg = (ft_rf_test_cnf_T *)rfMessage->local_para_ptr;    
+    if(ptrMsg->type == RF_TEST_CMD_CHECK_IF_FUNC_EXIST)
+    {
+        FT_UTILITY_COMMAND_CNF  cnf;
+        kal_mem_set(&cnf, '\0', sizeof(cnf));
+        cnf.status = (ptrMsg->param.CheckIfFuncExist.result==1)?FT_CNF_OK:FT_CNF_FAIL;
+        cnf.result.CheckIfFuncExist.query_ft_msg_id = ptrMsg->header.ft_msg_id;
+        cnf.result.CheckIfFuncExist.query_op_code = ptrMsg->param.CheckIfFuncExist.query_op_code;
+        FT_UTIL_SendCnf(&cnf, NULL);
+        return;
+    }
+    FT_SEND_MSG_TO_PC(rfMessage);
+}
+void FT_RfCheckFunctionSupported(kal_uint32 query_op_code)
+{
+    ilm_struct ilm_ptr;
+    ft_rf_test_req_T *ptrMsg;	
+    FT_ALLOC_OTHER_CC_MSG( &ilm_ptr, sizeof(ft_rf_test_req_T) );
+    // local parameter    
+    ptrMsg = (ft_rf_test_req_T *)ilm_ptr.local_para_ptr;
+    ptrMsg->header.ft_msg_id = FT_RF_TEST_REQ_ID;  
+    ptrMsg->type = RF_TEST_CMD_CHECK_IF_FUNC_EXIST;
+    ptrMsg->param.query_op_code = (RfTestCmdType)query_op_code;
+    FT_SEND_MSG(MOD_FT, MOD_L1, FT_GL1TST_SAP, MSG_ID_FT_TO_GL1TST, &ilm_ptr);   
+}
+#endif //#if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_l4.c b/mcu/middleware/meta/ft/src/ft_fnc_l4.c
new file mode 100644
index 0000000..bff3c45
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_l4.c
@@ -0,0 +1,105 @@
+#if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT) || defined(DUMMY_PROTOCOL)
+/*************************************************************************
+* Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h"
+#include "md_sap.h"
+#include "tst_msgid.h"
+#include "ft_msgid.h"
+#include "ps_public_l4_msgid.h"
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_l4.h"
+#include "ft_msg_l4.h"
+/**
+ * @param metaMessage and MOD_L4C  the input message for L4 AT test command processing
+ */
+void FT_L4_Operation(ilm_struct* ptrMsg)
+{
+    ilm_struct l4Message;
+
+    if(MOD_L4C == ptrMsg->src_mod_id)
+    {
+        switch (ptrMsg->msg_id)
+        {
+            case MSG_ID_FT_ENTER_FACTORY_MODE_CNF:
+            {
+                ft_enter_factory_mode_cnf_struct *l4CnfMsg;
+                FT_L4_ATCMD_CNF *ptrCnfMsg;
+                l4CnfMsg = (ft_enter_factory_mode_cnf_struct*)ptrMsg->local_para_ptr;
+                FT_ALLOC_MSG(&l4Message, sizeof(FT_L4_ATCMD_CNF));
+                ptrCnfMsg = (FT_L4_ATCMD_CNF *)l4Message.local_para_ptr;
+                ptrCnfMsg->header.ft_msg_id = FT_L4_ATCMD_CNF_ID;
+                ptrCnfMsg->type = 1;
+                if(l4CnfMsg->result == FT_MODE_SWITCH_SUCCESS)
+                {
+                    ptrCnfMsg->status = FT_CNF_OK;
+                }
+                else if(l4CnfMsg->result == FT_MODE_SWITCH_RETRY)
+                {
+                    ptrCnfMsg->status = FT_CNF_RETRY;
+                }
+                else
+                {
+                    ptrCnfMsg->status = FT_CNF_FAIL;
+                }
+                FT_SEND_MSG_TO_PC(&l4Message);
+                break;
+            }
+            case MSG_ID_FT_ENTER_NORMAL_MODE_CNF:
+            {
+                ft_enter_normal_mode_cnf_struct *l4CnfMsg;
+                FT_L4_ATCMD_CNF *ptrCnfMsg;
+                l4CnfMsg = (ft_enter_normal_mode_cnf_struct*)ptrMsg->local_para_ptr;
+		        FT_ALLOC_MSG(&l4Message, sizeof(FT_L4_ATCMD_CNF));
+                ptrCnfMsg = (FT_L4_ATCMD_CNF *)l4Message.local_para_ptr;
+                ptrCnfMsg->header.ft_msg_id = FT_L4_ATCMD_CNF_ID;
+                ptrCnfMsg->type = 0;
+                if(l4CnfMsg->result == FT_MODE_SWITCH_SUCCESS)
+                {
+                    ptrCnfMsg->status = FT_CNF_OK;
+                }
+                else if(l4CnfMsg->result == FT_MODE_SWITCH_RETRY)
+                {
+                    ptrCnfMsg->status = FT_CNF_RETRY;
+                }
+                else
+                {
+                    ptrCnfMsg->status = FT_CNF_FAIL;
+                }
+                FT_SEND_MSG_TO_PC(&l4Message);
+                break;
+            }
+            /* FT not in switch mode broadcast list
+			case MSG_ID_L4C_ENTER_FACTORY_MODE_REQ:
+            {
+                l4Message.local_para_ptr = NULL;
+                l4Message.peer_buff_ptr = NULL;
+                FT_SEND_MSG(MOD_FT, MOD_L4C, L4C_META_SAP, MSG_ID_L4C_ENTER_FACTORY_MODE_CNF, &l4Message); 
+                break;
+            }*/
+        }
+    }
+    else
+    {
+        FT_L4_ATCMD_REQ *ptrLocalMsg;
+        ptrLocalMsg = (FT_L4_ATCMD_REQ *)ptrMsg->local_para_ptr;
+        if(FT_L4_ATCMD_REQ_ID == ptrLocalMsg->header.ft_msg_id)
+        {
+            l4Message.local_para_ptr = NULL;
+            l4Message.peer_buff_ptr = NULL;
+            if(ptrLocalMsg->type == 1)
+            {
+                FT_SEND_MSG(MOD_FT, MOD_L4C, L4C_META_SAP,  MSG_ID_FT_ENTER_FACTORY_MODE_REQ, &l4Message);
+            }
+            else if(ptrLocalMsg->type == 0)
+            {
+                FT_SEND_MSG(MOD_FT, MOD_L4C, L4C_META_SAP,  MSG_ID_FT_ENTER_NORMAL_MODE_REQ, &l4Message);
+            }
+        }
+    }
+}
+#endif // #if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT) || defined(DUMMY_PROTOCOL)
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_lterf.c b/mcu/middleware/meta/ft/src/ft_fnc_lterf.c
new file mode 100644
index 0000000..bb54a6a
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_lterf.c
@@ -0,0 +1,194 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_lterf.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   Factory testing function for LTE
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#if defined(__LTE_RAT__)
+/*************************************************************************
+* Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h"
+#include "svc_sap.h"
+#include "tst_msgid.h"
+#include "ft_msgid.h"
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_lterf.h"
+/**
+ * @param metaMessage the input message from META tool for ERF test command processing
+ */
+void FT_Erf_Operation(ilm_struct* ptrMsg)
+{
+    ilm_struct erfMessage;
+    FT_CONSTRUCT_CC_MSG(ptrMsg, &erfMessage);
+    FT_SEND_MSG(MOD_FT, MOD_EL1, DHL_EL1TST_SAP, MSG_ID_DHL_TO_EL1TST, &erfMessage);   
+}
+/**
+ * @param metaMessage the input message from META tool for ERF test command processing
+ */
+void FT_PhyTool_Operation(ilm_struct* ptrMsg)
+{
+    ilm_struct erfMessage;
+    FT_CONSTRUCT_CC_MSG(ptrMsg, &erfMessage);
+    FT_SEND_MSG(MOD_FT, MOD_EL1, DHL_ETSTM_SAP, MSG_ID_DHL_TO_ETSTM, &erfMessage);   
+}
+/**
+ * Confirm message handler for MOD_ETSTM
+ */
+void FT_Erf_ConfirmHandler(ilm_struct* erfMessage)
+{
+    FT_ERF_TEST_CNF *ptrMsg;
+    ptrMsg = (FT_ERF_TEST_CNF *)erfMessage->local_para_ptr;
+    if(ptrMsg->type == ERF_TEST_CMD_CHECK_IF_FUNC_EXIST)
+    {
+        FT_UTILITY_COMMAND_CNF  cnf;
+        kal_mem_set(&cnf, '\0', sizeof(cnf));
+        cnf.status = (ptrMsg->param.CheckIfFuncExist.result==1)?FT_CNF_OK:FT_CNF_FAIL;
+        cnf.result.CheckIfFuncExist.query_ft_msg_id = ptrMsg->header.ft_msg_id;
+        cnf.result.CheckIfFuncExist.query_op_code = ptrMsg->param.CheckIfFuncExist.query_op_code;
+        FT_UTIL_SendCnf(&cnf, NULL);
+        return;
+    }
+    FT_SEND_MSG_TO_PC(erfMessage);
+}
+void FT_ErfCheckFunctionSupported(kal_uint32 query_op_code)
+{
+    ilm_struct ilm_ptr;
+    FT_ERF_TEST_REQ *ptrMsg;	
+    FT_ALLOC_OTHER_CC_MSG( &ilm_ptr, sizeof(FT_ERF_TEST_REQ) );
+    // local parameter    
+    ptrMsg = (FT_ERF_TEST_REQ *)ilm_ptr.local_para_ptr;
+    ptrMsg->header.ft_msg_id = FT_ERF_TEST_REQ_ID;  
+    ptrMsg->type = ERF_TEST_CMD_CHECK_IF_FUNC_EXIST;
+    ptrMsg->param.CheckIfFuncExist.cmd_tpye = (ERfTestCmdType)query_op_code;
+    FT_SEND_MSG(MOD_FT, MOD_EL1, DHL_EL1TST_SAP, MSG_ID_DHL_TO_EL1TST, &ilm_ptr);
+}
+#endif // #if defined(__LTE_RAT__)
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_misc.c b/mcu/middleware/meta/ft/src/ft_fnc_misc.c
new file mode 100644
index 0000000..f948081
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_misc.c
@@ -0,0 +1,1058 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_misc.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  Misc Function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+/*************************************************************************
+ * Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h" //MSBB change #include "stack_common.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_msgs.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_config.h"
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "kal_trace.h"
+#include "string.h"
+#include "sst_interface.h"
+#include "svc_sap.h"
+#include "md_sap.h"
+#include "mw_sap.h"
+#include "ft_msgid.h"
+#include "nvram_msgid.h"
+#include "sim_public_msgid.h"
+/**************************************************************************
+ * HAL header
+ *************************************************************************/
+#include "dcl.h"
+/**************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_misc.h"
+#include "ft_mem.h"
+#include "ft_fnc_nvram.h"
+#include "ft_trace_def.h"
+/**************************************************************************
+ * NVRAM header
+ *************************************************************************/
+#include "nvram_enums.h"
+#include "nvram_data_items.h"
+#include "ft_nvram_def.h"
+#include "l4_nvram_def.h"
+#include "mml1_nvram_def.h" 
+#include "nvram_struct.h"
+#include "nvram_interface.h"
+#include "nvram_editor_data_item.h"
+#include "ft_nvram_editor.h"
+/* NVRAM private header for data item iterator */
+//#include "nvram_util.h" -> "nvram_interface.h"
+/**************************************************************************
+ * SIM header
+ *************************************************************************/
+#include "ps2sim_struct.h"
+/**************************************************************************
+ * Custom header
+ *************************************************************************/
+#include "meta_customize.h"
+kal_uint8  ft_gl_path_check_flag = KAL_TRUE;
+kal_uint8 *p_ft_misc_buf = NULL;  // a pointer point to : nvram_cal_data_check_struct
+kal_bool   b_ft_misc_buf_from_med = KAL_TRUE; // KAL_TRUE: from MED task, KAL_FALSE: from control buffer
+kal_uint16 ft_gl_misc_token = 0;
+kal_uint8 ft_gl_sim_cmd_type = 0;  // store sim cmd type
+
+//=============== local buffer process =========================
+kal_uint8  FT_MISC_SendCnf(FT_MISC_CNF *ft_misc_ret, peer_buff_struct *peer_buff) {
+
+    ilm_struct       ilm_ptr;
+    FT_MISC_CNF *ptrMsg;
+
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_MISC_CNF));
+
+    /* if ptrMsg != NULL*/
+    ptrMsg = (FT_MISC_CNF *)ilm_ptr.local_para_ptr;
+
+    // assign primitive id
+    ptrMsg->header.ft_msg_id = FT_MISC_CMD_CNF_ID;
+
+    // assign return structure
+    ptrMsg->type = ft_misc_ret->type;
+
+    // copy the result directly without checking its cmd type
+    kal_mem_cpy(&(ptrMsg->result), &(ft_misc_ret->result), sizeof(FT_MISC_CNF_U));
+
+    ptrMsg->status = ft_misc_ret->status;
+
+    // assign peer buffer
+    if( NULL != peer_buff ) {
+        ilm_ptr.peer_buff_ptr = peer_buff;
+    }
+
+    /* FT_SEND_MSG(src_mod, dest_mod, sap_id, msg_id, ilm_ptr) */
+    FT_SEND_MSG_TO_PC_BY_TOKEN(&ilm_ptr, ft_gl_misc_token);
+    return 0;
+}
+#define FT_MISC_MAX_PEER_SIZE       2048
+#define FT_MISC_MAX_FRAME_SIZE      FT_MISC_MAX_PEER_SIZE/64*56
+#define FT_OTHER_INFO_FLAG 0
+#define FT_IMEI_INFO_FLAG  1
+#define FT_SML_INFO_FLAG 2
+kal_uint8 ft_misc_op_collect_cal_info(FT_MISC_CNF *misc_cnf)
+{
+    kal_char *pcStrPrefix;
+    kal_char *pcStrVerNo;
+    kal_uint8  flag;
+    peer_buff_struct   *peer_buff_ret = NULL;
+    kal_char  *pdu_ptr = NULL;
+    kal_uint16  pdu_length = 0;
+    kal_uint16  cur_pos = 0;
+    nvram_ltable_entry_struct *entry = NULL;
+    // find the first enrty when the input pointer is NULL pointer
+    while(nvram_util_next_data_item(&entry) == KAL_TRUE)
+    {
+        if(NVRAM_IO_ERRNO_OK != nvram_check_backup(entry->LID, &pcStrPrefix, &pcStrVerNo))
+        {
+            continue;
+        }
+        flag = FT_OTHER_INFO_FLAG;
+        if(entry->LID == NVRAM_EF_IMEI_IMEISV_LID)
+        {
+            flag = FT_IMEI_INFO_FLAG;
+        }
+        else if(entry->LID==NVRAM_EF_SML_LID)
+        {
+            flag = FT_SML_INFO_FLAG;
+        }
+allocate_peer_buf:
+        if(NULL == peer_buff_ret)  // allocate peer buffer
+        {
+            peer_buff_ret=construct_peer_buff(FT_MISC_MAX_FRAME_SIZE, 0, 0, TD_CTRL);
+            if(NULL == peer_buff_ret)
+            {
+                return 1;
+            }
+            /* Set the pdu_len to 0 to keep track of the current position and updated at each iteration */
+            peer_buff_ret->pdu_len = 0 ;
+        }
+        if( FT_MISC_MAX_FRAME_SIZE < (peer_buff_ret->pdu_len+3+strlen(pcStrPrefix)+strlen(pcStrVerNo)+1) )
+        {
+            misc_cnf->result.m_u1LastFrame = 0; // set last_frame = 0
+            misc_cnf->status = FT_CNF_OK;
+            // send confirm
+            FT_MISC_SendCnf(misc_cnf, peer_buff_ret);
+            // sleep to wait for tst flush out data
+            kal_sleep_task(50);
+            // allocate peer buffer again
+            peer_buff_ret = NULL;
+            cur_pos = 0;
+            goto allocate_peer_buf;
+        }
+        pdu_ptr = get_peer_buff_pdu( peer_buff_ret, &pdu_length );
+        // copy to peer buffer
+        cur_pos = 0;
+        // copy lid_value (Assertion check to guarantee that the protocol stays unchange)
+        {
+            ASSERT(sizeof(kal_uint16) == sizeof(nvram_lid_enum));
+            kal_mem_cpy(pdu_ptr+pdu_length, &(entry->LID), sizeof(kal_uint16));
+            cur_pos += sizeof(kal_uint16);
+        }
+        // copy file flag
+        {
+            kal_mem_cpy(pdu_ptr+pdu_length+cur_pos, &flag, sizeof(kal_uint8));
+            cur_pos += sizeof(kal_uint8);
+        }
+        // copy file prefix (Assertion check to guarantee that the protocol stays unchange)
+        {
+            ASSERT(strlen(pcStrPrefix) == 4);
+            kal_mem_cpy(pdu_ptr+pdu_length+cur_pos, pcStrPrefix, strlen(pcStrPrefix));
+            cur_pos +=(strlen(pcStrPrefix));
+        }
+        // copy lid Ver No (Assertion check to guarantee that the protocol stays unchange)
+        {
+            ASSERT(strlen(pcStrVerNo) == 3);
+            kal_mem_cpy(pdu_ptr+pdu_length+cur_pos, pcStrVerNo, strlen(pcStrVerNo)+1);
+            cur_pos += (strlen(pcStrVerNo)+1);
+        }
+        // update pdu_len
+        peer_buff_ret->pdu_len += cur_pos;
+    }
+    misc_cnf->result.m_u1LastFrame = 1;
+    misc_cnf->status = FT_CNF_OK;
+    FT_MISC_SendCnf(misc_cnf, peer_buff_ret);
+    return 0;
+}
+/**
+ * Get Number of ADC channels
+ * \return the number of ADC channels
+ */
+kal_uint8 FT_GetAdcMaxChannel(void)
+{
+    // HAL modification
+    DCL_HANDLE adc_handle;
+    ADC_CTRL_GET_MAX_PHYSICAL_CH_T  prGetMaxPhyCh;
+    kal_uint8 adc_max_channel;
+    adc_handle = DclSADC_Open(DCL_ADC, FLAGS_NONE);
+    if(DclHADC_Control(adc_handle, ADC_CMD_GET_MAX_PHYSICAL_CH, (DCL_CTRL_DATA_T *)&prGetMaxPhyCh) != STATUS_OK)
+    {
+        // error handling (prevent from access out-of bound)
+        adc_max_channel = 1;
+		return adc_max_channel;
+    }
+    adc_max_channel = prGetMaxPhyCh.u4Adc_max_ch;
+    if(DclSADC_Close(adc_handle) != STATUS_OK)
+    {
+        // error handling (prevent from access out-of bound)
+        adc_max_channel = 1;
+    }
+    return adc_max_channel;
+}
+
+void FT_MISC_Operation(ilm_struct *ptrMsg)
+{
+    kal_wchar         wpath[128];
+    FT_MISC_REQ       *p_req = (FT_MISC_REQ *)ptrMsg->local_para_ptr;
+    FT_MISC_CNF       misc_cnf;
+    memset(&misc_cnf, 0x0, sizeof(misc_cnf));
+    peer_buff_struct  *peer_buff_ret = NULL;  // default value
+    kal_char    *pdu_ptr = NULL;
+    kal_uint16    pdu_length = 0;
+    misc_cnf.type = p_req->type;
+    misc_cnf.status = FT_CNF_FAIL;  // default value
+    ft_gl_misc_token =  p_req->header.token;
+    MD_TRC_FT_MISC_OP_FUNC(p_req->type);
+
+    switch(p_req->type)
+    {
+        case FT_MISC_OP_GET_IMEI_LOC:
+        {
+            misc_cnf.result.m_u1IMEILoc = nvram_get_imei_type();
+            misc_cnf.status = FT_CNF_OK;
+            break;
+        }
+        case FT_MISC_OP_GET_IMEI_VALUE:
+        {
+            // check the record index (because tools before 0912 causes assertion)
+            kal_uint16 rec_num = nvram_get_imei_record_num();
+            if(p_req->cmd.m_u1RecordIndex < 1 || p_req->cmd.m_u1RecordIndex > rec_num)
+            {
+                // set the record index to 1 (the behavior will be confrom to that of target load before 0909)
+                p_req->cmd.m_u1RecordIndex = 1;
+            }
+            if(KAL_TRUE == nvram_get_imei_value(NVRAM_EF_IMEI_IMEISV_SIZE,
+                        misc_cnf.result.m_rIMEIData.buf, p_req->cmd.m_u1RecordIndex))
+            {
+                misc_cnf.result.m_rIMEIData.buf_len = NVRAM_EF_IMEI_IMEISV_SIZE;
+                misc_cnf.status = FT_CNF_OK;
+            }
+            else
+                misc_cnf.status = FT_CNF_FAIL;
+            break;
+
+        }
+#if defined(__MTK_INTERNAL__)
+        case FT_MISC_OP_SET_IMEI_VALUE:
+        {
+            FT_MISC_CNF           misc_cnf;
+            misc_cnf.type = FT_MISC_OP_SET_IMEI_VALUE;
+            misc_cnf.result.m_u2RecordIndex = p_req->cmd.m_rIMEIData.record_index;
+            misc_cnf.status = FT_CNF_FAIL;
+
+            kal_uint8 *buffer = (kal_uint8*)get_ctrl_buffer(NVRAM_EF_IMEI_IMEISV_SIZE);
+            memcpy(buffer, p_req->cmd.m_rIMEIData.imei, 8);
+            buffer[8] = p_req->cmd.m_rIMEIData.svn;
+            if( NVRAM_ERRNO_SUCCESS == nvram_external_secure_write_data (NVRAM_EF_IMEI_IMEISV_LID, p_req->cmd.m_rIMEIData.record_index, buffer, NVRAM_EF_IMEI_IMEISV_SIZE, NULL) )
+            {
+                misc_cnf.status = FT_CNF_OK;
+            }
+            free_ctrl_buffer(buffer);
+            FT_MISC_SendCnf(&misc_cnf, NULL);
+            return;
+        }
+#endif  //#if defined(__MTK_INTERNAL__)
+        case FT_MISC_OP_GET_IMEI_REC_NUM:
+        {
+            misc_cnf.result.m_u2IMEIRecords = nvram_get_imei_record_num();
+            misc_cnf.status = FT_CNF_OK;
+            break;
+        }
+        case FT_MISC_OP_VERIFY_TEMP_SML_FILE:
+        {
+            //kal_char  *pdu_ptr;
+            //kal_uint16    pdu_length;
+            kal_wchar *w_filepath;
+            // get the file path from peer_buffer
+            if(ptrMsg->peer_buff_ptr != NULL)
+            {
+                pdu_ptr = get_peer_buff_pdu( ptrMsg->peer_buff_ptr, &pdu_length );
+
+                // cast to kal_wchar
+                w_filepath = (kal_wchar *)pdu_ptr;
+
+                misc_cnf.status = FT_CNF_OK;
+
+                // ask nvram task to check the SML file
+                if(NVRAM_IO_ERRNO_OK == nvram_validate_file(NVRAM_EF_SML_LID, w_filepath))
+                    misc_cnf.result.m_u1VerifyResult = FT_SML_VALID;
+                else
+                    misc_cnf.result.m_u1VerifyResult = FT_SML_INVALID;
+
+            }
+            else  // peer buffer is null
+            {
+                misc_cnf.status = FT_CNF_FAIL;
+                misc_cnf.result.m_u1VerifyResult = FT_SML_NO_FILENAME;
+            }
+
+            break;
+        }
+        case FT_MISC_OP_GET_CAL_INFO:
+        {
+            ft_misc_op_collect_cal_info(&misc_cnf);
+            return;
+        }
+        case FT_MISC_OP_QUERY_NVRAM_FOLDER:
+        {
+            kal_uint16  length;
+            kal_char* buf;
+            kal_uint8 folder_total_amount = nvram_get_folder_total_amount();
+            kal_int16 total_length = 0;
+            kal_int8 i;
+            misc_cnf.status = FT_CNF_OK;
+
+            // allocate peer buffer
+            if(NULL == peer_buff_ret)
+            {//FT_MISC_MAX_FRAME_SIZE
+                peer_buff_ret = construct_peer_buff(FT_MISC_MAX_FRAME_SIZE, 0, 0, TD_CTRL);
+                if(NULL == peer_buff_ret)  return;
+
+                peer_buff_ret->pdu_len = 0 ;
+            }
+            pdu_ptr = get_peer_buff_pdu( peer_buff_ret, &pdu_length );
+            for(i = 0;i<folder_total_amount;i++)
+            {
+                buf = nvram_get_work_path(i);
+                kal_wsprintf(wpath, "%s", buf);
+                if(nvram_check_hidden_file(wpath, KAL_TRUE))
+                {
+                    continue;
+                }
+                length = (strlen(buf)+1);
+                kal_mem_cpy(pdu_ptr+pdu_length+total_length, (buf), length );
+                *(pdu_ptr+pdu_length+total_length+length-1) = '?';
+                total_length += length;
+            }
+            // update pdu_len
+            peer_buff_ret->pdu_len += (total_length);
+
+
+            break;
+        }
+        case FT_MISC_OP_VERIFY_NVRAM_ATTR_SETTING_COMPLETE:
+        {
+            kal_uint16 stop_index = custom_meta_check_must_backup_lid_array(p_req->cmd.m_bcheckImeiFlag);
+            if(stop_index == custom_meta_get_check_lid_num()) // check successfully!
+            {
+                misc_cnf.status = FT_CNF_OK;
+                misc_cnf.result.m_rNvramVerifyResult.m_stop_enum_value = custom_meta_get_enum_by_index(stop_index-1); // pass the imei_enum
+                misc_cnf.result.m_rNvramVerifyResult.m_total_lid_num = custom_meta_get_check_lid_num();
+                misc_cnf.result.m_rNvramVerifyResult.m_stop_index = stop_index;
+            }
+            else
+            {
+                misc_cnf.status = FT_CNF_FAIL;
+                misc_cnf.result.m_rNvramVerifyResult.m_stop_enum_value = custom_meta_get_enum_by_index(stop_index);
+                misc_cnf.result.m_rNvramVerifyResult.m_total_lid_num = custom_meta_get_check_lid_num();
+                misc_cnf.result.m_rNvramVerifyResult.m_stop_index = stop_index;
+            }
+            break;
+        }
+        case FT_MISC_OP_ENABLE_PATH_LIMITION:
+        case FT_MISC_OP_DISABLE_PATH_LIMITION:
+        {
+            ft_gl_path_check_flag = (p_req->type == FT_MISC_OP_ENABLE_PATH_LIMITION)?KAL_TRUE:KAL_FALSE;
+            misc_cnf.status = FT_CNF_OK;
+            break;
+        }
+        case FT_MISC_OP_GET_NVRAM_FOLDER_AMOUNT:
+        {
+            kal_uint8 i;
+            misc_cnf.result.m_u1NVRAMFolderAmount = nvram_get_folder_total_amount();
+            for(i = 0;i<nvram_get_folder_total_amount();i++)
+            {
+                kal_wsprintf(wpath, "%s", nvram_get_work_path(i));
+                if(nvram_check_hidden_file(wpath, KAL_TRUE))
+                {
+                    misc_cnf.result.m_u1NVRAMFolderAmount--;
+                }
+            }
+            misc_cnf.status = FT_CNF_OK;
+
+        }
+        break;
+#ifndef SIM_NOT_PRESENT
+        case FT_MISC_OP_CHECK_SIM1_INSERTED:
+        {
+            // Send reset request to MOD_SIM
+            ilm_struct  ilm_ptr;
+            sim_reset_req_struct* ptr_loc_para;
+            FT_ALLOC_OTHER_MSG(&ilm_ptr, sizeof(sim_reset_req_struct));
+            ptr_loc_para = (sim_reset_req_struct*) (ilm_ptr.local_para_ptr);
+            ptr_loc_para->src_id = 0xff;
+            // set sim cmd type to global variable
+            ft_gl_sim_cmd_type = FT_MISC_OP_CHECK_SIM1_INSERTED;
+            FT_SEND_MSG(MOD_FT, MOD_SIM, PS_SIM_SAP, MSG_ID_SIM_RESET_REQ, &ilm_ptr);
+            // wait for SIM task CNF message
+            return;
+        }
+#ifdef __GEMINI__
+        case FT_MISC_OP_CHECK_SIM2_INSERTED:
+        {
+            // Send reset request to MOD_SIM_2
+            ilm_struct  ilm_ptr;
+            sim_reset_req_struct* ptr_loc_para;
+            FT_ALLOC_OTHER_MSG(&ilm_ptr, sizeof(sim_reset_req_struct));
+            ptr_loc_para = (sim_reset_req_struct*) (ilm_ptr.local_para_ptr);
+            ptr_loc_para->src_id = 0xff;
+            // set sim cmd type to global variable
+            ft_gl_sim_cmd_type =FT_MISC_OP_CHECK_SIM2_INSERTED;
+            FT_SEND_MSG(MOD_FT, MOD_SIM_2, PS_SIM_SAP, MSG_ID_SIM_RESET_REQ, &ilm_ptr);
+            // wait for SIM task CNF message
+            return;
+        }
+#endif // __GEMINI__
+#ifdef GEMINI_PLUS
+        case FT_MISC_OP_CHECK_GEMINI_PLUS_SIM_INSERTED:
+        {
+            // Send reset request to MOD_SIM_N
+            ilm_struct  ilm_ptr;
+            sim_reset_req_struct* ptr_loc_para;
+            // if index out of range, break and then send error status CNF
+            if(p_req->cmd.m_u1SimIndex >= GEMINI_PLUS)
+            {
+                break;
+            }
+            FT_ALLOC_OTHER_MSG(&ilm_ptr, sizeof(sim_reset_req_struct));
+            ptr_loc_para = (sim_reset_req_struct*) (ilm_ptr.local_para_ptr);
+            ptr_loc_para->src_id = 0xff;
+            // set sim cmd type to global variable
+            ft_gl_sim_cmd_type = FT_MISC_OP_CHECK_GEMINI_PLUS_SIM_INSERTED;
+            FT_SEND_MSG(MOD_FT, (module_type)(MOD_SIM + p_req->cmd.m_u1SimIndex), PS_SIM_SAP, MSG_ID_SIM_RESET_REQ, &ilm_ptr);
+            // wait for SIM task CNF message
+            return;
+        }
+#endif // GEMINI_PLUS
+#endif // SIM_NOT_PRESENT
+        case FT_MISC_OP_SET_MUIC_CHARGER_MODE:
+        {
+#ifdef __DRV_EXT_CHARGER_DETECTION__
+            MU_BQ25040_Charger_Mode(p_req->cmd.m_u1ChargerMode);
+            misc_cnf.status = FT_CNF_OK;
+#else
+            misc_cnf.status = FT_CNF_FAIL;
+
+#endif
+            break;
+        }
+        case FT_MISC_OP_GET_ADC_FROM_EFUSE:
+        {
+            kal_bool b_ret_code;
+            kal_uint8 i;
+            kal_uint8 adc_max_channel;
+            DCL_HANDLE adc_handle;
+            ADC_CTRL_READ_CALIBRATION_DATA_T prReadCalibrationData;
+            adc_handle = DclSADC_Open(DCL_ADC, FLAGS_NONE);
+            adc_max_channel = FT_GetAdcMaxChannel();
+            b_ret_code = (STATUS_OK == DclSADC_Control(adc_handle, ADC_CMD_READ_CALIBRATION_DATA, (DCL_CTRL_DATA_T*)&prReadCalibrationData)) ?
+                KAL_TRUE : KAL_FALSE;
+            misc_cnf.status = FT_CNF_OK;
+            misc_cnf.result.m_rGetAdcFromEfuse.bADCStoredInEfuse = b_ret_code;
+            misc_cnf.result.m_rGetAdcFromEfuse.u2ADCChnNum = b_ret_code ? adc_max_channel : 0;
+
+            // if channel number > 0, construct peer buffer
+            if(misc_cnf.result.m_rGetAdcFromEfuse.u2ADCChnNum > 0) // i.e. FT_GetAdcMaxChannel()
+            {
+                if( NULL != (peer_buff_ret=construct_peer_buff(adc_max_channel*8, 0, 0, TD_CTRL)) )
+                {
+                    pdu_ptr = get_peer_buff_pdu( peer_buff_ret, &pdu_length );
+                    peer_buff_ret->pdu_len = adc_max_channel *8;
+
+                    for(i =0; i< adc_max_channel; i++) // append slope first
+                    {
+                        kal_mem_cpy(pdu_ptr+(i*4), &(prReadCalibrationData.i4ADCSlope[i]), sizeof(kal_int32));
+                    }
+                    for(i =0; i<adc_max_channel; i++) // append offset second
+                    {
+                        kal_mem_cpy(pdu_ptr+((adc_max_channel+i)*4), &(prReadCalibrationData.i4ADCOffset[i]), sizeof(kal_int32));
+                    }
+                }
+            }
+            break;
+        }
+        case FT_MISC_OP_GET_CALFLAG_ENUM:
+        {
+            misc_cnf.result.m_u2CalFlagEnum = custom_ft_get_calflag_enum();
+            misc_cnf.status = FT_CNF_OK;
+        }
+        break;
+        case FT_MISC_OP_GET_ADC_MAX_CHANNEL:
+        {
+            // HAL modification
+            misc_cnf.status = FT_CNF_OK;
+            misc_cnf.result.m_u1ADCMaxChannel = FT_GetAdcMaxChannel();
+            break;
+        }
+        case FT_MISC_OP_GET_TADC_INDEX:
+        {
+            // HAL modification
+            //misc_cnf.result.m_u1TADCChannelIndex = custom_adc_get_channel(rftmp_adc_channel);
+            DCL_HANDLE adc_handle;
+            ADC_CTRL_GET_PHYSICAL_CHANNEL_T adc_ch;
+            misc_cnf.status = FT_CNF_OK;
+            adc_handle = DclSADC_Open(DCL_ADC, FLAGS_NONE);
+            adc_ch.u2AdcName = DCL_RFTMP_ADC_CHANNEL;
+            if(DclSADC_Control( adc_handle, ADC_CMD_GET_CHANNEL, (DCL_CTRL_DATA_T *)& adc_ch) != STATUS_OK)
+            {
+                misc_cnf.status = FT_CNF_FAIL;
+            }
+            misc_cnf.result.m_u1TADCChannelIndex = adc_ch.u1AdcPhyCh;
+            if(DclSADC_Close(adc_handle) != STATUS_OK)
+            {
+                misc_cnf.status = FT_CNF_FAIL;
+            }
+            break;
+        }
+        case FT_MISC_OP_GET_RF_CAL_ENV_ENUM:
+            misc_cnf.result.m_u2Enum = custom_ft_get_rf_cal_env_enum();
+            misc_cnf.status = FT_CNF_OK;
+        break;
+        case FT_MISC_OP_GET_RF_CAL_LOSS_SETTING_ENUM:
+            misc_cnf.result.m_u2Enum = custom_ft_get_rf_loss_setting_enum();
+            misc_cnf.status = FT_CNF_OK;
+        break;
+        case FT_MISC_OP_GET_RF_TEST_POWER_RESULT_ENUM:
+            misc_cnf.result.m_u2Enum = custom_ft_get_rf_test_power_result_enum();
+            misc_cnf.status = FT_CNF_OK;
+        break;
+        case FT_MISC_OP_GET_RID:
+        {
+            if(KAL_TRUE == SST_Get_ChipRID((kal_char*)misc_cnf.result.m_rRIDData.buf, (p_req->cmd.m_RIDLength*8)))
+            {
+                misc_cnf.result.m_rRIDData.buf_len = p_req->cmd.m_RIDLength; // return RID length in bytes
+            }
+            else
+            {
+                misc_cnf.result.m_rRIDData.buf_len = 0; // return length = 0 for error check
+            }
+            misc_cnf.status = FT_CNF_OK;
+            break;
+        }
+        case FT_MISC_OP_GET_BARCODE_VALUE:
+        {
+            if(p_req->cmd.m_u1RecordIndex < 1 || p_req->cmd.m_u1RecordIndex > NVRAM_EF_BARCODE_NUM_TOTAL)
+            {
+                p_req->cmd.m_u1RecordIndex = 1;
+            }
+            if( NULL != (peer_buff_ret=construct_peer_buff(NVRAM_EF_BARCODE_NUM_SIZE, 0, 0, TD_CTRL)))
+            {
+                peer_buff_ret->pdu_len = NVRAM_EF_BARCODE_NUM_SIZE;
+                pdu_ptr = get_peer_buff_pdu( peer_buff_ret, &pdu_length );
+                if(KAL_TRUE == nvram_external_read_data(NVRAM_EF_BARCODE_NUM_LID, p_req->cmd.m_u1RecordIndex, (kal_uint8*)pdu_ptr, NVRAM_EF_BARCODE_NUM_SIZE))
+                {
+                    misc_cnf.status = FT_CNF_OK;
+                }
+            }
+            break;
+        }
+        case FT_MISC_OP_CHECK_SIM_HW_TEST:
+        {
+#if !defined(SIM_NOT_PRESENT)
+            extern int usim_iftest_for_smt(kal_uint32 SIM_index);
+            kal_int32 status;
+            MD_TRC_FT_MISC_OP_CHECK_SIM_HW_TEST_ENTER_DRV();
+            status = usim_iftest_for_smt(p_req->cmd.m_u1SimIndex);
+            MD_TRC_FT_MISC_OP_CHECK_SIM_HW_TEST_LEAVE_DRV(status);
+            kal_mem_cpy(&(misc_cnf.result.m_i4SimHwStatus), &status, sizeof(kal_int32));
+            misc_cnf.status = FT_CNF_OK;
+#else // #if !defined(SIM_NOT_PRESENT)
+            kal_uint32* pStatus = (kal_uint32*) &(misc_cnf.result.m_i4SimHwStatus);
+            *pStatus = 0;
+            misc_cnf.status = FT_CNF_FAIL;
+#endif // #if defined(SIM_NOT_PRESENT)
+            break;
+        }
+        default:
+            return;
+    }
+    // send confirm to PC side
+    FT_MISC_SendCnf(&misc_cnf, peer_buff_ret);
+}
+
+/**
+ * Check if the function supported
+ * \param query_op_code the OP code to be checked if supported
+ * \retval FT_CNF_FAIL not supported
+ * \retval FT_CNF_OK supported
+ */
+kal_uint32 FT_MiscCheckFunctionSupported(kal_uint32 query_op_code)
+{
+    kal_uint32 cnf_code;
+    if(FT_MISC_OP_END> query_op_code)
+    {
+        if(FT_MISC_OP_SET_IMEI_VALUE == query_op_code)
+        {       
+#if defined(__MTK_INTERNAL__)
+            cnf_code = FT_CNF_OK;
+#else
+	        cnf_code = FT_CNF_FAIL;
+#endif  //#if defined(__MTK_INTERNAL__)
+        }
+        else if(FT_MISC_OP_SET_WIFI_MAC_ADDR == query_op_code)
+        {
+            cnf_code = FT_CNF_FAIL;
+        }
+        else if(FT_MISC_OP_SET_MUIC_CHARGER_MODE == query_op_code)
+        {
+#ifdef __DRV_EXT_CHARGER_DETECTION__
+            cnf_code = FT_CNF_OK;
+#else
+            cnf_code = FT_CNF_FAIL;
+
+#endif
+        }
+        else if(
+                (FT_MISC_OP_GET_RF_CAL_ENV_ENUM == query_op_code) ||
+                (FT_MISC_OP_GET_RF_CAL_LOSS_SETTING_ENUM == query_op_code) ||
+                (FT_MISC_OP_GET_RF_TEST_POWER_RESULT_ENUM == query_op_code)
+               )
+        {
+#ifdef __TC01__
+            cnf_code = FT_CNF_OK;
+#else
+            cnf_code = FT_CNF_FAIL;
+#endif
+        }
+        else if(FT_MISC_OP_GET_MMI_CACHE_ENUM_INDEX == query_op_code)
+        {
+            cnf_code = FT_CNF_FAIL;
+        }
+        else if(FT_MISC_OP_CHECK_SIM_HW_TEST == query_op_code)
+        {
+#if !defined(SIM_NOT_PRESENT)
+            cnf_code = FT_CNF_OK;
+#else // #if !defined(SIM_NOT_PRESENT)
+            cnf_code = FT_CNF_FAIL;
+#endif // #if defined(SIM_NOT_PRESENT)
+        }
+        else if (
+                (FT_MISC_OP_CALDATA_INTEGRITY_START_REC == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_STOP_REC == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_ADD_ONE == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_DEL_ONE == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_DEL_ALL == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_CHECK_ONE == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_CHECK_ALL == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_START_REC_EX == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_STOP_REC_EX == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_ADD_ONE_EX == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_DEL_ONE_EX == query_op_code) ||
+                (FT_MISC_OP_CALDATA_INTEGRITY_DEL_ALL_EX == query_op_code)
+                )
+        {
+            cnf_code = FT_CNF_FAIL;
+        }
+        else
+        {
+            cnf_code = FT_CNF_OK;
+        }
+    }
+    else
+    {
+        cnf_code = FT_CNF_FAIL;
+    }
+    return cnf_code;
+}
+
+/**
+ * Handles the Add on record for other SW modules in target
+ * \param ptrMsg the ILM request message from other module
+ */
+void FT_Misc_CalDataInTargetAddOneRequestHandler(ilm_struct *ptrMsg)
+{
+    ilm_struct ilm_ptr;
+    kal_uint8 uRet = 0;
+    ft_cal_data_add_one_cnf_struct* cnf = NULL;
+
+    FT_ALLOC_OTHER_MSG( &ilm_ptr, sizeof(ft_cal_data_add_one_cnf_struct) );
+    // local parameter    
+    cnf = (ft_cal_data_add_one_cnf_struct*)ilm_ptr.local_para_ptr;
+    cnf->status = uRet; 
+    FT_SEND_MSG(MOD_FT, ptrMsg->src_mod_id, ptrMsg->sap_id, MSG_ID_FT_CAL_DATA_ADD_ONE_CNF, &ilm_ptr);
+}
+
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_misc_ex.c b/mcu/middleware/meta/ft/src/ft_fnc_misc_ex.c
new file mode 100644
index 0000000..20d7bb8
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_misc_ex.c
@@ -0,0 +1,615 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_misc_ex.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  Misc Function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+/*************************************************************************
+ * Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h" //MSBB change #include "stack_common.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_msgs.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_config.h"
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "svc_sap.h"
+#include "ft_msgid.h"
+#include "nvram_msgid.h"
+/**************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_misc_ex.h"
+/**************************************************************************
+ * Custom header
+ *************************************************************************/
+#include "meta_customize.h"
+#if defined(__TC01_ERS_SUPPORT__)
+// FIXME: remove the compile option wrapping after GOLF QM
+#include "ers_type.h"
+#include "ers_api.h"
+#endif // #if defined(__TC01_ERS_SUPPORT__)
+
+#if defined(__FS_RAMDISK__)
+// added for ram disk dump
+#include "ramdisk_gprot.h"
+#endif //#if defined(__FS_RAMDISK__) 
+
+// INT_SetCmdToSys
+#include "init.h"
+
+kal_uint16 ft_gl_misc_ex_token = 0;
+kal_uint8  *ft_gl_misc_ex_buf = NULL;
+kal_uint8  FT_MISC_EX_SendCnf(FT_MISC_EX_CNF *ft_misc_ret, peer_buff_struct *peer_buff)
+{
+
+    ilm_struct           ilm_ptr;
+    FT_MISC_EX_CNF  *ptrMsg;
+
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_MISC_EX_CNF));
+
+    /* if ptrMsg != NULL*/
+    ptrMsg = (FT_MISC_EX_CNF *)ilm_ptr.local_para_ptr;
+
+    // assign primitive id
+    ptrMsg->header.ft_msg_id = FT_MISC_EX_CMD_CNF_ID;
+
+    // assign return structure
+    ptrMsg->type = ft_misc_ret->type;
+
+    // copy the result directly without checking its cmd type
+    kal_mem_cpy(&(ptrMsg->result), &(ft_misc_ret->result), sizeof(FT_MISC_EX_CNF_U));
+
+    ptrMsg->status = ft_misc_ret->status;
+
+    // assign peer buffer
+    if( NULL != peer_buff )
+    {
+        ilm_ptr.peer_buff_ptr = peer_buff;
+    }
+
+    FT_SEND_MSG_TO_PC_BY_TOKEN(&ilm_ptr, ft_gl_misc_ex_token);    
+    return 0;
+}
+
+#if defined(__TC01_ERS_SUPPORT__)
+void FT_ReadERS_Data(ilm_struct *ptrMsg)
+{
+    kal_uint16        pdu_length_in;
+    kal_char          *pdu_ptr_in;
+    FT_MISC_EX_CNF      misc_ex_cnf;
+    kal_int32         ers_data_size;
+    kal_uint8         *p_ers_data ;
+    kal_int32         ers_data_idx;
+    kal_uint32        u4CurOffset = 0;
+
+
+
+
+    misc_ex_cnf.type = FT_MISC_EX_OP_GET_ERS_DATA;
+    misc_ex_cnf.status = FT_CNF_FAIL;  // default value
+    ers_data_size = ERS_query_size(); //wise_query_ERS_size();
+
+    if( NULL != ptrMsg->peer_buff_ptr )
+    {
+        pdu_ptr_in = get_peer_buff_pdu( ptrMsg->peer_buff_ptr, &pdu_length_in );
+    }
+    kal_mem_cpy(&ers_data_idx, pdu_ptr_in, 4);
+    p_ers_data = (kal_uint8*)ERS_query_content_by_idx(ers_data_idx);//wise_query_ERS_content((WCHAR *)pdu_ptr_in);
+
+    // organize the buffer, and send it sequentially to PC side
+    if(p_ers_data != NULL)
+    {
+        // allocate the peer buffer to send to PC-side
+        while(u4CurOffset < ers_data_size)
+        {
+
+            peer_buff_struct *peer_buff = NULL;
+            kal_char *pdu_ptr = NULL;
+            kal_uint16   pdu_length = 0;
+            kal_uint16  u2_cur_len = FT_MISC_EX_DATA_FRAME_SIZE; // default: 1800 bytes to send
+
+            misc_ex_cnf.result.m_rErsDataFrm.m_u4TotalSize = ers_data_size;
+            misc_ex_cnf.result.m_rErsDataFrm.m_u4CurOffset = u4CurOffset;
+            if(u4CurOffset+FT_MISC_EX_DATA_FRAME_SIZE >= ers_data_size)
+            {
+                misc_ex_cnf.result.m_rErsDataFrm.m_bLastFrm = KAL_TRUE;
+                u2_cur_len =  ers_data_size - u4CurOffset;
+            }
+            else
+                misc_ex_cnf.result.m_rErsDataFrm.m_bLastFrm = KAL_FALSE;
+
+            // allocate a peer buffer
+            if( NULL != (peer_buff=construct_peer_buff(u2_cur_len,  0, 0, TD_CTRL)) )
+            {
+                pdu_ptr = get_peer_buff_pdu( peer_buff, &pdu_length );
+                kal_mem_cpy(pdu_ptr, p_ers_data+u4CurOffset , u2_cur_len);
+                peer_buff->pdu_len = u2_cur_len;
+            }
+            misc_ex_cnf.status = FT_CNF_OK;
+            FT_MISC_EX_SendCnf(&misc_ex_cnf, peer_buff);
+            kal_sleep_task(50);
+
+            peer_buff = NULL;// the mem will be released by FT task when copy to TST buffer
+            u4CurOffset += u2_cur_len;
+
+
+        }
+
+    }
+    else
+    {
+        misc_ex_cnf.status = 0xFF;
+        FT_MISC_EX_SendCnf(&misc_ex_cnf, NULL);
+    }
+
+}
+#endif // #if defined(__TC01_ERS_SUPPORT__)
+
+void FT_MiscEx_NvramConfirmHandler(ilm_struct* ptrMsgCnf)
+{
+    FT_MISC_EX_CNF misc_ex_cnf;
+    memset(&misc_ex_cnf,0x0,sizeof(misc_ex_cnf));
+    peer_buff_struct *peer_buff_ret = NULL;  // default value
+    misc_ex_cnf.status = FT_CNF_FAIL;  // default value
+    switch (ptrMsgCnf->msg_id)
+    {
+        case MSG_ID_NVRAM_SDS_CNF:
+        case MSG_ID_NVRAM_BIN_REGION_CNF:
+        {
+#if !defined(__MODEM_CCCI_EXIST__) || !defined(__MODEM_CARD__)
+            if(!Custom_META_SdsSupported())
+            {
+                misc_ex_cnf.type = FT_MISC_EX_OP_BACKUP_TO_SDS;
+                misc_ex_cnf.status = FT_CNF_FAIL;
+                misc_ex_cnf.result.m_u4SDSStatus = 0;
+            }
+            else
+#endif
+            {
+#if !defined(__MODEM_CCCI_EXIST__) || !defined(__MODEM_CARD__)
+                nvram_sds_cnf_struct* cnf = (nvram_sds_cnf_struct*)ptrMsgCnf->local_para_ptr;
+#else
+                nvram_bin_region_cnf_struct* cnf = (nvram_bin_region_cnf_struct*)ptrMsgCnf->local_para_ptr;               
+#endif
+                misc_ex_cnf.type = (FT_MISC_EX_CMD_TYPE)cnf->access_id;
+                misc_ex_cnf.status = FT_CNF_OK;
+                misc_ex_cnf.result.m_u4SDSStatus = cnf->result;
+            }
+            break;
+        }
+        default:
+            return;
+    }
+    FT_MISC_EX_SendCnf(&misc_ex_cnf,peer_buff_ret);
+}
+
+#if defined(__FS_RAMDISK__)
+void FT_Read_RamDisk_Data(ilm_struct *ptrMsg)
+{
+    FT_MISC_EX_CNF	  misc_ex_cnf; 
+    FT_MISC_EX_REQ*   p_req = (FT_MISC_EX_REQ *)ptrMsg->local_para_ptr;
+    kal_uint32        u4CurOffset = p_req->cmd.m_u4RamDiskReqOffset;
+    kal_uint32        u4TotalSize = ramdisk_get_raw_length();
+    // allocate the peer buffer to send to PC-side
+    peer_buff_struct *peer_buff = NULL;
+    kal_char	*pdu_ptr = NULL;
+    kal_uint16	pdu_length = 0;
+    kal_uint16  u2_cur_len = FT_MISC_EX_DATA_FRAME_SIZE; // default: 1800 bytes to send
+
+    misc_ex_cnf.type = FT_MISC_EX_OP_RAMDISK_READ;
+    misc_ex_cnf.status = FT_CNF_FAIL;  // default value
+
+    misc_ex_cnf.result.m_rRamDiskFrm.m_u4TotalSize = u4TotalSize;
+    misc_ex_cnf.result.m_rRamDiskFrm.m_u4CurOffset = u4CurOffset;
+    if(u4CurOffset+FT_MISC_EX_DATA_FRAME_SIZE >= u4TotalSize)
+    {
+        misc_ex_cnf.result.m_rErsDataFrm.m_bLastFrm = KAL_TRUE;
+        u2_cur_len = u4TotalSize - u4CurOffset;
+    }
+    else
+        misc_ex_cnf.result.m_rErsDataFrm.m_bLastFrm = KAL_FALSE;
+
+    // allocate a peer buffer
+    if( NULL != (peer_buff=construct_peer_buff(u2_cur_len, 0, 0, TD_CTRL)) ) 
+    {
+        pdu_ptr = get_peer_buff_pdu( peer_buff, &pdu_length );
+        peer_buff->pdu_len = u2_cur_len;
+        // read from ram disk
+        if(ramdisk_get_raw_data(pdu_ptr, u4CurOffset, u2_cur_len) > 0 || u2_cur_len == 0)
+        {
+            misc_ex_cnf.status = FT_CNF_OK;
+        }
+        FT_MISC_EX_SendCnf(&misc_ex_cnf, peer_buff); 
+        peer_buff = NULL;// the mem will be released by FT task when copy to TST buffer
+    }
+    else
+    {
+        // return fail;
+        FT_MISC_EX_SendCnf(&misc_ex_cnf, NULL); 
+    }
+}
+#endif //#if defined(__FS_RAMDISK__)
+void FT_MISC_EX_Operation(ilm_struct *ptrMsg)
+{
+#if defined(__TC01_ERS_SUPPORT__)
+    kal_char*             pdu_ptr;
+    kal_uint16            pdu_length;
+#endif // #if defined(__TC01_ERS_SUPPORT__)
+    ilm_struct            ptr_ilm;
+    FT_MISC_EX_CNF        misc_ex_cnf;
+    memset(&misc_ex_cnf,0x0,sizeof(misc_ex_cnf));
+    FT_MISC_EX_REQ*       p_req = (FT_MISC_EX_REQ *)ptrMsg->local_para_ptr;
+    peer_buff_struct*     peer_buff_ret = NULL;  // default value
+
+    misc_ex_cnf.type     = p_req->type;
+    misc_ex_cnf.status   = FT_CNF_FAIL;
+    ft_gl_misc_ex_token  = p_req->header.token;
+    switch(p_req->type)
+    {
+        case FT_MISC_EX_OP_GET_ERS_COUNT:
+        {
+#if defined(__TC01_ERS_SUPPORT__)
+            misc_ex_cnf.result.m_i4ErsDataCount = ERS_query_count(); //wise_query_ERS_count();
+#else // #if defined(__TC01_ERS_SUPPORT__)
+            misc_ex_cnf.result.m_i4ErsDataCount = 0;
+#endif // #if !defined(__TC01_ERS_SUPPORT__)
+            misc_ex_cnf.status = FT_CNF_OK;
+            break;
+        }
+        case FT_MISC_EX_OP_GET_ERS_DATA_INFO_BY_INDEX:
+        {
+#if defined(__TC01_ERS_SUPPORT__)
+            ers_info_struct ers_info;
+            ERS_query_info(p_req->cmd.m_i4ErsDataIndex, &ers_info);
+            misc_ex_cnf.result.m_rErsDataTime.sec = ers_info.ers_ctime.sec;
+            misc_ex_cnf.result.m_rErsDataTime.min = ers_info.ers_ctime.min;
+            misc_ex_cnf.result.m_rErsDataTime.hour = ers_info.ers_ctime.hour;
+            misc_ex_cnf.result.m_rErsDataTime.day = ers_info.ers_ctime.day;
+            misc_ex_cnf.result.m_rErsDataTime.mon = ers_info.ers_ctime.mon;
+            misc_ex_cnf.result.m_rErsDataTime.wday = ers_info.ers_ctime.wday;
+            misc_ex_cnf.result.m_rErsDataTime.year = ers_info.ers_ctime.year;
+
+            if( NULL != (peer_buff_ret=construct_peer_buff((2+1)*2, 0, 0, TD_CTRL)) ) // defined in mcu\external_mmi\wise\bal\sys\include\ws_dbg_type.h
+            {
+                pdu_ptr = get_peer_buff_pdu( peer_buff_ret, &pdu_length );
+                // copy filename
+                //kal_mem_cpy(pdu_ptr, (void *)ers_info.ers_filename, (kal_wstrlen(ers_info.ers_filename)+1)*2);
+                kal_mem_cpy(pdu_ptr, (void*)&(p_req->cmd.m_i4ErsDataIndex), sizeof(kal_int32));
+                kal_mem_set(pdu_ptr+4, 0x0, 2);
+                peer_buff_ret->pdu_len = 6; //(kal_wstrlen(ers_info.ers_filename)+1)*2;
+            }
+            misc_ex_cnf.status = FT_CNF_OK;
+#else // #if defined(__TC01_ERS_SUPPORT__)
+            misc_ex_cnf.status = FT_CNF_FAIL;
+#endif // #if !defined(__TC01_ERS_SUPPORT__)
+            break;
+        }
+        case FT_MISC_EX_OP_GET_ERS_SIZE:
+        {
+#if defined(__TC01_ERS_SUPPORT__)
+            misc_ex_cnf.result.m_u4ErsDataSize = ERS_query_size(); //wise_query_ERS_size();
+#else // #if defined(__TC01_ERS_SUPPORT__)
+            misc_ex_cnf.result.m_u4ErsDataSize = 0;
+#endif // #if !defined(__TC01_ERS_SUPPORT__)
+            misc_ex_cnf.status = FT_CNF_OK;
+            break;
+        }
+        case  FT_MISC_EX_OP_GET_ERS_DATA: // send message to NVRAM task to read ERS data
+        {
+#if defined(__TC01_ERS_SUPPORT__)
+            FT_ReadERS_Data(ptrMsg);
+            return;
+#else // #if defined(__TC01_ERS_SUPPORT__)
+            misc_ex_cnf.status = FT_CNF_FAIL;
+#endif // #if !defined(__TC01_ERS_SUPPORT__)
+            break;
+        }
+
+        case FT_MISC_EX_OP_BACKUP_TO_SDS:
+        {
+#if !defined(__MODEM_CCCI_EXIST__) || !defined(__MODEM_CARD__)
+            if(!Custom_META_SdsSupported())
+            {
+                misc_ex_cnf.status = FT_CNF_FAIL;
+                break;
+            }
+            else
+#endif
+            {
+                nvram_sds_req_struct* ptrMsg;
+                FT_ALLOC_OTHER_MSG(&ptr_ilm,sizeof(nvram_sds_req_struct));
+                ptrMsg = (nvram_sds_req_struct *)ptr_ilm.local_para_ptr;
+                ptrMsg->access_id = (kal_uint8)FT_MISC_EX_OP_BACKUP_TO_SDS;
+                // the access mode is defined in nvram_enums.h (nvram_sds_access_enum)
+                ptrMsg->access_mode = (nvram_sds_access_enum)p_req->cmd.mode;
+#if !defined(__MODEM_CCCI_EXIST__) || !defined(__MODEM_CARD__)
+                FT_SEND_MSG(MOD_FT, MOD_NVRAM, PS_NVRAM_SAP, MSG_ID_NVRAM_SDS_REQ, &ptr_ilm);
+#else
+                FT_SEND_MSG(MOD_FT, MOD_NVRAM, PS_NVRAM_SAP, MSG_ID_NVRAM_BIN_REGION_REQ, &ptr_ilm);
+#endif
+                return;
+            }
+        }
+        /* ram disk dump */
+#if defined(__FS_RAMDISK__)        
+        case FT_MISC_EX_OP_RAMDISK_CHECK_EXIST:   /**< \brief check ram disk is existing or not */
+        {
+            if(ramdisk_is_existed())
+            {   
+                misc_ex_cnf.result.m_cRamDiskExist = 1;
+            }
+            else
+            {
+                misc_ex_cnf.result.m_cRamDiskExist = 0;
+            }
+            misc_ex_cnf.status = FT_CNF_OK;
+            break;
+        }
+        case FT_MISC_EX_OP_RAMDISK_GET_SIZE:      /**< \brief get ram disk size */
+        {
+            misc_ex_cnf.result.m_u4RamDiskSize = ramdisk_get_raw_length();
+            if(misc_ex_cnf.result.m_u4RamDiskSize != 0)
+            {   
+                misc_ex_cnf.status = FT_CNF_OK;
+            }
+            else
+            {
+                misc_ex_cnf.status = FT_CNF_FAIL;
+            }              
+            break;
+        }
+        case FT_MISC_EX_OP_RAMDISK_READ:          /**< \brief read from ram disk */
+        {
+            FT_Read_RamDisk_Data(ptrMsg);
+            return;
+        }
+#endif //#if defined(__FS_RAMDISK__)        
+        case FT_MISC_EX_OP_SET_COMMAND_TO_SYSTEM: /**< \brief set/clr download flag */   
+        {
+            misc_ex_cnf.status = FT_CNF_OK;
+            if(p_req->cmd.m_u4SetCmd2System == 0)  // SET_DL_FLAG = 0   set BROM download flag
+            {
+                INT_SetCmdToSys(SYS_CMD_SET_BROM_DL);
+            }
+            else if(p_req->cmd.m_u4SetCmd2System == 1)  // CLR_DL_FLAG = 1   clear download flag
+            {
+                INT_SetCmdToSys(SYS_CMD_CLR_DL_FLAG);
+            }
+            else if(p_req->cmd.m_u4SetCmd2System == 2)  //SET_DL_FLAG_BL = 2  set Bootloader download flag
+            {
+                INT_SetCmdToSys(SYS_CMD_SET_BROM_DL);
+            }
+            else
+            {
+                misc_ex_cnf.status = FT_CNF_FAIL;
+            }
+            break;
+        }
+        default:
+            return;
+    }
+    FT_MISC_EX_SendCnf(&misc_ex_cnf, peer_buff_ret);
+}
+kal_uint32 FT_MiscExCheckFunctionSupported(kal_uint32 query_op_code)
+{
+    kal_uint32 cnf_code;
+    if(FT_MISC_EX_OP_END> query_op_code)
+    {
+        if( query_op_code == FT_MISC_EX_OP_GET_ERS_SIZE ||
+                query_op_code == FT_MISC_EX_OP_GET_ERS_DATA
+          )
+        {
+#ifdef WISDOM_MMI
+            cnf_code = FT_CNF_OK;
+#else
+            cnf_code = FT_CNF_FAIL;
+#endif
+
+        }
+        else if(query_op_code == FT_MISC_EX_OP_COPY_NVRAM_TO_BP_AREA ||
+                query_op_code == FT_MISC_EX_OP_VERIFY_BP_AREA
+               )
+        {
+            cnf_code = FT_CNF_FAIL;
+
+        }
+        else if(query_op_code == FT_MISC_EX_OP_BACKUP_TO_SDS)
+        {
+#if !defined(__MODEM_CCCI_EXIST__) || !defined(__MODEM_CARD__)
+            if(Custom_META_SdsSupported() != KAL_TRUE)
+            {
+                cnf_code = FT_CNF_FAIL;
+            }
+            else
+#endif
+            {
+                cnf_code = FT_CNF_OK;
+            }
+        }
+        else if(query_op_code == FT_MISC_EX_OP_RAMDISK_CHECK_EXIST ||
+            query_op_code == FT_MISC_EX_OP_RAMDISK_GET_SIZE ||
+            query_op_code == FT_MISC_EX_OP_RAMDISK_READ)
+        {
+#if defined(__FS_RAMDISK__)                  
+          cnf_code = FT_CNF_OK;
+#else
+          cnf_code = FT_CNF_FAIL;
+#endif           
+        }        
+        /*******************************
+         * obsoleted op codes
+         ******************************/
+        else if(query_op_code == FT_MISC_EX_OP_OBSOLETED1 ||
+                query_op_code == FT_MISC_EX_OP_OBSOLETED2)
+        {
+            cnf_code = FT_CNF_FAIL;
+        }
+        else if(query_op_code == FT_MISC_EX_OP_SET_COMMAND_TO_SYSTEM)
+        {
+            cnf_code = FT_CNF_OK;
+        }        
+        else
+        {
+            cnf_code = FT_CNF_OK;
+        }
+        
+    }
+    else
+    {
+        cnf_code = FT_CNF_FAIL;
+    }
+    return cnf_code;
+}
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_mmrf.c b/mcu/middleware/meta/ft/src/ft_fnc_mmrf.c
new file mode 100644
index 0000000..7e39932
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_mmrf.c
@@ -0,0 +1,224 @@
+/*****************************************************************************
+ *  Copyright Statement:
+ *  --------------------
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+ *  Modification Notice:
+ *  --------------------------
+ *  This software is modified by MediaTek Inc. and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2001
+ *
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_mmrf.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   Factory testing function for MMRF
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+/*************************************************************************
+ * Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h"
+#include "kal_trace.h"
+#include "svc_sap.h"
+#include "md_mw_sap.h"
+#include "mmrf_msgid.h"
+#include "mmrf_msg_interface.h"
+#include "ft_msgid.h"
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#ifndef L1_SIM
+#include "ft_fnc_nvram.h"
+#include "nvram_defs.h"
+#include "nvram_enums.h"
+#include "nvram_interface.h"
+#include "nvram_data_items.h"
+#include "ft_nvram_def.h"
+#include "nvram_struct.h"
+#endif // #ifndef L1_SIM
+#include "ft_fnc_mmrf.h"
+extern kal_eventgrpid MMRF_UPDATE_RUNTIME_EVENT;
+/**
+ * @param metaMessage the input message from META tool for MMRF test command processing
+ */
+void FT_Mmrf_Operation(ilm_struct* ptrMsg)
+{
+    ilm_struct mmrfMessage;
+    FT_CONSTRUCT_CC_MSG(ptrMsg, &mmrfMessage);
+    FT_SEND_MSG(MOD_FT, MOD_MMRF_XL1TST, FT_MMRF_SAP, MSG_ID_FT_TO_MMRF, &mmrfMessage);   
+}
+/**
+ * Confirm message handler for MOD_ETSTM
+ */
+void FT_Mmrf_ConfirmHandler(ilm_struct* mmrfMessage)
+{
+    mmrftst_cnf_struct *ptrMsg;
+    ptrMsg = (mmrftst_cnf_struct *)mmrfMessage->local_para_ptr;
+    if(ptrMsg->type == MMRF_TEST_CMD_CHECK_IF_FUNC_EXIST)
+    {
+        FT_UTILITY_COMMAND_CNF  cnf;
+        kal_mem_set(&cnf, '\0', sizeof(cnf));
+        cnf.status = (ptrMsg->result==1)?FT_CNF_OK:FT_CNF_FAIL;
+        cnf.result.CheckIfFuncExist.query_ft_msg_id = ptrMsg->header.ft_msg_id;
+        cnf.result.CheckIfFuncExist.query_op_code = ptrMsg->param.checkIfFuncExist.query_op_code;
+        FT_UTIL_SendCnf(&cnf, NULL);
+        return;
+    }
+    FT_SEND_MSG_TO_PC(mmrfMessage);
+}
+void FT_MmrfCheckFunctionSupported(kal_uint32 query_op_code)
+{
+    ilm_struct ilm_ptr;
+    mmrftst_req_struct *ptrMsg;	
+    FT_ALLOC_OTHER_CC_MSG( &ilm_ptr, sizeof(mmrftst_req_struct) );
+    // local parameter    
+    ptrMsg = (mmrftst_req_struct *)ilm_ptr.local_para_ptr;
+    ptrMsg->header.ft_msg_id = FT_MMRF_TEST_REQ_ID;  
+    ptrMsg->type = MMRF_TEST_CMD_CHECK_IF_FUNC_EXIST;
+    ptrMsg->param.checkIfFuncExist.query_op_code = (MMRfTestCmdType)query_op_code;
+    FT_SEND_MSG(MOD_FT,  MOD_MMRF_XL1TST, FT_MMRF_SAP, MSG_ID_FT_TO_MMRF, &ilm_ptr);
+}
+/**
+ * Update Runtime Confirm message handler for  MOD_MMRF_XL1TST
+ */
+void FT_Mmrf_UpdateRuntimeHandler(peer_buff_struct* peer_buff, kal_uint16 lid, kal_uint16 rid)
+{
+    ilm_struct ilm_ptr;
+    kal_char* pduToMmrf;
+    kal_char* pduInput;
+    peer_buff_struct* peerToMmrf;
+    mmrf_update_runtime_req_struct* mmrf_update_runtime_req;
+
+    FT_ALLOC_OTHER_CC_MSG(&ilm_ptr, sizeof(mmrf_update_runtime_req_struct));
+    /* set local parameter */
+    mmrf_update_runtime_req = (mmrf_update_runtime_req_struct*)ilm_ptr.local_para_ptr;
+    mmrf_update_runtime_req->nvramLid = lid;
+    mmrf_update_runtime_req->record = rid;
+    /* copy peer buffer */
+    pduInput = get_peer_buff_pdu(peer_buff, NULL);
+    peerToMmrf = construct_cc_non_cached_peer_buff(peer_buff->pdu_len, 0, 0, TD_RESET);
+    pduToMmrf = get_peer_buff_pdu(peerToMmrf, NULL);
+    kal_mem_cpy(pduToMmrf, pduInput, peer_buff->pdu_len);
+    ilm_ptr.peer_buff_ptr = peerToMmrf;
+    FT_SEND_MSG(MOD_FT,  MOD_MMRF_XL1TST, FT_MMRF_SAP, MSG_ID_MMRF_UPDATE_RUNTIME_REQ, &ilm_ptr);
+}
+/**
+ * Update Runtime Confirm message handler for  MOD_MMRF_XL1TST
+ */
+void FT_Mmrf_UpdateRuntimeConfirmHandler(ilm_struct* _ilm)
+{
+    kal_set_eg_events(MMRF_UPDATE_RUNTIME_EVENT, 0x1, KAL_OR);
+}
+kal_bool FT_Mmrf_PollUpdateRuntimeReady()
+{
+    kal_uint32 ev;
+    kal_sleep_task(1);
+    if(kal_retrieve_eg_events(MMRF_UPDATE_RUNTIME_EVENT, 0x1, KAL_AND_CONSUME, &ev, 0) == KAL_NOT_PRESENT)
+    {
+        return KAL_FALSE;
+    }
+    return KAL_TRUE;
+}
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_nrf.c b/mcu/middleware/meta/ft/src/ft_fnc_nrf.c
new file mode 100644
index 0000000..cbdccf5
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_nrf.c
@@ -0,0 +1,95 @@
+/*****************************************************************************
+ *  Copyright Statement:
+ *  --------------------
+ *  This software is protected by Copyright and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2005
+ *
+ *  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ *  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ *  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+ *  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+ *  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+ *  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+ *  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+ *  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+ *  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+ *  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+ *
+ *  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+ *  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+ *  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+ *  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+ *  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ *  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+ *  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+ *  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+ *  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+ *  Modification Notice:
+ *  --------------------------
+ *  This software is modified by MediaTek Inc. and the information contained
+ *  herein is confidential. The software may not be copied and the information
+ *  contained herein may not be used or disclosed except with the written
+ *  permission of MediaTek Inc. (C) 2001
+ *
+ *******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_nr.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   Factory testing function for NR
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+  *************************************************************************/
+/*************************************************************************
+ * Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h"
+#include "kal_trace.h"
+#include "ft_msgid.h"
+#include "svc_sap.h"
+#include "md_mw_sap.h"
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_nrf.h"
+/**
+ * @param metaMessage the input message from META tool for NR test command processing
+ */
+void FT_Nrf_Operation(ilm_struct* ptrMsg)
+{
+    #if defined(__MD97__)
+    ilm_struct nrfMessage;
+    FT_CONSTRUCT_CC_MSG(ptrMsg, &nrfMessage);
+    FT_SEND_MSG(MOD_FT, MOD_NL1, NL1_FT_SAP, MSG_ID_FT_TO_NL1, &nrfMessage);  
+	#endif //!defined(__MD97__)
+}
+/**
+ * Confirm message handler for MOD_NL
+ */
+void FT_Nrf_ConfirmHandler(ilm_struct* nrfMessage)
+{
+    FT_SEND_MSG_TO_PC(nrfMessage);
+}
\ No newline at end of file
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_nvram.c b/mcu/middleware/meta/ft/src/ft_fnc_nvram.c
new file mode 100644
index 0000000..312fd55
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_nvram.c
@@ -0,0 +1,428 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_nvram.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT NVRAM operations
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#if defined(__MOD_NVRAM__) && !defined(NVRAM_NOT_PRESENT)
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_nvram.h"
+#include "ft_fnc_misc.h"
+#include "svc_sap.h"
+#include "nvram_msgid.h"
+#include "ft_msgid.h"
+#include "ft_trace_def.h"
+#include "ft_fnc_mmrf.h"
+/**************************************************************************
+ * NVRAM header
+ *************************************************************************/
+#include "nvram_defs.h"
+#include "nvram_enums.h"
+#include "nvram_interface.h"
+#include "nvram_data_items.h"
+#include "ft_nvram_def.h"
+#include "l4_nvram_def.h"
+#include "nvram_struct.h"
+void FT_Nvram_SendWriteCommandToNvram(peer_buff_struct* peer_buff, kal_uint16 lid, kal_uint16 rid, kal_uint8 ftAccessId, kal_bool holdBufferForRelay)
+{
+    kal_uint8  *pdu_ptr;
+    kal_uint16 pdu_length; 
+    ilm_struct  ilm_ptr;
+    nvram_write_cnf_struct *cnf_result_ptr;
+
+    FT_ALLOC_OTHER_MSG(&ilm_ptr, sizeof( nvram_write_cnf_struct ));
+    cnf_result_ptr = (nvram_write_cnf_struct *)ilm_ptr.local_para_ptr;
+    pdu_ptr = get_peer_buff_pdu(peer_buff, &pdu_length);   
+    cnf_result_ptr->file_idx = lid;
+    cnf_result_ptr->para = rid;
+    cnf_result_ptr->access_id = ftAccessId;
+    
+    /* call secure API  to access nvram item */
+    cnf_result_ptr->result = nvram_external_secure_write_data(lid, rid, pdu_ptr, pdu_length, NULL);
+    MD_TRC_FT_NVRAM_CALL_WRITE_NVRAM_API(cnf_result_ptr->result);	
+    
+    if( holdBufferForRelay != KAL_TRUE)
+    {
+        free_peer_buff(peer_buff);
+    }
+    /* Check polling for MMRF runtime update */
+    FT_SEND_MSG(MOD_FT, MOD_FT, PS_NVRAM_SAP, MSG_ID_NVRAM_WRITE_CNF, &ilm_ptr);
+}
+void FT_Nvram_SendReadCommandToNvram(kal_uint16 lid, kal_uint16 rid, kal_uint8 ftAccessId)
+{
+    nvram_read_cnf_struct  cnf_result;
+    peer_buff_struct *peer_buff = NULL;
+    kal_uint8  *pdu_ptr;
+    kal_uint16 totalRID;
+    kal_uint16 pdu_length; 
+
+    cnf_result.file_idx = lid;
+    cnf_result.para = rid;
+    cnf_result.length = 0;
+    cnf_result.access_id = ftAccessId;
+    cnf_result.result = nvram_get_info(lid, & totalRID, &pdu_length);  
+    if( NVRAM_ERRNO_SUCCESS == cnf_result.result )
+    {
+        if( NULL != (peer_buff=construct_peer_buff(pdu_length, 0, 0, TD_CTRL)) )
+        {
+            pdu_ptr = get_peer_buff_pdu(peer_buff, &pdu_length);  
+            cnf_result.length = pdu_length;
+            /* call secure API  to access nvram item */
+            cnf_result.result = nvram_external_secure_read_data(lid, rid, pdu_ptr, pdu_length, NULL); 
+        }
+        else
+        {
+            cnf_result.result = 0xFA; 
+        }
+    }
+    MD_TRC_FT_NVRAM_CALL_READ_NVRAM_API(cnf_result.result);
+	
+    if ( NVRAM_ERRNO_SUCCESS != cnf_result.result )
+    {
+        cnf_result.length = 0;
+        peer_buff = NULL;
+        free_peer_buff(peer_buff);
+		FT_Nvram_SendReadResponseToHost(&cnf_result, peer_buff, KAL_TRUE);
+    }
+    else
+	{
+		FT_Nvram_ReadNvramConfirmHandler(&cnf_result, peer_buff);
+	}
+}
+/*******************************************************************************
+ * FUNCTION
+ *   FT_Nvram_WriteNvramHandler()
+ *
+ * DESCRIPTION
+ *   Handle the write request of NVRAM
+ *
+ * CALLS
+ *   None
+ *
+ * PARAMETERS
+ *
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+void FT_Nvram_WriteNvramHandler(ft_nvram_write_req_struct_T* req, peer_buff_struct* peer_buff, kal_uint8 accessId)
+{
+    /* Duplicate the message to MMRF for runtime update */
+    FT_Mmrf_UpdateRuntimeHandler(peer_buff, req->file_idx, req->para);
+    FT_Nvram_SendWriteCommandToNvram(peer_buff, req->file_idx, req->para, accessId, KAL_TRUE);
+}
+/*******************************************************************************
+ * FUNCTION
+ *   FT_Nvram_ReadNvramHandler()
+ *
+ * DESCRIPTION
+ *   Handle the read request of FT to NVRAM
+ *
+ * CALLS
+ *   None
+ *
+ * PARAMETERS
+ *
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+void FT_Nvram_ReadNvramHandler(ft_nvram_read_req_struct_T* req, kal_uint8 accessId)
+{
+    FT_Nvram_SendReadCommandToNvram(req->file_idx, req->para, accessId);
+}
+void FT_Nvram_SendReadResponseToHost(nvram_read_cnf_struct* nvramReadCnf, peer_buff_struct* nvramReadCnfPeerBuf, kal_bool holdBufferForRelay)
+{
+    ilm_struct    ilm_ptr;
+    ft_nvram_read_cnf_struct_T *ft_cnf;
+
+    MD_TRC_FT_NVRAM_SEND_READ_RESPONSE_TO_HOST(holdBufferForRelay);
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(ft_nvram_read_cnf_struct_T));
+    ft_cnf = (ft_nvram_read_cnf_struct_T *)ilm_ptr.local_para_ptr;
+    ft_cnf->header.ft_msg_id = FT_NVRAM_READ_CNF_ID;
+    ft_cnf->file_idx = nvramReadCnf->file_idx;
+    ft_cnf->para = nvramReadCnf->para;
+    /* Check the FILE index to SIM lock */
+    if( nvram_test_lock() && (NVRAM_EF_SML_LID == nvramReadCnf->file_idx) )
+    {
+        ft_cnf->status = 0xFF;
+        ilm_ptr.peer_buff_ptr = NULL;
+        free_peer_buff(nvramReadCnfPeerBuf);
+    }
+    else
+    {
+        ft_cnf->status = nvramReadCnf->result;
+        ilm_ptr.peer_buff_ptr = nvramReadCnfPeerBuf;
+    }
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+/*******************************************************************************
+ * FUNCTION
+ *   FT_Nvram_ReadNvramConfirmHandler
+ *
+ * DESCRIPTION
+ *   Handle the confirmation of reading
+ *
+ * CALLS
+ *
+ *
+ * PARAMETERS
+ *   local_para_struct * local_para_ptr, //( force to nvram_read_cnf_struct* cnf )
+ *   peer_buff_struct * peer_buff_ptr
+ *
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+void FT_Nvram_ReadNvramConfirmHandler(nvram_read_cnf_struct* nvramReadCnf, peer_buff_struct* nvramReadCnfPeerBuf)
+{
+    ft_gl_token = ft_gl_nvram_token;
+    FT_Nvram_SendReadResponseToHost(nvramReadCnf, nvramReadCnfPeerBuf, KAL_TRUE);
+}
+void FT_Nvram_SendWriteResponseToHost(nvram_write_cnf_struct* nvramWriteCnf)
+{
+    ilm_struct  ilm_ptr;
+    ft_nvram_write_cnf_struct_T *ptrMsg ;
+
+    MD_TRC_FT_NVRAM_SEND_WRITE_RESPONSE_TO_HOST();
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(ft_nvram_write_cnf_struct_T));
+    ptrMsg = (ft_nvram_write_cnf_struct_T *)ilm_ptr.local_para_ptr;
+    ptrMsg->header.ft_msg_id = FT_NVRAM_WRITE_CNF_ID;
+    ptrMsg->file_idx = nvramWriteCnf->file_idx;
+    ptrMsg->para = nvramWriteCnf->para;
+    ptrMsg->status = nvramWriteCnf->result;
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+}
+/*******************************************************************************
+ * FUNCTION
+ *   FT_Nvram_WriteNvramConfirmHandler
+ *
+ * DESCRIPTION
+ *   Handle the confirmation of writting
+ *
+ * CALLS
+ *
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+void FT_Nvram_WriteNvramConfirmHandler(nvram_write_cnf_struct* nvramWriteCnf)
+{
+    FT_Nvram_SendWriteResponseToHost(nvramWriteCnf);
+}
+kal_bool FT_Nvram_IsModNvramRespnose(ilm_struct* ilm_ptr)
+{
+    if(ilm_ptr->msg_id == MSG_ID_NVRAM_WRITE_CNF ||
+            ilm_ptr->msg_id == MSG_ID_NVRAM_CREATE_IMAGE_CNF ||
+            ilm_ptr->msg_id == MSG_ID_NVRAM_VERIFY_IMAGE_CNF ||
+            ilm_ptr->msg_id == MSG_ID_NVRAM_RESET_CNF ||
+            ilm_ptr->msg_id == MSG_ID_NVRAM_WRITE_IMEI_CNF ||
+            ilm_ptr->msg_id == MSG_ID_NVRAM_SET_LOCK_CNF ||
+            ilm_ptr->msg_id == MSG_ID_NVRAM_SDS_CNF ||
+            ilm_ptr->msg_id == MSG_ID_NVRAM_BIN_REGION_CNF)
+    {
+        return KAL_TRUE;
+    }
+    else
+    {
+        return KAL_FALSE;
+    }
+}
+#endif // #if defined(__MOD_NVRAM__) && !defined(NVRAM_NOT_PRESENT)
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_nvram_sec.c b/mcu/middleware/meta/ft/src/ft_fnc_nvram_sec.c
new file mode 100644
index 0000000..d2e73cc
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_nvram_sec.c
@@ -0,0 +1,322 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_nvram.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FT NVRAM security mechanism
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#if defined(__NVRAM_SECRET_DATA__)
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_fnc_nvram.h"
+#include "ft_fnc_misc.h"
+#include "svc_sap.h"
+#include "nvram_msgid.h"
+#include "ft_msgid.h"
+#include "ft_fnc_mmrf.h"
+/**************************************************************************
+ * NVRAM header
+ *************************************************************************/
+#include "nvram_defs.h"
+#include "nvram_enums.h"
+#include "nvram_interface.h"
+#include "nvram_data_items.h"
+#include "ft_nvram_def.h"
+#include "nvram_struct.h"
+#include "rc4.h"
+/*******************************************************************************
+ * FUNCTION
+ *   FT_NvramSec_WriteNvramHandler()
+ *
+ * DESCRIPTION
+ *   Handle the write request of NVRAM
+ *
+ * CALLS
+ *   None
+ *
+ * PARAMETERS
+ *
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+kal_uint16  g_u2_ft_nvram_pdu_length = 0;
+kal_uint8   *p_g_u1_ft_nvram_pdu_ptr = NULL;
+peer_buff_struct *p_g_pbs_ft_nvram = NULL;
+void FT_NvramSec_WriteNvramHandler(ft_nvram_write_req_struct_T* req, peer_buff_struct* peer_buff, kal_uint8 accessId)
+{
+    //ilm_struct  ilm_ptr;
+    //nvram_write_req_struct *nvram_ptr_loc_para;
+    kal_uint16             pdu_length;
+    kal_uint8              *pdu_ptr = get_peer_buff_pdu( peer_buff, &pdu_length );
+    kal_bool  bPassCheck = KAL_FALSE;
+    kal_int32 err_code = 0xFE;
+    kal_uint8 key[256]; // at most 256 bytes
+    kal_int32 real_key_len;
+    real_key_len = custom_nvram_get_database_key(key, sizeof(key));
+    if(req->msg_num == 2 && real_key_len >0) // we must wait until we collect all
+    {
+        if(req->msg_idx == 0) // allocate a peer buffer to store it.
+        {
+            if(p_g_pbs_ft_nvram != NULL) // free previous buffer
+            {
+                free_peer_buff(p_g_pbs_ft_nvram);
+                p_g_pbs_ft_nvram = NULL;
+            }
+            // allocate a new peer buffer
+            if( NULL != (p_g_pbs_ft_nvram=construct_peer_buff(pdu_length, 0, 0, TD_CTRL)) )
+            {
+                p_g_u1_ft_nvram_pdu_ptr = get_peer_buff_pdu( p_g_pbs_ft_nvram, &g_u2_ft_nvram_pdu_length );
+                kal_mem_cpy(p_g_u1_ft_nvram_pdu_ptr, pdu_ptr , pdu_length);
+                p_g_pbs_ft_nvram->pdu_len = pdu_length;
+            }
+            return; // wait for next message
+        }
+        else // the second message with encrpted data
+        {
+            kal_int32 i;
+            RC4_CNXT cnxt;
+            kal_uint8 *output_data = (kal_uint8*) get_ctrl_buffer(g_u2_ft_nvram_pdu_length);  // since at most 2k bytes
+            if(p_g_u1_ft_nvram_pdu_ptr!=NULL)
+            {
+                // get the key
+                //real_key_len =  custom_nvram_get_database_key(key, sizeof(key));
+                if(real_key_len >0) // get the key
+                {
+                    // deciphered the input data
+                    che_rc4_set_key((RC4_CNXT *)&cnxt, (kal_uint32)real_key_len, (kal_uint8 *)key);
+                    che_rc4((RC4_CNXT *)&cnxt, p_g_u1_ft_nvram_pdu_ptr , g_u2_ft_nvram_pdu_length, key, real_key_len, CHE_MODE_NULL, output_data);
+                    for(i=0; i<g_u2_ft_nvram_pdu_length; i++)
+                    {
+                        if(output_data[i] != pdu_ptr[i])
+                        {
+                            err_code = 0xFD;
+                            break;
+                        }
+                    }
+                    if(i == g_u2_ft_nvram_pdu_length)
+                    {
+                        bPassCheck = true;
+                    }
+                }
+            }
+            else
+            {
+                err_code = 0xFC;
+            }
+            free_ctrl_buffer(output_data);
+        }
+    }
+    else
+    {
+        if(real_key_len == 0) // sec not ON
+            bPassCheck = true;
+    }
+    if(!bPassCheck)
+    {
+        // invoke:
+        nvram_write_cnf_struct  cnf_result;
+        cnf_result.file_idx = req->file_idx;
+        cnf_result.para = req->para;
+        cnf_result.result = err_code;
+        // allocate a peer buffer to stored the output data for debug
+        FT_WriteTo_NVRAM_CNF(&cnf_result);
+        return;
+    }
+    if(real_key_len >0 &&
+            req->msg_num == 2 &&
+            p_g_pbs_ft_nvram != NULL) // re-assign the pdu_ptr, and free the buffer
+    {
+        kal_mem_cpy(pdu_ptr, p_g_u1_ft_nvram_pdu_ptr,pdu_length);
+        free_peer_buff(p_g_pbs_ft_nvram);
+        p_g_pbs_ft_nvram = NULL;
+    }
+    /* Duplicate the message to MMRF for runtime update */
+    FT_Mmrf_UpdateRuntimeHandler(peer_buff, req->file_idx, req->para);
+    FT_Nvram_SendWriteCommandToNvram(peer_buff, req->file_idx, req->para, accessId, KAL_TRUE);
+}
+/*******************************************************************************
+ * FUNCTION
+ *   FT_NvramSec_ReadNvramHandler()
+ *
+ * DESCRIPTION
+ *   Handle the read request of FT to NVRAM
+ *
+ * CALLS
+ *   None
+ *
+ * PARAMETERS
+ *
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+void FT_NvramSec_ReadNvramHandler(ft_nvram_read_req_struct_T* req, kal_uint8 accessId)
+{
+    //ilm_struct  ilm_ptr;
+    //nvram_read_req_struct *ptrMsg;
+    kal_uint8 key[256]; // at most 256 bytes
+    kal_int32 real_key_len;
+    kal_uint8 input_data[4];
+    kal_uint8 output_data[4];
+    kal_uint8 i;
+    RC4_CNXT cnxt;
+    kal_uint32 err_code = 0xFE;
+    kal_bool bPassCheck = KAL_FALSE;
+    real_key_len =  custom_nvram_get_database_key(key, sizeof(key));
+    kal_mem_set(output_data, 0x0, sizeof(output_data));
+    // make sure if the authenticaion pass
+    if(req->ciphered_data_valid && real_key_len > 0 ) // the load need to be checked, and user send ciphered data
+    {
+        kal_mem_cpy(input_data, &(req->file_idx), 2);
+        kal_mem_cpy(input_data+2, &(req->para), 2);
+        // deciphered the input data
+        che_rc4_set_key((RC4_CNXT *)&cnxt, (kal_uint32)real_key_len, (kal_uint8 *)key);
+        che_rc4((RC4_CNXT *)&cnxt, input_data , 4, key, real_key_len, CHE_MODE_NULL, output_data);
+        for(i=0; i<4; i++)
+        {
+            if(output_data[i] != req->ciphered_data[i])
+            {
+                err_code = 0xFD;
+                break;
+            }
+        }
+        if(i == 4)
+            bPassCheck = KAL_TRUE;
+    }
+    else // ciphered data invalid
+    {
+        if(real_key_len == 0) // no need to checked
+            bPassCheck = KAL_TRUE;
+        else // need check, but user doesn't send data
+            err_code = 0xFB;
+    }
+    if(!bPassCheck)
+    {
+        // invoke:
+        kal_uint16    pdu_length_new = 0;
+        kal_uint8   *pdu_ptr_new;
+        peer_buff_struct *peer_buff_new;
+        nvram_read_cnf_struct  cnf_result;
+        cnf_result.file_idx = req->file_idx;
+        cnf_result.para = req->para;
+        cnf_result.result = err_code;
+        cnf_result.access_id = 0;
+        // allocate a peer buffer to stored the output data for debug
+
+        if( NULL != (peer_buff_new=construct_peer_buff(4, 0, 0, TD_CTRL)) )
+        {
+            pdu_ptr_new = get_peer_buff_pdu( peer_buff_new, &pdu_length_new );
+            kal_mem_cpy(pdu_ptr_new, output_data , 4);
+            peer_buff_new->pdu_len = 4;
+        }
+        FT_ReadFrom_NVRAM_CNF(&cnf_result, peer_buff_new);
+        return;
+    }
+    FT_Nvram_SendReadCommandToNvram(req->file_idx, req->para, accessId);
+}
+#endif // #if defined(__NVRAM_SECRET_DATA__)
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_util.c b/mcu/middleware/meta/ft/src/ft_fnc_util.c
new file mode 100644
index 0000000..1ecceed
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_util.c
@@ -0,0 +1,1131 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_fnc_util.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   Factory testing function library (Category: Utility Commands)
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+/*************************************************************************
+* Include Statements for KAL
+ *************************************************************************/
+#include "ctrl_buff_pool.h"
+#include "svc_sap.h"
+#include "ft_msgid.h"
+/**************************************************************************
+ * HAL header
+ *************************************************************************/
+#ifndef L1_SIM
+#include "dcl.h"
+#include "device.h"
+#include "drv_features.h"
+#include "fs_gprot.h"
+#endif //#ifndef L1_SIM
+#include "tst_def.h"
+/**************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#ifndef L1_SIM
+#include "ft_fnc_fat.h"
+#include "ft_fnc_misc.h"
+#include "ft_fnc_misc_ex.h"
+#endif //#ifndef L1_SIM
+#include "ft_fnc_l1rf.h"
+#include "ft_fnc_wcdma.h"
+#include "ft_fnc_lterf.h"
+#include "ft_fnc_tdscdma.h" 
+#include "ft_fnc_mmrf.h"
+kal_uint32 FT_UtilCheckFunctionSupported(kal_uint32 query_op_code);
+/**************************************************************************
+ * Custom header
+ *************************************************************************/
+#ifndef L1_SIM
+#include "meta_customize.h"
+#include "custom_equipment.h"
+#endif // #ifndef L1_SIM
+
+kal_uint32 FT_REQUIRED_META_DLL_MAIN_VER  =   6;
+kal_uint32 FT_REQUIRED_META_DLL_MINOR_VER = 944;
+kal_uint32 FT_REQUIRED_META_DLL_BUILD_NUM =   0;
+kal_uint32 FT_REQUIRED_VERSION_UNKNOWN = 0xFFFFFFFF;
+kal_uint32 FT_REQUIRED_CTRL_BUFF_MAXSIZE = 35536;
+/*******************************************************************************
+ *
+ *  FAT functionality
+ *
+ *******************************************************************************/
+#ifndef L1_SIM /* xl1sim not support FAT */
+/**
+ * Get Path for requested size
+ */
+kal_int16 FT_GetAvailableDrive(kal_int32 size)
+{
+#if !defined(__LOW_COST_SUPPORT_ULC__)
+    kal_int16 drv_letter       = -1;
+    kal_int16 i                = 0;
+    kal_uint32 dev[4]          = {FS_DRIVE_I_SYSTEM, FS_DRIVE_V_NORMAL, FS_DRIVE_V_REMOVABLE, FS_DRIVE_V_EXTERNAL};
+    kal_wchar *pathname        = NULL;
+    pathname = (kal_wchar*)get_ctrl_buffer(FT_FAT_MAX_FULLPATH);
+    if(pathname)
+    {
+        for(i=0;i<4;i++)
+        {
+            drv_letter = FS_GetDrive(dev[i], 1, FS_NO_ALT_DRIVE);
+            if(drv_letter > 0)
+            {
+                kal_wsprintf(pathname, "%c:\\", drv_letter);
+                if(size < FT_GetDiskFreeSpace(pathname))
+                {
+                    break;
+                }
+            }
+        }
+    }
+    else
+    {
+        ASSERT(0);
+    }
+    free_ctrl_buffer(pathname);
+    return drv_letter;
+#else // #if !defined(__LOW_COST_SUPPORT_ULC__)
+    return -1;
+#endif // #if defined(__LOW_COST_SUPPORT_ULC__)
+}
+#endif //#ifndef L1_SIM
+/*************************************************************************
+ * FUNCTION
+ *  ft_get_ctrlbuf_max_size
+ *
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *  0:    Could not target the maximal size
+ *  else: maximal size supported.
+ *
+ * GLOBALS AFFECTED
+ *
+ *************************************************************************/
+kal_uint32 ft_get_ctrlbuf_max_size( void )
+{
+#ifndef L1_SIM
+	kal_int16   i=RPS_CREATED_CTRL_BUFF_POOLS-1;
+	
+	/* Total entries defined at adaptation\include\ctrl_buff_pool.h
+	   RPS_CREATED_CTRL_BUFF_POOLS = 14
+	   For each buffer associated with non-zero entries count, it should have been created,
+	   and pool_id always non-zero. */
+	while ( (ctrl_buff_pool_info_g[i].pool_id==0) && (i >= 0) )
+	   i--;
+
+	/* Somehow, if table corrupted, must return 0 */	   
+	if ( i<0 )
+	   return 0;
+	   
+   return (ctrl_buff_pool_info_g[i].size);
+#else // #ifndef L1_SIM
+	return FT_REQUIRED_CTRL_BUFF_MAXSIZE;
+#endif // #ifdef L1_SIM
+}
+
+/*******************************************************************************
+ *
+ *  FT task check if function exist
+ *
+ *******************************************************************************/
+kal_uint8  FT_UTIL_SendCnf(const FT_UTILITY_COMMAND_CNF  *cnf, peer_buff_struct *p_peer_buff) {
+
+    ilm_struct   ilm_ptr;
+    FT_UTILITY_COMMAND_CNF  *ptrMsg;
+
+    FT_ALLOC_MSG(&ilm_ptr, sizeof(FT_UTILITY_COMMAND_CNF));
+
+    // if ptrMsg != NULL
+    ptrMsg = (FT_UTILITY_COMMAND_CNF *)ilm_ptr.local_para_ptr;
+
+    // assign primitive id
+    ptrMsg->header.ft_msg_id = FT_UTILITY_COMMAND_CNF_ID;
+
+    // assign return structure
+    ptrMsg->type = cnf->type;
+    ptrMsg->result = cnf->result;
+    ptrMsg->status = cnf->status;
+
+    // assign peer buffer
+    if( NULL != p_peer_buff ) {
+        ilm_ptr.peer_buff_ptr = p_peer_buff;
+    }
+
+    FT_SEND_MSG_TO_PC(&ilm_ptr);
+    return 0;
+}
+#ifndef L1_SIM /* xl1sim no device cmd */
+void ft_util_check_if_ulc_support(FT_UTILITY_COMMAND_CNF  *cnf)
+{
+#if defined(__LOW_COST_SUPPORT_ULC__)
+    cnf->status = FT_CNF_OK;
+#else
+    cnf->status = FT_CNF_FAIL;
+#endif
+}
+void ft_util_watch_dog_start(FT_UTILITY_COMMAND_REQ  *req, FT_UTILITY_COMMAND_CNF  *cnf,peer_buff_struct *peer_buff_ret)
+{
+    DCL_HANDLE dcl_wdt_handle;
+    WDT_CTRL_SET_VALUE_T interval;
+    WDT_CTRL_ENABLE_T enable;
+    dcl_wdt_handle = DclWDT_Open(DCL_WDT, FLAGS_NONE);
+	if(DCL_HANDLE_INVALID != dcl_wdt_handle) /*DCL_HANDLE_INVALID (-1) define@dcl.h*/
+	{
+    // set interval
+    interval.u2Value = req->cmd.WatchDog.interval;
+    DclWDT_Control(dcl_wdt_handle, WDT_CMD_SET_VALUE, (DCL_CTRL_DATA_T*)&interval);
+    // send confirm first
+    cnf->status = FT_CNF_OK;
+    FT_UTIL_SendCnf(cnf,peer_buff_ret);
+    kal_sleep_task(50);
+    // disable all interrupt mask
+    SaveAndSetIRQMask();
+    // restart timer
+    DclWDT_Control(dcl_wdt_handle, WDT_CMD_RESTART, 0);
+    // enable watch dog count down
+    enable.fgEnable = DCL_TRUE;
+    DclWDT_Control(dcl_wdt_handle, WDT_CMD_ENABLE, (DCL_CTRL_DATA_T*)&enable);
+    DclWDT_Close(dcl_wdt_handle);
+    Custom_META_USBVirtualComDisconnect();
+    while(1);
+	}else
+	{
+		cnf->status = FT_CNF_FAIL;
+	}
+}
+#endif //#ifndef L1_SIM
+kal_int8 ft_util_check_if_func_exist(const FT_UTILITY_COMMAND_REQ  *req, FT_UTILITY_COMMAND_CNF  *cnf)
+{
+    kal_uint32  query_ft_msg_id = req->cmd.CheckIfFuncExist.query_ft_msg_id;
+    kal_uint32  query_op_code = req->cmd.CheckIfFuncExist.query_op_code;
+    cnf->status = FT_CNF_FAIL;
+    switch(query_ft_msg_id) {
+#ifndef L1_SIM 
+		case FT_REG_READ_ID:
+        case FT_REG_WRITE_ID:
+        case FT_IS_ALIVE_REQ_ID:
+        case FT_POWER_OFF_REQ_ID:
+        case FT_NVRAM_GET_DISK_INFO_REQ_ID:
+        case FT_NVRAM_RESET_REQ_ID:
+        case FT_NVRAM_LOCK_REQ_ID:
+        case FT_NVRAM_READ_REQ_ID:
+        case FT_NVRAM_WRITE_REQ_ID:
+        case FT_VER_INFO_REQ_ID:
+        case FT_ADC_GETMEADATA_ID:
+        {
+            cnf->status = FT_CNF_OK;
+            break;
+        }
+#if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+        case FT_RF_TEST_REQ_ID:
+        {
+            FT_RfCheckFunctionSupported(query_op_code);            
+            return 1; // does not reply message immediately        
+        }
+#endif // #if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#if !defined(__UL1_TASK_DISABLE__)
+        case FT_URF_TEST_REQ_ID:
+        {
+            FT_UL1RfCheckFunctionSuppported(query_op_code);
+            return 1; // does not reply message immediately
+        }
+#endif // #if !defined(__UL1_TASK_DISABLE__)
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+
+		case FT_FAT_OPERATION_ID:
+            if( FT_FAT_OP_OPEN<=query_op_code && FT_FAT_OP_END>query_op_code ) {
+                cnf->status = FT_CNF_OK;
+            }
+            break;
+        case FT_UTILITY_COMMAND_REQ_ID:
+        {
+            cnf->status = FT_UtilCheckFunctionSupported(query_op_code);
+            break;
+        }
+        case FT_MISC_CMD_REQ_ID:
+        {
+            cnf->status = FT_MiscCheckFunctionSupported(query_op_code);
+            break;
+        }
+        case FT_MISC_EX_CMD_REQ_ID:
+        {
+            cnf->status = FT_MiscExCheckFunctionSupported(query_op_code);
+            break;
+        }
+#if defined(__LTE_RAT__)
+#if !defined(__EL1_TASK_DISABLE__)
+        case FT_ERF_TEST_REQ_ID:
+        {
+            FT_ErfCheckFunctionSupported(query_op_code);            
+            return 1; // does not reply message immediately
+        }
+#endif // #if !defined(__EL1_TASK_DISABLE__)
+#endif // #if defined(__LTE_RAT__)
+        case FT_MMRF_TEST_REQ_ID:
+        {
+            FT_MmrfCheckFunctionSupported(query_op_code);            
+            return 1; // does not reply message immediately        
+        }
+#else //#ifndef L1_SIM
+        case FT_IS_ALIVE_REQ_ID:
+        case FT_VER_INFO_REQ_ID:
+        {
+            cnf->status = FT_CNF_OK;
+            break;
+        }
+#if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+        case FT_RF_TEST_REQ_ID:
+        {
+            FT_RfCheckFunctionSupported(query_op_code);            
+            return 1; // does not reply message immediately        
+        }
+#endif // #if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#if !defined(__UL1_TASK_DISABLE__)
+        case FT_URF_TEST_REQ_ID:
+        {
+            FT_UL1RfCheckFunctionSuppported(query_op_code);
+            return 1; // does not reply message immediately
+        }
+#endif // #if !defined(__UL1_TASK_DISABLE__)
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+
+        case FT_UTILITY_COMMAND_REQ_ID:
+        {
+            cnf->status = FT_UtilCheckFunctionSupported(query_op_code);
+            break;
+        }
+#if defined(__LTE_RAT__)
+        case FT_ERF_TEST_REQ_ID:
+        {
+            FT_ErfCheckFunctionSupported(query_op_code);            
+            return 1; // does not reply message immediately
+        }
+#endif // #if defined(__LTE_RAT__)
+        case FT_MMRF_TEST_REQ_ID:
+        {
+            FT_MmrfCheckFunctionSupported(query_op_code);            
+            return 1; // does not reply message immediately        
+        }
+#endif //#ifndef L1_SIM
+        case FT_GET_SLA_STATUS_REQ_ID:
+        case FT_GET_SLA_PARA_REQ_ID:
+        case FT_VERIFY_SLA_RND_REQ_ID:
+        case FT_CHECK_SLA_VER_REQ_ID:
+        {
+            cnf->status = FT_CNF_OK;
+            break;
+        }
+        default:
+            cnf->status = FT_CNF_FAIL;
+            break;
+    }
+
+    // assign return structure
+    cnf->result.CheckIfFuncExist.query_ft_msg_id = query_ft_msg_id;
+    cnf->result.CheckIfFuncExist.query_op_code = query_op_code;
+    return 0;
+}
+
+#ifndef L1_SIM /* xl1sim not support */
+void ft_util_check_if_isp_support(FT_UTILITY_COMMAND_CNF  *cnf) {
+    /*
+#if defined(ISP_SUPPORT) //&& !defined(YUV_SENSOR_SUPPORT)
+cnf->status = FT_CNF_OK;
+#else
+cnf->status = FT_CNF_FAIL;
+#endif
+*/
+    if(custom_ft_util_check_if_isp_support())
+        cnf->status = FT_CNF_OK;
+    else
+        cnf->status = FT_CNF_FAIL;
+}
+#endif //#ifndef L1_SIM
+void ft_util_check_if_smart_phone_modem_supported(FT_UTILITY_COMMAND_CNF *cnf)
+{
+#if defined(__SMART_PHONE_MODEM__)
+    cnf->status = FT_CNF_OK;
+#else
+    cnf->status = FT_CNF_FAIL;
+#endif
+}
+#ifndef L1_SIM /* xl1sim no power/deivce control */
+void ft_util_query_rtc(FT_UTILITY_COMMAND_CNF  *cnf)
+{
+    // HAL modification
+    //RTC_GetTime(&cnf->result.rtc);
+    DCL_HANDLE rtc_handle;
+    RTC_CTRL_GET_TIME_T rtc_cmd_data3; // New Declaration
+    cnf->status = FT_CNF_OK;
+    rtc_handle = DclRTC_Open(DCL_RTC, FLAGS_NONE);
+    if(DclRTC_Control(rtc_handle, RTC_CMD_GET_TIME, (DCL_CTRL_DATA_T *)&rtc_cmd_data3) != STATUS_OK)
+    {
+        cnf->status = FT_CNF_FAIL;
+    }
+    cnf->result.rtc.rtc_year = rtc_cmd_data3.u1Year;
+    cnf->result.rtc.rtc_wday = rtc_cmd_data3.u1WDay;
+    cnf->result.rtc.rtc_mon = rtc_cmd_data3.u1Mon;
+    cnf->result.rtc.rtc_day = rtc_cmd_data3.u1Day;
+    cnf->result.rtc.rtc_hour = rtc_cmd_data3.u1Hour;
+    cnf->result.rtc.rtc_min = rtc_cmd_data3.u1Min;
+    cnf->result.rtc.rtc_sec = rtc_cmd_data3.u1Sec;
+    DclRTC_Close(rtc_handle);
+}
+void ft_util_query_itc_pcl(FT_UTILITY_COMMAND_CNF  *cnf)
+{
+    // Phase out on UMOLY
+    cnf->result.rf_pcl = 0xFFFFFFFF;
+    cnf->status = FT_CNF_OK;
+}
+void ft_util_query_pmic_id(FT_UTILITY_COMMAND_CNF  *cnf)
+{
+    cnf->result.pmic_id = FT_MT6326;
+    cnf->status = FT_CNF_OK;
+}
+
+void ft_util_set_led_light_level(FT_UTILITY_COMMAND_REQ  *req, FT_UTILITY_COMMAND_CNF  *cnf)
+{
+#if(!defined(__L1_STANDALONE__))
+    kal_uint8   level=0;
+    level=req->cmd.LEDLevel.led_light_level;
+    if(custom_cfg_gpio_set_level(GPIO_DEV_LED_KEY,level))
+        cnf->status = FT_CNF_OK;
+    else
+        cnf->status = FT_CNF_FAIL;
+#endif
+}
+void ft_util_set_vibrator_onoff(FT_UTILITY_COMMAND_REQ  *req, FT_UTILITY_COMMAND_CNF  *cnf)
+{
+#if(!defined(__L1_STANDALONE__))
+	kal_uint8   onoff=0;
+    onoff=req->cmd.VibrOnOff.onoff;
+    if(custom_cfg_gpio_set_level(GPIO_DEV_VIBRATOR,onoff))
+        cnf->status = FT_CNF_OK;
+    else
+        cnf->status = FT_CNF_FAIL;
+#endif
+}
+void ft_util_set_lcd_light_level(FT_UTILITY_COMMAND_REQ  *req, FT_UTILITY_COMMAND_CNF  *cnf)
+{
+#if(!defined(__L1_STANDALONE__))
+    kal_uint8   level=0;
+    kal_uint8 led_type;
+    level=req->cmd.LCDLevel.lcd_light_level;
+    led_type = req->cmd.LCDLevel.lcd_type;
+    if(level>5) level = 5;
+    if(led_type==0)
+    {
+        if(custom_cfg_gpio_set_level(GPIO_DEV_LED_MAINLCD,level))
+            cnf->status = FT_CNF_OK;
+        else
+            cnf->status = FT_CNF_FAIL;
+    }
+    else if(led_type==1)
+    {
+        if(custom_cfg_gpio_set_level(GPIO_DEV_LED_SUBLCD,level))
+            cnf->status = FT_CNF_OK;
+        else
+            cnf->status = FT_CNF_FAIL;
+
+    }
+#endif
+}
+#endif //#ifndef L1_SIM
+void ft_util_check_vers(FT_UTILITY_COMMAND_REQ  *req, FT_UTILITY_COMMAND_CNF  *cnf, peer_buff_struct **pp_peer_buff_ret)
+{
+    META_UTIL_CHECK_TARGET_VER_CNF_T *p_dt = NULL;
+    kal_uint16  pdu_length = 0;
+
+    // allocate peer buffer
+    if(NULL == (*pp_peer_buff_ret = construct_peer_buff(sizeof(META_UTIL_CHECK_TARGET_VER_CNF_T), 0, 0, TD_CTRL)))
+	{
+		cnf->status = FT_CNF_FAIL;
+		return;
+	}
+
+    p_dt = (META_UTIL_CHECK_TARGET_VER_CNF_T *)get_peer_buff_pdu(*pp_peer_buff_ret, &pdu_length);
+    kal_mem_set(p_dt, 0, sizeof(META_UTIL_CHECK_TARGET_VER_CNF_T));
+    p_dt->m_bCheckPass = KAL_TRUE;
+
+    if(req->cmd.m_rCheckMetaVerReq.m_eVerType == META_VERSION_META_DLL_UTIL_VER ||
+            req->cmd.m_rCheckMetaVerReq.m_eVerType == META_VERSION_USER_DEFINE)
+    {
+        // checkin
+        // main version first, if >, pass the check!, if < fail,
+        // if main version is the same, check minor version
+        // if minor version the same, check build number
+
+        if(req->cmd.m_rCheckMetaVerReq.m_u4MainVersion < FT_REQUIRED_META_DLL_MAIN_VER)
+        {
+            p_dt->m_bCheckPass = KAL_FALSE;
+        }
+        else if(req->cmd.m_rCheckMetaVerReq.m_u4MainVersion == FT_REQUIRED_META_DLL_MAIN_VER)
+        {
+            if(req->cmd.m_rCheckMetaVerReq.m_u4MinorVersion < FT_REQUIRED_META_DLL_MINOR_VER)
+            {
+                p_dt->m_bCheckPass = KAL_FALSE;
+            }
+            else if(req->cmd.m_rCheckMetaVerReq.m_u4MinorVersion == FT_REQUIRED_META_DLL_MINOR_VER)
+            {
+                if(req->cmd.m_rCheckMetaVerReq.m_u4BuildNum < FT_REQUIRED_META_DLL_BUILD_NUM)
+                    p_dt->m_bCheckPass = KAL_FALSE;
+            }
+        }
+        // assign the target version information
+        p_dt->m_u4TargetMainVersion = FT_REQUIRED_META_DLL_MAIN_VER;
+        p_dt->m_u4TargetMinorVersion = FT_REQUIRED_META_DLL_MINOR_VER;
+        p_dt->m_u4TargetBuildNum = FT_REQUIRED_META_DLL_BUILD_NUM;
+    }
+    else // other type version check // so far, none, just assign version info to 0xFFFFFFFF
+    {
+        // in this case: version check pass
+        p_dt->m_u4TargetMainVersion = FT_REQUIRED_VERSION_UNKNOWN;
+        p_dt->m_u4TargetMinorVersion = FT_REQUIRED_VERSION_UNKNOWN;
+        p_dt->m_u4TargetBuildNum = FT_REQUIRED_VERSION_UNKNOWN;
+    }
+    cnf->status = FT_CNF_OK;
+}
+void ft_util_set_check_paras(FT_UTILITY_COMMAND_REQ  *req, FT_UTILITY_COMMAND_CNF  *cnf)
+{
+    cnf->status = FT_CNF_OK;
+}
+#ifndef L1_SIM /* xl1sim no power control */
+void ft_util_reboot_to_normal_mode(FT_UTILITY_COMMAND_REQ  *req, FT_UTILITY_COMMAND_CNF *cnf)
+{
+    DCL_HANDLE handle;
+    handle=DclPW_Open(DCL_PW, FLAGS_NONE);
+    /* RCT_PDN2 bit1: make sure the the next boot is IDLE (normal mode) */
+    DclPW_Control(handle,PW_CMD_SET_SWITCH_TO_IDLE,NULL);
+    DclPW_Close(handle);
+    // enable watchdog timer
+    ft_util_watch_dog_start(req, cnf, NULL);
+}
+void ft_util_get_vpa_voltage_list(const FT_UTILITY_COMMAND_REQ *req, FT_UTILITY_COMMAND_CNF *cnf, peer_buff_struct **peer_buff_ret)
+{
+    DCL_HANDLE handle;
+    PMU_CTRL_VPA_GET_VOLTAGE_LIST voltageList;
+    handle=DclPMU_Open(DCL_PMU, FLAGS_NONE);
+    if(DclPMU_Control(handle, VPA_GET_VOLTAGE_LIST, (DCL_CTRL_DATA_T *)&voltageList) != STATUS_OK)
+    {
+        cnf->status = FT_CNF_FAIL;
+    }
+    else
+    {
+        cnf->status = FT_CNF_OK;
+    }
+    DclPMU_Close(handle);
+    if(cnf->status == FT_CNF_OK)
+    {
+        if( NULL != (*peer_buff_ret=construct_peer_buff(sizeof(FtUtilCmdCnfVpaVoltageList), 0, 0, TD_CTRL)) )
+        {
+            kal_uint32 i;
+            FtUtilCmdCnfVpaVoltageList * pdu_ptr = get_peer_buff_pdu( *peer_buff_ret, &((*peer_buff_ret)->pdu_len) );
+            if(pdu_ptr != NULL)
+            {
+                kal_mem_set(pdu_ptr, 0, sizeof(FtUtilCmdCnfVpaVoltageList));
+                for(i=0;i<voltageList.number;i++)
+                {
+                    /******************************************************
+                     * if the voltage is valid, pass the information to PC
+                     *****************************************************/
+                    if(voltageList.pVoltageList[i] != PMU_VOLT_INVALID)
+                    {
+                        pdu_ptr->voltageList[pdu_ptr->validNumber]   = voltageList.pVoltageList[i];
+                        pdu_ptr->registerValue[pdu_ptr->validNumber] = i;
+                        pdu_ptr->validNumber++;
+                    }
+                }
+            }
+            else
+            {
+                ASSERT(pdu_ptr);
+            }
+        }
+        else
+        {
+            ASSERT(0);
+        }
+    }
+}
+#endif //#ifndef L1_SIM
+#ifndef L1_SIM
+void FT_UtilityCommand(ilm_struct *ptrMsg) {
+
+    FT_UTILITY_COMMAND_REQ  *p_req=(FT_UTILITY_COMMAND_REQ *)ptrMsg->local_para_ptr;
+    FT_UTILITY_COMMAND_CNF  cnf;
+    peer_buff_struct        *peer_buff_ret = NULL;
+
+    kal_mem_set(&cnf, '\0', sizeof(cnf));
+    cnf.type = p_req->type;
+    cnf.status = FT_CNF_FAIL;
+    peer_buff_ret = NULL;
+
+    switch(p_req->type) {
+        case FT_UTILCMD_CHECK_IF_FUNC_EXIST:
+            if(ft_util_check_if_func_exist(p_req, &cnf))
+            {
+                 return;
+            }
+            break;
+        case FT_UTILCMD_CHECK_IF_ISP_SUPPORT:
+            ft_util_check_if_isp_support(&cnf);
+            break;
+        case FT_UTILCMD_ENABLE_WATCHDOG_TIMER:
+            ft_util_watch_dog_start(p_req, &cnf,peer_buff_ret);
+            break;
+        case FT_UTILCMD_CHECK_IF_ACOUSTIC16_SUPPORT:
+            cnf.status = FT_CNF_OK;
+            break;
+        case FT_UTILCMD_CHECK_IF_LOW_COST_SINGLE_BANK_FLASH:
+#ifdef _LOW_COST_SINGLE_BANK_FLASH_
+            cnf.status = FT_CNF_OK;
+#endif
+            break;
+        case FT_UTILCMD_QUERY_PMIC_ID:
+            ft_util_query_pmic_id(&cnf);
+            break;
+        case FT_UTILCMD_LED_LIGHT_LEVEL:
+            ft_util_set_led_light_level(p_req,&cnf);
+            break;
+        case FT_UTILCMD_VIBRATOR_ONOFF:
+            ft_util_set_vibrator_onoff(p_req,&cnf);
+            break;
+        case FT_UTILCMD_QUERY_LOCAL_TIME:
+            ft_util_query_rtc(&cnf);
+            break;
+        case FT_UTILCMD_CHECK_IF_DRC_SUPPORT:
+#if defined(DRC_ENABLED)
+            cnf.status = FT_CNF_OK;
+#endif
+            break;
+        case FT_UTILCMD_MAIN_SUB_LCD_LIGHT_LEVEL:
+            ft_util_set_lcd_light_level(p_req, &cnf);
+            break;
+        case FT_UTILCMD_CHECK_IF_ULC_FAT_SUPPORT:
+            ft_util_check_if_ulc_support(&cnf);
+            break;
+        case FT_UTILCMD_CHECK_IF_SMART_PHONE_MODEM_SUPPORT:
+            ft_util_check_if_smart_phone_modem_supported(&cnf);
+            break;
+        case FT_UTILCMD_CHECK_TARGET_META_REQUIRED_VERS:
+            ft_util_check_vers(p_req,&cnf,&peer_buff_ret);
+            break;
+        case FT_UTILCMD_SET_TARGET_CHECK_PARAS:
+            ft_util_set_check_paras(p_req,&cnf);
+            break;
+        case FT_UTILCMD_CHECK_IF_TARGET_NV_SEC_ON:
+            cnf.result.m_bNVSecOn = KAL_FALSE;
+            cnf.status = FT_CNF_OK;
+            break;
+        case FT_UTILCMD_REBOOT_TO_NORMAL_MODE:
+            ft_util_reboot_to_normal_mode(p_req, &cnf);
+            break;
+        case FT_UTILCMD_QUERY_TARGET_OPTION_INFO:
+        {
+            cnf.result.m_u4TargetOptionInfo = 0; // reset to 0
+#ifdef LIPTON_BB
+            cnf.result.m_u4TargetOptionInfo |= META_LIPTON_OPTION_ON;  // 0x00000001
+#endif // #ifdef LIPTON_BB
+#ifdef __TC01__
+            cnf.result.m_u4TargetOptionInfo |= META_TC01_OPTION_ON;  // 0x00000002 
+#endif // #ifdef __TC01__
+#if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+            if(KAL_TRUE == TL1_IS_3G_TDD_EXIST())
+            {
+                cnf.result.m_u4TargetOptionInfo |= META_AST_TD_OPTION_ON;  // 0x00000004
+            }
+#endif // #if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+            cnf.status = FT_CNF_OK;
+            break;
+        }
+        case FT_UTILCMD_QUERY_VPA_VOLTAGE_LIST:
+        {
+            ft_util_get_vpa_voltage_list(p_req, &cnf, &peer_buff_ret);
+            break;
+        }
+        case FT_UTILCMD_QUERY_DRIVE_AVAILABLE_FOR_FILE_SIZE:
+        {
+            cnf.status = FT_CNF_OK;
+            cnf.result.driveLetter = FT_GetAvailableDrive(p_req->cmd.requestedFileSize);
+            break;
+        }
+        case FT_UTILCMD_QUERY_MAX_CTRL_BUFFER_SIZE:
+        {
+            cnf.status = FT_CNF_OK;
+            /*
+             * prevent from customization error
+             */
+            if(ft_get_ctrlbuf_max_size() <= Custom_META_ControlBufferSize())
+            {
+                cnf.result.maxControlBufferSize = ft_get_ctrlbuf_max_size();
+            }
+            else
+            {
+                /*
+                 * Keep the original performance
+                 */
+                if(Custom_META_ControlBufferSize() < 2048)
+                {
+                    cnf.result.maxControlBufferSize = 2048;
+                }
+                else
+                {
+                    cnf.result.maxControlBufferSize = Custom_META_ControlBufferSize();
+                }
+            }
+            break;
+        }
+        case FT_UTILCMD_QUERY_ADC_MODULE_SUPPORT:
+        {
+            cnf.status = FT_CNF_OK;
+#if defined(DRV_ADC_NOT_EXIST)||defined(DRV_ADC_OFF)
+            cnf.result.module_support = KAL_FALSE;
+#else
+            cnf.result.module_support = KAL_TRUE;
+#endif // #if defined(DRV_ADC_NOT_EXIST)||defined(DRV_ADC_OFF)
+            break;
+        }
+        case FT_UTILCMD_QUERY_RTC_MODULE_SUPPORT:
+        {
+            cnf.status = FT_CNF_OK;
+#if defined(DRV_RTC_OFF)||defined(DRV_RTC_NOT_EXIST)
+            cnf.result.module_support = KAL_FALSE;
+#else
+            cnf.result.module_support = KAL_TRUE;
+#endif // #if defined(DRV_RTC_NOT_EXIST)||defined(DRV_RTC_OFF)
+            break;
+        }
+        case FT_UTILCMD_QUERY_META_MODE_TRACE:
+        {
+#if defined(__TST_META_MODE_TRACE_ENABLE__)
+            cnf.result.trace_mode = 0;
+            cnf.status = FT_CNF_OK;
+#else
+            cnf.status = FT_CNF_FAIL;
+#endif // #if defined(__TST_META_MODE_TRACE_ENABLE__)           
+            break;
+        }
+        case FT_UTILCMD_ENABLE_META_MODE_TRACE:
+        {
+            cnf.status = FT_CNF_FAIL;
+            break;
+        }
+        case FT_UTILCMD_QUERY_MODEM_MODE:
+        {
+            kal_uint8 boot_mode = kal_query_boot_mode();
+            cnf.result.modem_mode = boot_mode;
+            cnf.status = FT_CNF_OK;
+        }
+        default:
+            break;
+    }
+    FT_UTIL_SendCnf(&cnf, peer_buff_ret);
+}
+#else //#ifndef L1_SIM
+void FT_UtilityCommand(ilm_struct *ptrMsg) {
+
+    FT_UTILITY_COMMAND_REQ  *p_req=(FT_UTILITY_COMMAND_REQ *)ptrMsg->local_para_ptr;
+    FT_UTILITY_COMMAND_CNF  cnf;
+    peer_buff_struct        *peer_buff_ret = NULL;
+
+    kal_mem_set(&cnf, '\0', sizeof(cnf));
+    cnf.type = p_req->type;
+    cnf.status = FT_CNF_FAIL;
+    peer_buff_ret = NULL;
+
+    switch(p_req->type) {
+        case FT_UTILCMD_CHECK_IF_FUNC_EXIST:
+            if(ft_util_check_if_func_exist(p_req, &cnf))
+            {
+                 return;
+            }
+            break;
+        case FT_UTILCMD_CHECK_IF_SMART_PHONE_MODEM_SUPPORT:
+            ft_util_check_if_smart_phone_modem_supported(&cnf);
+            break;
+        case FT_UTILCMD_CHECK_TARGET_META_REQUIRED_VERS:
+            ft_util_check_vers(p_req,&cnf,&peer_buff_ret);
+            break;
+        case FT_UTILCMD_SET_TARGET_CHECK_PARAS:
+            ft_util_set_check_paras(p_req,&cnf);
+            break;
+        case FT_UTILCMD_QUERY_MAX_CTRL_BUFFER_SIZE:
+        {
+            cnf.status = FT_CNF_OK;
+			cnf.result.maxControlBufferSize = ft_get_ctrlbuf_max_size();
+            break;
+        }
+        default:
+            break;
+    }
+    FT_UTIL_SendCnf(&cnf, peer_buff_ret);
+}
+#endif //#ifndef L1_SIM
+kal_uint32 FT_UtilCheckFunctionSupported(kal_uint32 query_op_code)
+{
+    kal_uint32 cnf_code;
+    if( FT_UTILCMD_END > query_op_code )
+    {
+        switch(query_op_code)
+        {
+            // obsolete
+            case FT_UTILCMD_BT_POWER_ON:
+                cnf_code = FT_CNF_FAIL;
+                break;
+            case FT_UTILCMD_QUERY_BT_WIFI_SINGLE_ANTENNA_CAP:
+            case FT_UTILCMD_SET_ANTENNA_PATH_TO_BT:
+            case FT_UTILCMD_SET_ANTENNA_PATH_TO_WIFI:
+                cnf_code = FT_CNF_FAIL;
+                break;
+            case FT_UTILCMD_QUERY_LIMITED_STATE:
+            {
+                cnf_code = FT_CNF_FAIL;
+                break;
+            }
+#if !defined(__TST_META_MODE_TRACE_ENABLE__)
+            case FT_UTILCMD_QUERY_META_MODE_TRACE:
+            case FT_UTILCMD_ENABLE_META_MODE_TRACE:
+            {
+                cnf_code = FT_CNF_FAIL;
+                break;
+            }
+#endif // #if !defined(__TST_META_MODE_TRACE_ENABLE__)
+            case FT_UTILCMD_RF_ITC_PCL:
+            {
+                cnf_code = FT_CNF_FAIL;
+                break;            	
+            }
+            default:
+                cnf_code = FT_CNF_OK;
+                break;
+        }
+    }
+    else
+    {
+        cnf_code = FT_CNF_FAIL;
+    }
+    return cnf_code;
+}
diff --git a/mcu/middleware/meta/ft/src/ft_fnc_wcdma.c b/mcu/middleware/meta/ft/src/ft_fnc_wcdma.c
new file mode 100644
index 0000000..2f5cc6c
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_fnc_wcdma.c
@@ -0,0 +1,351 @@
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_fnc_wcdma.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *  WCDMA Function
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#if !defined(__UL1_TASK_DISABLE__)
+
+/*************************************************************************
+* Include Statements for KAL
+ *************************************************************************/
+
+#include "kal_public_defs.h" //MSBB change #include "stack_common.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_msgs.h"
+#include "md_sap.h"
+#include "svc_sap.h"
+#include "ft_msgid.h"
+
+#include "ul1tst_public.h"
+
+
+/*************************************************************************
+* Include Statements for MAUI
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_public.h"
+#include "ft_fnc_wcdma.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_config.h"
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+void FT_FtURfTestReq( ilm_struct *ptrMsg )
+{
+    ilm_struct urfMessage;
+    FT_CONSTRUCT_CC_MSG(ptrMsg, &urfMessage);
+    FT_SEND_MSG(MOD_FT, MOD_UL1, FT_UL1TST_SAP, MSG_ID_FT_TO_UL1TST, &urfMessage);
+}
+void FT_UL1TST_SEND_CNF_BACK(ilm_struct *ptrMsg_ul1tst)
+{
+    ft_urf_test_cnf_T *ptrMsg;
+    ptrMsg = (ft_urf_test_cnf_T *)ptrMsg_ul1tst->local_para_ptr;
+    if(ptrMsg->type == URF_TEST_CMD_CHECK_IF_FUNC_EXIST )
+    {
+        FT_UTILITY_COMMAND_CNF  cnf;
+        kal_mem_set(&cnf, '\0', sizeof(cnf));
+        cnf.status = (ptrMsg->param.CheckIfFuncExist.result==1)?FT_CNF_OK:FT_CNF_FAIL;
+        cnf.result.CheckIfFuncExist.query_ft_msg_id = ptrMsg->header.ft_msg_id;
+        cnf.result.CheckIfFuncExist.query_op_code = ptrMsg->param.CheckIfFuncExist.query_op_code;
+        FT_UTIL_SendCnf(&cnf, NULL);
+        return;
+    }
+    FT_SEND_MSG_TO_PC(ptrMsg_ul1tst);
+}
+void FT_UL1RfCheckFunctionSuppported(kal_uint32 query_op_code)
+{
+    ilm_struct ilm_ptr;
+    ft_urf_test_req_T *ptrMsg;	
+    FT_ALLOC_OTHER_CC_MSG( &ilm_ptr, sizeof(ft_urf_test_req_T) );
+    // local parameter    
+    ptrMsg = (ft_urf_test_req_T *)ilm_ptr.local_para_ptr;
+    ptrMsg->header.ft_msg_id = FT_URF_TEST_REQ_ID;  
+    ptrMsg->type = URF_TEST_CMD_CHECK_IF_FUNC_EXIST;
+    ptrMsg->param.query_op_code = (URfTestCmdType)query_op_code;
+    FT_SEND_MSG(MOD_FT, MOD_UL1, FT_UL1TST_SAP, MSG_ID_FT_TO_UL1TST, &ilm_ptr);
+}
+#endif  // #ifndef  (__UL1_TASK_DISABLE__)
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
diff --git a/mcu/middleware/meta/ft/src/ft_main.c b/mcu/middleware/meta/ft/src/ft_main.c
new file mode 100644
index 0000000..1b505a5
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_main.c
@@ -0,0 +1,1887 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ft_main.c
+ *
+ * Project:
+ * --------
+ *   Maui_Software
+ *
+ * Description:
+ * ------------
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ *
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+/*************************************************************************
+ * Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h" //MSBB change #include "stack_common.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_msgs.h"
+#ifndef L1_SIM
+#include "task_config.h"
+#endif // #ifndef L1_SIM
+#include "syscomp_config.h"
+#include "md_mw_sap.h"
+#include "mmrf_msgid.h"
+#include "mmrf_msg_interface.h"
+#include "svc_sap.h"
+#include "ft_msgid.h"
+//#include "wndrv_msgid.h"
+#include "l1hisr_msgid.h"
+#include "sim_public_msgid.h"
+#ifdef L1_SIM
+#include "simul_public.h"
+#endif
+/*************************************************************************
+ * System Service header
+ *************************************************************************/
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "kal_public_defs.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_config.h"
+//MSBB remove #include "fctycomp_config.h"
+#include "stdio.h"
+#ifndef L1_SIM
+#include "init.h"
+#endif // #ifndef L1_SIM
+/*************************************************************************
+ * NVRAM header
+ *************************************************************************/
+#ifndef L1_SIM
+#include "nvram_data_items.h"
+#include "ft_nvram_def.h"
+#include "nvram_struct.h"
+#include "nvram_enums.h"
+#include "nvram_msgid.h"
+#endif // #ifndef L1_SIM
+/*************************************************************************
+ * Custom header
+ *************************************************************************/
+#ifndef L1_SIM
+#include "custom_nvram_config.h"
+#include "custom_equipment.h"
+#endif // #ifndef L1_SIM
+/*************************************************************************
+ * HAL header
+ *************************************************************************/
+#ifndef L1_SIM
+#if !defined(__L1_STANDALONE__)
+#include "device.h"  // for GPIO_DEV_LED_MAINLCD and LED_LIGHT_LEVEL5
+#endif
+#endif // #ifndef L1_SIM
+/*************************************************************************
+ * FT header
+ *************************************************************************/
+#include "ft_msg.h"
+#include "ft_mem.h"
+#include "ft_private.h"
+#ifndef L1_SIM
+#include "ft_customize.h"
+#endif // #ifndef L1_SIM
+#include "ft_fnc_l1rf.h"
+#ifndef L1_SIM
+#include "ft_fnc_misc.h"
+#include "ft_fnc_misc_ex.h"
+#include "ft_fnc_custom.h"
+#include "ft_fnc_aux.h"
+#endif // #ifndef L1_SIM
+#include "ft_fnc_wcdma.h"
+#include "ft_fnc_tdscdma.h"
+#ifndef L1_SIM
+#include "ft_fnc_fat.h"
+#include "ft_fnc_nvram.h"
+#endif // #ifndef L1_SIM
+#include "ft_fnc_lterf.h"
+#include "ft_fnc_mmrf.h"
+#include "ft_fnc_nrf.h"
+#include "ft_fnc_l4.h"
+#ifndef L1_SIM
+#include "ft_fnc_c2krf.h"
+fp_nvram_read_handler_t FT_ReadFrom_NVRAM             = FT_Nvram_ReadNvramHandler;
+fp_nvram_write_handler_t FT_WriteTo_NVRAM             = FT_Nvram_WriteNvramHandler;
+fp_nvram_read_confirm_handler_t FT_ReadFrom_NVRAM_CNF = FT_Nvram_ReadNvramConfirmHandler;
+fp_nvram_write_confirm_handler_t FT_WriteTo_NVRAM_CNF = FT_Nvram_WriteNvramConfirmHandler;
+#endif // #ifndef L1_SIM
+/*************************************************************************
+ * SIM header
+ *************************************************************************/
+#ifndef L1_SIM
+#include "ps2sim_struct.h"
+#endif // #ifndef L1_SIM
+/*************************************************************************
+ * SLA header
+ *************************************************************************/
+#include "meta_sec_support.h"
+/*************************************************************************
+ * Function declaration
+ *************************************************************************/
+void FT_Task(task_entry_struct * task_entry_ptr);
+kal_bool FT_Init(void);
+extern void L1T_DispatchReports(void);
+kal_uint16   ft_gl_token=0;
+kal_uint16   ft_gl_rf_token;
+kal_uint16   ft_gl_l4aud_token;
+kal_uint16   ft_gl_l4aud_ind_token;
+kal_uint16   ft_gl_nvram_token;
+kal_uint16   ft_gl_customer_token;
+kal_uint16          ft_gl_l4aud_current_volume = 3;
+peer_buff_struct    *ft_gl_l4aud_peer_buf = NULL;
+extern kal_uint8    ft_gl_sim_cmd_type;  // sim cmd type from ft_fnc_misc.c
+
+kal_char g_FT_debug_buf[128];
+kal_uint16   FT_GetGolbalToken(void)
+{
+    return ft_gl_token;
+}
+/*************************************************************************
+ * FUNCTION
+ *  ft_create
+ *
+ * DESCRIPTION
+ *
+ * PARAMETERS
+ *
+ * RETURNS
+ *  None
+ *
+ * GLOBALS AFFECTED
+ *
+ *************************************************************************/
+kal_bool ft_create(comptask_handler_struct **handle)
+{
+    static const comptask_handler_struct ft_handler_info =
+    {
+        FT_Task,  /* task entry function */
+        FT_Init,  /* task initialization function */
+        NULL  /* task configuration function */
+    };
+
+    *handle = (comptask_handler_struct *)&ft_handler_info;
+    return KAL_TRUE;
+}
+
+#ifdef L1_SIM
+extern kal_status gs_read_message(module_type, void *, kal_uint16, kal_bool);
+#endif 
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/*******************************************************************************
+ * FUNCTION
+ *   FT_InitCalibrationData
+ *
+ * DESCRIPTION
+ *   The calibration data fetch in power-on stage
+ *
+ * CALLS
+ *
+ * PARAMETERS
+ *   None
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+void FT_InitCalibrationData(task_entry_struct *task_entry_ptr)
+{
+#ifndef L1_SIM
+    nvram_startup_req_struct *ptrMsg;
+    ptrMsg = (nvram_startup_req_struct*)construct_local_para(sizeof(nvram_startup_req_struct), TD_CTRL);
+    if(NULL == ptrMsg)
+    {
+        ASSERT(0);
+    }
+    ptrMsg->poweron_mode=NVRAM_POWERON_NORMAL;
+    msg_send5(MOD_FT, MOD_NVRAM, PS_NVRAM_SAP, MSG_ID_NVRAM_STARTUP_REQ, (local_para_struct*)ptrMsg);
+#endif // #ifndef L1_SIM
+}
+
+/*******************************************************************************
+*
+*  Local Functions
+*
+*******************************************************************************/
+#ifdef L1_CATCHER
+void Trc_Init(void);
+#endif
+static void FT_Initialization(task_entry_struct *task_entry_ptr)
+{
+    // active module ID in task_active_module_g
+    kal_set_active_module_id(MOD_FT);
+#ifndef L1_SIM
+    FtInitMemoryPool();
+    // custom init
+    FT_CustomInit();
+#if !defined(__L1_STANDALONE__)
+    // enable main LCD backlight
+    custom_cfg_gpio_set_level(GPIO_DEV_LED_MAINLCD, LED_LIGHT_LEVEL5);
+#endif // #if !defined(__L1_STANDALONE__)
+#endif // #ifndef L1_SIM
+#ifdef L1_CATCHER
+    // L1 logging initialization
+    Trc_Init();
+#endif // #ifdef L1_CATCHER
+    FT_InitCalibrationData(task_entry_ptr);
+    FT_InitFtData();
+#if ( defined(__HSDPA_SUPPORT__) || defined(__HSUPA_SUPPORT__) ) && defined(__MODEM_CARD__)
+    /// clear USB download RTC bit for HSPA data card project
+    INT_SetCmdToSys(SYS_CMD_CLR_DL_FLAG);
+#endif // #if ( defined(__HSDPA_SUPPORT__) || defined(__HSUPA_SUPPORT__) ) && defined(__MODEM_CARD__)
+}
+
+extern kal_bool Custom_META_IsSecureOperation(ilm_struct* ptrMsg);
+
+#ifndef L1_SIM
+void FT_DispatchMessage(ilm_struct* ptrMsg)
+{
+    FT_H  *ft_header;
+    ft_header=(FT_H *)(ptrMsg->local_para_ptr);
+    /* process messages with specific message ID */
+    switch(ptrMsg->msg_id)
+    {
+        case MSG_ID_FT_CAL_DATA_ADD_ONE_REQ:
+        {
+            FT_Misc_CalDataInTargetAddOneRequestHandler(ptrMsg);
+            return;
+        }
+        case MSG_ID_MMRF_UPDATE_RUNTIME_CNF:
+        {
+            FT_Mmrf_UpdateRuntimeConfirmHandler(ptrMsg);
+            return;
+        }
+        default:
+            break;
+    }
+    /* process message with specific source module ID */
+#if !defined(__DHL_MODULE__)
+    if(ptrMsg->src_mod_id == MOD_TST_READER)
+#else
+    if(ptrMsg->src_mod_id == MOD_DHL)
+#endif // #if !defined(__DHL_MODULE__)
+    {
+        ft_gl_token=ft_header->token;
+#ifdef __META_SLA_ENHANCEMENT__
+        if (FT_MetaSLA_Is_Enabled() && !MetaSLA_Is_Verified())
+        {
+            if(KAL_TRUE == Custom_META_IsSecureOperation(ptrMsg))
+            {
+                dhl_print(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_FT,"[SLA] msg id:%d is dropped since SLA is not verified", ft_header->ft_msg_id);
+                return;
+            }
+        }
+#endif // #ifdef __META_SLA_ENHANCEMENT__
+
+        switch (ft_header->ft_msg_id)
+        {
+            /********************************************
+             * L1 RF test functionality
+             ********************************************/
+#if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+            case FT_RF_TEST_REQ_ID:
+            {
+                FT_Rf_Operation(ptrMsg);
+                break;
+            }
+#endif // #if !defined(__LTE_SM__)&&defined(__MTK_GL1_GSM__)
+            /********************************************
+             * BB test functionality
+             ********************************************/
+            case FT_REG_READ_ID:
+            {
+                FT_FtRegisterRead((ft_RegisterRead_req_T*)ptrMsg->local_para_ptr,FT_BaseBandReg);
+                break;
+            }
+            case FT_REG_WRITE_ID:
+            {
+                FT_FtRegisterWrite((ft_RegisterWrite_req_T*)ptrMsg->local_para_ptr,FT_BaseBandReg);
+                break;
+            }
+            case FT_PMIC_REG_READ_ID:
+            {
+                FT_FtPMICRegisterRead((ft_PMICRegisterRead_req_T*)ptrMsg->local_para_ptr,FT_PMICReg);
+                break;
+            }
+            case FT_PMIC_REG_WRITE_ID:
+            {
+                FT_FtPMICRegisterWrite((ft_PMICRegisterWrite_req_T*)ptrMsg->local_para_ptr,FT_PMICReg);
+                break;
+            }
+            case FT_ADC_GETMEADATA_ID:
+            {
+                FT_FtADC_GetMeaData((ft_FtADC_GetMeaData_req_T*)ptrMsg->local_para_ptr);
+                break;
+            }
+            /********************************************
+             * UL1 RF test functionality
+             ********************************************/
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#if !defined(__UL1_TASK_DISABLE__)
+            case FT_URF_TEST_REQ_ID:
+            {
+                FT_FtURfTestReq( ptrMsg );
+                break;
+            }
+#endif // #if !defined(__UL1_TASK_DISABLE__)
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+            /********************************************
+             *
+             *  NVRAM functionality
+             *
+             ********************************************/
+            case FT_NVRAM_GET_DISK_INFO_REQ_ID:
+            {
+                ilm_struct ilm_ptr;
+                FT_NVRAM_GET_DISK_INFO_CNF *ptr_loc_para;
+                // store nvram token id, because any of NVRAM command won't return immediately.
+                ft_gl_nvram_token = ft_header->token;
+                FT_ALLOC_OTHER_MSG(&ilm_ptr,sizeof(FT_NVRAM_GET_DISK_INFO_CNF));
+                ptr_loc_para=(FT_NVRAM_GET_DISK_INFO_CNF *)(ilm_ptr.local_para_ptr);
+                /* if ptr_ilm != NULL*/
+                ptr_loc_para->header.ft_msg_id=FT_NVRAM_GET_DISK_INFO_CNF_ID;
+#if defined(__MOD_NVRAM__)
+                if(nvram_get_disk_file_info(&(ptr_loc_para->diskfilesize), &(ptr_loc_para->freespace), &(ptr_loc_para->overhead))) {
+                    ptr_loc_para->status = 0;
+                }
+                else {
+                    ptr_loc_para->diskfilesize = 0;
+                    ptr_loc_para->freespace = 0;
+                    ptr_loc_para->overhead = 0;
+                    ptr_loc_para->status = 1;
+                }
+#endif // #if defined(__MOD_NVRAM__)
+                FT_SEND_MSG_TO_PC(&ilm_ptr);
+                break;
+            }
+            case FT_NVRAM_RESET_REQ_ID:
+            {
+                ilm_struct ptr_ilm;
+                nvram_reset_req_struct *ptr_loc_para;
+                // store nvram token id, because any of NVRAM command won't return immediately.
+                ft_gl_nvram_token = ft_header->token;
+                FT_ALLOC_OTHER_MSG(&ptr_ilm,sizeof( nvram_reset_req_struct));
+                /* if ptr_ilm != NULL*/
+                ptr_loc_para=(nvram_reset_req_struct *)(ptr_ilm.local_para_ptr);
+
+                if( ((ft_nvram_reset_req_struct_T*)ptrMsg->local_para_ptr)->reset_category == 0) // reset all
+                {
+
+                    ptr_loc_para->reset_category= NVRAM_RESET_ALL;
+                }
+                else if( ((ft_nvram_reset_req_struct_T*)ptrMsg->local_para_ptr)->reset_category == 3) // reset certain
+                {
+
+                    ptr_loc_para->reset_category= NVRAM_RESET_CERTAIN;
+                }
+                else if( ((ft_nvram_reset_req_struct_T*)ptrMsg->local_para_ptr)->reset_category == 4) // reset factory
+                {
+                    ptr_loc_para->reset_category= NVRAM_RESET_FACTORY;
+                }
+                else
+                {
+                    destroy_ilm(&ptr_ilm);
+                    break; // directly break!, Let PC side timeout!
+                }
+                ptr_loc_para->app_id = NVRAM_APP_RESERVED;
+                ptr_loc_para->LID=((ft_nvram_reset_req_struct_T*)ptrMsg->local_para_ptr)->file_idx;
+                FT_SEND_MSG(MOD_FT, MOD_NVRAM, PS_NVRAM_SAP, MSG_ID_NVRAM_RESET_REQ, &ptr_ilm);
+                break;
+            }
+            case FT_NVRAM_READ_REQ_ID:
+            {
+                ft_gl_nvram_token = ft_header->token;
+                FT_ReadFrom_NVRAM((ft_nvram_read_req_struct_T*)ptrMsg->local_para_ptr, 0);
+                break;
+            }
+            case FT_NVRAM_WRITE_REQ_ID:
+            {
+                ft_gl_nvram_token = ft_header->token;
+                FT_WriteTo_NVRAM((ft_nvram_write_req_struct_T*)ptrMsg->local_para_ptr, ptrMsg->peer_buff_ptr, 0);
+                break;
+            }
+            case FT_NVRAM_LOCK_REQ_ID:
+            {
+                ilm_struct ptr_ilm;
+                nvram_set_lock_req_struct *ptr_loc_para;
+                ft_nvram_lock_req_struct_T  *ptr_msg = (ft_nvram_lock_req_struct_T *)(ptrMsg->local_para_ptr);
+                // store nvram token id, because NVRAM command won't return immediately.
+                ft_gl_nvram_token = ft_header->token;
+                FT_ALLOC_OTHER_MSG(&ptr_ilm, sizeof(nvram_set_lock_req_struct));
+                /* if ptr_ilm != NULL*/
+                ptr_loc_para=(nvram_set_lock_req_struct *)(ptr_ilm.local_para_ptr);
+                // if OTP lock or NVRAM lock
+                if( NVRAM_LOCK_OTP == ptr_msg->lock_en ) {
+                    ptr_loc_para->lock_en = NVRAM_LOCK_OTP;
+                }
+                else {
+                    ptr_loc_para->lock_en = NVRAM_LOCK_ENABLE;
+                }
+                FT_SEND_MSG(MOD_FT, MOD_NVRAM, PS_NVRAM_SAP, MSG_ID_NVRAM_SET_LOCK_REQ, &ptr_ilm);
+                break;
+            }
+            /********************************************
+             *
+             *  FAT functionality
+             *
+             ********************************************/
+            case FT_FAT_OPERATION_ID:
+            {
+                FT_FAT_Operation((FT_FAT_OPERATION *)ptrMsg->local_para_ptr, ptrMsg->peer_buff_ptr);
+                break;
+            }
+            /********************************************
+             *
+             *  Version Info functionality
+             *
+             ********************************************/
+            case FT_VER_INFO_REQ_ID:
+            {
+                FT_GetVersionInfo();
+                break;
+            }
+            /********************************************
+             *
+             *  FT task test alive
+             *
+             ********************************************/
+            case FT_IS_ALIVE_REQ_ID:
+            {
+                FT_TestAlive();
+                break;
+            }
+            /********************************************
+             *
+             *  FT task Power Off
+             *
+             ********************************************/
+            case FT_POWER_OFF_REQ_ID:
+            {
+                FT_PowerOff();
+                break;
+            }
+            /********************************************
+             *
+             *  FT task utility command
+             *
+             ********************************************/
+            case FT_UTILITY_COMMAND_REQ_ID:
+            {
+                FT_UtilityCommand(ptrMsg);
+                break;
+            }
+            /********************************************
+             *
+             *  Misc utility command
+             *
+             ********************************************/
+            case FT_MISC_CMD_REQ_ID:
+            {
+                FT_MISC_Operation(ptrMsg);
+                break;
+            }
+            /********************************************
+             *
+             *  Misc EX utility command
+             *
+             ********************************************/
+            case FT_MISC_EX_CMD_REQ_ID:
+            {
+                FT_MISC_EX_Operation(ptrMsg);
+                break;
+            }
+            case FT_CUSTOM_REQ_ID:
+            {
+                // send message to FTC task
+                ft_gl_customer_token = ft_header->token;
+                FT_Custom_Operation(ptrMsg);
+                break;
+            }
+#if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+            case FT_AUX_REQ_ID:
+            {
+                if(KAL_TRUE == TL1_IS_3G_TDD_EXIST())  //20130206
+                {
+                // send message to FTA task
+                ft_gl_customer_token = ft_header->token;
+                FT_Aux_Operation(ptrMsg);
+            }
+            else
+            {
+                sprintf(g_FT_debug_buf, "[FT_DispatchMessage][FT_AUX_REQ_ID] HW TDD does not exist.");
+                tst_sys_trace(g_FT_debug_buf);
+            }
+            break;
+            }
+#endif // #if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+#if defined(__LTE_RAT__) || defined(L1_SIM)
+            case FT_ERF_TEST_REQ_ID:
+            {
+                FT_Erf_Operation(ptrMsg);
+                break;
+            }
+            case FT_PHY_TOOL_REQ_ID:
+            {
+                FT_PhyTool_Operation(ptrMsg);
+                break;
+            }
+#endif // #if defined(__LTE_RAT__)
+
+#if defined(__C2K_RAT__)
+            case FT_CRF_TEST_REQ_ID:
+            {
+                FT_Crf_Operation(ptrMsg);
+                break;
+            }
+#endif // #if defined(__C2K_RAT__)
+
+            case FT_MMRF_TEST_REQ_ID:
+            {
+                FT_Mmrf_Operation(ptrMsg);
+                break;
+            }
+
+		    case FT_NRF_TEST_REQ_ID:
+            {
+                FT_Nrf_Operation(ptrMsg);
+                break;
+            }
+#if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT) || defined(DUMMY_PROTOCOL)
+            case FT_L4_ATCMD_REQ_ID:
+            {
+                FT_L4_Operation(ptrMsg);
+                break;
+            }
+#endif // #if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT)
+
+            case FT_GET_SLA_STATUS_REQ_ID:
+            {
+                FT_GetSlaStatus();
+                break;
+            }
+
+            case FT_CHECK_SLA_VER_REQ_ID:
+            {
+                FT_CheckSlaVer((FT_CHECK_SLA_VER_REQ *)ptrMsg->local_para_ptr);
+                break;
+            }
+
+            case FT_GET_SLA_PARA_REQ_ID:
+            {
+                FT_GetSlaPara();
+                break;
+            }
+
+            case FT_VERIFY_SLA_RND_REQ_ID:
+            {
+                FT_VerifySla((FT_VERIFY_SLA_RND_REQ *)ptrMsg->local_para_ptr);
+                break;
+            }
+
+            default:
+            {
+                dhl_print(TRACE_INFO, DHL_USER_FLAG_NONE, MOD_FT,"[SLA] unknown msg id:%d", ft_header->ft_msg_id);
+                FT_SendDeniedMsgIdCnf(ft_header->ft_msg_id, FT_CNF_NOT_SUPPORTED);
+                break;
+            }
+        }
+    }
+    else if( (ptrMsg->src_mod_id == MOD_FTC) )
+    {
+        ft_gl_token = ft_gl_customer_token;
+        FT_Handle_FTC_CNF(ptrMsg);
+        ptrMsg->peer_buff_ptr=NULL; /* make sure the TST will release the mem*/
+    }
+
+#if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+    else if( (ptrMsg->src_mod_id == MOD_FTA) )
+    {
+        ft_gl_token = ft_gl_customer_token;
+        FT_Handle_FTA_CNF(ptrMsg);
+        ptrMsg->peer_buff_ptr=NULL; /* make sure the TST will release the mem*/
+    }
+#endif // #if defined(__UMTS_TDD128_MODE__) && defined(__AST_TL1_TDD__)
+#if defined(__MOD_NVRAM__)
+    else if( KAL_TRUE == FT_Nvram_IsModNvramRespnose(ptrMsg) )
+    {
+       switch (ptrMsg->msg_id)
+       {
+           case MSG_ID_NVRAM_WRITE_CNF:
+           {
+               nvram_write_cnf_struct*  msg_ptr = NULL;
+               ft_gl_token = ft_gl_nvram_token;
+               msg_ptr=(nvram_write_cnf_struct*)ptrMsg->local_para_ptr;
+               /* Check MMRF runtime update */
+               if( KAL_FALSE == FT_Mmrf_PollUpdateRuntimeReady() )
+               {
+                   hold_local_para(ptrMsg->local_para_ptr);
+                   FT_SEND_MSG(MOD_FT, MOD_FT, PS_NVRAM_SAP, MSG_ID_NVRAM_WRITE_CNF, ptrMsg);
+                   break;
+               }
+               FT_WriteTo_NVRAM_CNF(msg_ptr);
+               break;
+           }
+           case MSG_ID_NVRAM_RESET_CNF:
+           {
+               nvram_reset_cnf_struct*       msg_ptr;
+               ilm_struct                    ilm_ptr;
+               ft_nvram_reset_cnf_struct_T*  pMsg;
+               ft_gl_token = ft_gl_nvram_token;
+               msg_ptr=(nvram_reset_cnf_struct*)ptrMsg->local_para_ptr;
+               FT_ALLOC_MSG(&ilm_ptr, sizeof(ft_nvram_reset_cnf_struct_T));
+               pMsg=(ft_nvram_reset_cnf_struct_T*)ilm_ptr.local_para_ptr;
+               pMsg->header.ft_msg_id=FT_NVRAM_RESET_CNF_ID;
+               pMsg->status = msg_ptr->result;
+               FT_SEND_MSG_TO_PC(&ilm_ptr);
+               break;
+           }
+           case MSG_ID_NVRAM_SET_LOCK_CNF:
+           {
+               nvram_set_lock_cnf_struct*    msg_ptr;
+               ilm_struct                    ilm_ptr;
+               ft_nvram_lock_cnf_struct_T*   pMsg;
+               ft_gl_token = ft_gl_nvram_token;
+               msg_ptr=(nvram_set_lock_cnf_struct*)ptrMsg->local_para_ptr;
+               FT_ALLOC_MSG(&ilm_ptr, sizeof(ft_nvram_lock_cnf_struct_T));
+               pMsg=(ft_nvram_lock_cnf_struct_T*)ilm_ptr.local_para_ptr;
+               pMsg->header.ft_msg_id=FT_NVRAM_LOCK_CNF_ID;
+               pMsg->status = msg_ptr->result;
+               FT_SEND_MSG_TO_PC(&ilm_ptr);
+               break;
+           }
+#if defined(__MTK_INTERNAL__)
+           case MSG_ID_NVRAM_WRITE_IMEI_CNF:
+           {
+               nvram_write_imei_cnf_struct*    msg_ptr;
+               FT_MISC_CNF           misc_cnf;
+               msg_ptr=(nvram_write_imei_cnf_struct*)ptrMsg->local_para_ptr;
+               misc_cnf.type = FT_MISC_OP_SET_IMEI_VALUE;
+               if(msg_ptr->result == NVRAM_ERRNO_SUCCESS)
+               {
+                   misc_cnf.result.m_u2RecordIndex = msg_ptr->record_index;
+                   misc_cnf.status = FT_CNF_OK;
+               }
+               else
+               {
+                   misc_cnf.result.m_u2RecordIndex = msg_ptr->result;
+                   misc_cnf.status = FT_CNF_FAIL;
+               }
+               FT_MISC_SendCnf(&misc_cnf, NULL);
+               break;
+           }
+#endif  //#if defined(__MTK_INTERNAL__)
+           case MSG_ID_NVRAM_SDS_CNF:
+           case MSG_ID_NVRAM_BIN_REGION_CNF:
+           {
+               FT_MiscEx_NvramConfirmHandler(ptrMsg);
+               break;
+           }
+           default:
+               break;
+       }
+    }
+#endif // end of #if defined(__MOD_NVRAM__)
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#if !defined(__UL1_TASK_DISABLE__)
+    else if( (ptrMsg->src_mod_id == MOD_UL1) )
+    {
+        FT_UL1TST_SEND_CNF_BACK(ptrMsg);
+    }
+#endif // #if !defined(__UL1_TASK_DISABLE__)
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+    else if( (ptrMsg->src_mod_id == MOD_L1) )
+    {
+        FT_Rf_ConfirmHandler(ptrMsg);
+    }
+#endif // #if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+#ifndef SIM_NOT_PRESENT
+    else if( (ptrMsg->src_mod_id == MOD_SIM) && (ft_gl_sim_cmd_type != FT_MISC_OP_CHECK_GEMINI_PLUS_SIM_INSERTED))
+    {
+       switch (ptrMsg->msg_id)
+       {
+           case MSG_ID_SIM_RESET_CNF:
+           {
+               FT_MISC_CNF misc_cnf;
+               sim_reset_cnf_struct *msg_ptr;
+               msg_ptr=(sim_reset_cnf_struct*)ptrMsg->local_para_ptr;
+               misc_cnf.type = FT_MISC_OP_CHECK_SIM1_INSERTED;
+               misc_cnf.result.m_u1SIMInserted = (kal_bool)msg_ptr->is_sim_inserted; // get SIM inserted status here.  1:insert  , 0: not insert
+               misc_cnf.status = FT_CNF_OK;
+               FT_MISC_SendCnf(&misc_cnf, NULL);
+           }
+               break;
+           default:
+               break;
+       }
+    }
+#ifdef __GEMINI__
+    else if((ptrMsg->src_mod_id == MOD_SIM_2) && (ft_gl_sim_cmd_type != FT_MISC_OP_CHECK_GEMINI_PLUS_SIM_INSERTED))
+    {
+        switch (ptrMsg->msg_id)
+        {
+            case MSG_ID_SIM_RESET_CNF:
+            {
+                FT_MISC_CNF misc_cnf;
+                sim_reset_cnf_struct *msg_ptr;
+                msg_ptr=(sim_reset_cnf_struct*)ptrMsg->local_para_ptr;
+                misc_cnf.type = FT_MISC_OP_CHECK_SIM2_INSERTED;
+                misc_cnf.result.m_u1SIMInserted = (kal_bool)msg_ptr->is_sim_inserted; // get SIM inserted status here.  1:insert  , 0: not insert
+                misc_cnf.status = FT_CNF_OK;
+                FT_MISC_SendCnf(&misc_cnf, NULL);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+#endif // __GEMINI__
+#ifdef GEMINI_PLUS
+    else if((ptrMsg->src_mod_id >= MOD_SIM) && (ptrMsg->src_mod_id < MOD_SIM + GEMINI_PLUS) &&
+            (ft_gl_sim_cmd_type == FT_MISC_OP_CHECK_GEMINI_PLUS_SIM_INSERTED))
+    {
+        switch (ptrMsg->msg_id)
+        {
+            case MSG_ID_SIM_RESET_CNF:
+            {
+                FT_MISC_CNF misc_cnf;
+                sim_reset_cnf_struct *msg_ptr;
+                msg_ptr=(sim_reset_cnf_struct*)ptrMsg->local_para_ptr;
+                misc_cnf.type = FT_MISC_OP_CHECK_GEMINI_PLUS_SIM_INSERTED;
+                misc_cnf.result.m_u1SIMInserted = (kal_bool)msg_ptr->is_sim_inserted; // get SIM inserted status here.  1:insert  , 0: not insert
+                misc_cnf.status = FT_CNF_OK;
+                FT_MISC_SendCnf(&misc_cnf, NULL);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+#endif // GEMINI_PLUS
+#endif // SIM_NOT_PRESENT
+#if defined(__LTE_RAT__)
+    else if( MOD_EL1== ptrMsg->src_mod_id )
+    {
+        FT_Erf_ConfirmHandler(ptrMsg);
+    }
+#endif // #if defined(__LTE_RAT__)
+
+#if defined(__C2K_RAT__)
+    else if( MOD_CL1TST == ptrMsg->src_mod_id )
+    {
+        FT_Crf_ConfirmHandler(ptrMsg);
+    }
+#endif // #if defined(__C2K_RAT__)
+
+    else if( MOD_MMRF_XL1TST == ptrMsg->src_mod_id )
+    {
+        FT_Mmrf_ConfirmHandler(ptrMsg);
+    }
+	
+#if defined(__MD97__)
+	else if( MOD_NL1 == ptrMsg->src_mod_id )
+    {
+        FT_Nrf_ConfirmHandler(ptrMsg);
+    }
+#endif // #if !defined(__MD97__)
+
+#if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT) || defined(DUMMY_PROTOCOL)
+    else if( MOD_L4C == ptrMsg->src_mod_id )
+    {
+        FT_L4_Operation(ptrMsg);
+    }
+#endif // #if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT) 
+
+}
+#else
+void FT_DispatchMessage(ilm_struct* ptrMsg)
+{
+    FT_H  *ft_header;
+    ft_header=(FT_H *)(ptrMsg->local_para_ptr);
+    /* process messages with specific message ID */
+    switch(ptrMsg->msg_id)
+    {
+        case MSG_ID_MMRF_UPDATE_RUNTIME_CNF:
+        {
+            FT_Mmrf_UpdateRuntimeConfirmHandler(ptrMsg);
+            return;
+        }
+        default:
+            break;
+    }
+    /* process message with specific source module ID */
+#if !defined(__DHL_MODULE__)
+    if(ptrMsg->src_mod_id == MOD_TST_READER)
+#else
+    if(ptrMsg->src_mod_id == MOD_DHL)
+#endif // #if !defined(__DHL_MODULE__)
+    {
+        ft_gl_token=ft_header->token;
+        switch (ft_header->ft_msg_id)
+        {
+            /********************************************
+             * L1 RF test functionality
+             ********************************************/
+#if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+            case FT_RF_TEST_REQ_ID:
+            {
+                FT_Rf_Operation(ptrMsg);
+                break;
+            }
+#endif // #if !defined(__LTE_SM__)&&defined(__MTK_GL1_GSM__)
+            /********************************************
+             * UL1 RF test functionality
+             ********************************************/
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#if !defined(__UL1_TASK_DISABLE__)
+            case FT_URF_TEST_REQ_ID:
+            {
+                FT_FtURfTestReq( ptrMsg );
+                break;
+            }
+#endif // #if !defined(__UL1_TASK_DISABLE__)
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+            /********************************************
+             *
+             *  Version Info functionality
+             *
+             ********************************************/
+            case FT_VER_INFO_REQ_ID:
+            {
+                FT_GetVersionInfo();
+                break;
+            }
+            /********************************************
+             *
+             *  FT task test alive
+             *
+             ********************************************/
+            case FT_IS_ALIVE_REQ_ID:
+            {
+                FT_TestAlive();
+                break;
+            }
+            /********************************************
+             *
+             *  FT task utility command
+             *
+             ********************************************/
+            case FT_UTILITY_COMMAND_REQ_ID:
+            {
+                FT_UtilityCommand(ptrMsg);
+                break;
+            }
+#if defined(__LTE_RAT__) || defined(L1_SIM)
+            case FT_ERF_TEST_REQ_ID:
+            {
+                FT_Erf_Operation(ptrMsg);
+                break;
+            }
+#endif // #if defined(__LTE_RAT__)
+            case FT_MMRF_TEST_REQ_ID:
+            {
+                FT_Mmrf_Operation(ptrMsg);
+                break;
+            }
+
+		    case FT_NRF_TEST_REQ_ID:
+            {
+                FT_Nrf_Operation(ptrMsg);
+                break;
+            }
+			
+#if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT) || defined(DUMMY_PROTOCOL)
+            case FT_L4_ATCMD_REQ_ID:
+            {
+                FT_L4_Operation(ptrMsg);
+            }
+#endif // #if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT)
+            default:
+            break;
+        }
+    }
+#if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#if !defined(__UL1_TASK_DISABLE__)
+    else if( (ptrMsg->src_mod_id == MOD_UL1) )
+    {
+        FT_UL1TST_SEND_CNF_BACK(ptrMsg);
+    }
+#endif // #if !defined(__UL1_TASK_DISABLE__)
+#endif // #if defined(__UMTS_RAT__) && defined(__MTK_UL1_FDD__)
+#if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+    else if( (ptrMsg->src_mod_id == MOD_L1) )
+    {
+        FT_Rf_ConfirmHandler(ptrMsg);
+    }
+#endif // #if !defined(L1_NOT_PRESENT) && !defined(__L1_TASK_DISABLE__) && !defined(DUMMYL1)
+#if defined(__LTE_RAT__)
+    else if( MOD_EL1== ptrMsg->src_mod_id )
+    {
+        FT_Erf_ConfirmHandler(ptrMsg);
+    }
+#endif // #if defined(__LTE_RAT__)
+
+    else if( MOD_MMRF_XL1TST == ptrMsg->src_mod_id )
+    {
+        FT_Mmrf_ConfirmHandler(ptrMsg);
+    }
+#if defined(__MD97__)
+	else if( MOD_NL1 == ptrMsg->src_mod_id )
+    {
+        FT_Nrf_ConfirmHandler(ptrMsg);
+    }
+#endif // #if !defined(__MD97__)
+#if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT) || defined(DUMMY_PROTOCOL)
+    else if( MOD_L4C == ptrMsg->src_mod_id )
+    {
+        FT_L4_Operation(ptrMsg);
+    }
+#endif // #if !defined(__L4_TASK_DISABLE__) && !defined(L4_NOT_PRESENT) 
+}
+#endif // #ifndef L1_SIM
+/*******************************************************************************
+ * FUNCTION
+ *   FT_Task
+ *
+ * DESCRIPTION
+ *   Entry point for the factory testing task. The function performs initialisation,
+ *   then sits in an infinite loop reading messages or reports and dispatching
+ *   them.
+ *
+ * CALLS
+ *
+ * PARAMETERS
+ *   None
+ *
+ * RETURNS
+ *   None
+ *
+ * GLOBALS AFFECTED
+ *   None
+ *******************************************************************************/
+
+#define META_Version_Check_Fail  0
+#define META_Version_Check_Required 0
+
+void FT_Task(task_entry_struct * task_entry_ptr)
+{
+    ilm_struct current_ilm;
+    FT_Initialization(task_entry_ptr);
+    while ( 1 )
+    {
+#ifndef L1_SIM
+		msg_receive_extq(&current_ilm );
+#else
+		gs_read_message(MOD_FT, &current_ilm, sizeof(current_ilm), KAL_TRUE);
+#endif //#ifndef L1_SIM
+        FT_DispatchMessage(&current_ilm );
+        destroy_ilm(&current_ilm);
+    }
+}
+kal_eventgrpid MMRF_UPDATE_RUNTIME_EVENT;
+kal_bool FT_Init(void)
+{
+    MMRF_UPDATE_RUNTIME_EVENT = kal_create_event_group("MMRF_UPD");
+    return KAL_TRUE;
+}
diff --git a/mcu/middleware/meta/ft/src/ft_mem.c b/mcu/middleware/meta/ft/src/ft_mem.c
new file mode 100644
index 0000000..4c46a86
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_mem.c
@@ -0,0 +1,138 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_mem.c
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   Factory testing memory management functions
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ *              HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+/*************************************************************************
+ * Include Statements for KAL
+ *************************************************************************/
+#include "kal_general_types.h"
+#include "kal_public_defs.h"
+#include "kal_public_api.h"
+/*************************************************************************
+ * Include Statements FT
+ *************************************************************************/
+#include "ft_mem.h"
+#include "meta_customize.h"
+/*************************************************************************
+ * FT memory global variable
+ *************************************************************************/
+KAL_ADM_ID           ft_ext_mem_pool_id = 0;
+void FtInitMemoryPool(void)
+{
+    ft_ext_mem_pool_id = kal_adm_create(
+        Custom_META_GetCustomMemoryPool(),
+        Custom_META_GetCustomMemoryPoolSize(),
+        (kal_uint32*)Custom_META_GetCustomMemoryPoolArrangement(),
+        KAL_FALSE
+        );
+}
+void* FtAllocExtMemory(kal_uint32 size)
+{
+    if(ft_ext_mem_pool_id > 0)
+    {
+        return kal_adm_alloc(ft_ext_mem_pool_id, size);
+    }
+    else
+    {
+        return NULL;
+    }
+}
+void FtFreeExtMemory(void* ptr)
+{
+    if(ft_ext_mem_pool_id > 0)
+    {
+        kal_adm_free(ft_ext_mem_pool_id, ptr);
+    }
+}
+kal_uint32 FtGetLeftExtMemory(void)
+{
+    if(ft_ext_mem_pool_id > 0)
+    {
+        return kal_adm_get_max_alloc_size(ft_ext_mem_pool_id);
+    }
+    else
+    {
+        return 0;
+    }
+}
diff --git a/mcu/middleware/meta/ft/src/ft_report.c b/mcu/middleware/meta/ft/src/ft_report.c
new file mode 100644
index 0000000..71b4720
--- /dev/null
+++ b/mcu/middleware/meta/ft/src/ft_report.c
@@ -0,0 +1,149 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ft_report.c
+ *
+ * Project:
+ * --------
+ *   MTK6208
+ *
+ * Description:
+ * ------------
+ *   Functions to handle L1 report
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+#include "ft_msg.h"
+#include "ft_private.h"
+#include "ft_report.h"
+
diff --git a/mcu/middleware/meta/ftc/ftc_main.c b/mcu/middleware/meta/ftc/ftc_main.c
new file mode 100644
index 0000000..d85ccf3
--- /dev/null
+++ b/mcu/middleware/meta/ftc/ftc_main.c
@@ -0,0 +1,281 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ *   ftc_main.c
+ *
+ * Project:
+ * --------
+ *   Maui_Software
+ *
+ * Description:
+ * ------------
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *============================================================================
+ *             HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ * removed!
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+/*************************************************************************
+* Include Statements for KAL
+ *************************************************************************/
+#include "kal_public_defs.h" //MSBB change #include "stack_common.h"
+#include "kal_public_defs.h" //MSBB change #include "stack_msgs.h"
+#include "task_config.h"
+#include "syscomp_config.h"
+#include "md_mw_sap.h"
+#include "ft_msgid.h"
+/*************************************************************************
+* Include Statements for MAUI
+ *************************************************************************/
+//MSBB remove #include "fctycomp_config.h"
+#include "ft_msg_common.h"
+#include "ftc_msg.h"
+#include "ftc_private.h"
+// added in RHR first round
+#include "kal_public_defs.h" //MSBB change #include "stack_config.h"
+#include "kal_general_types.h"
+#include "kal_public_api.h"
+#include "kal_public_defs.h"
+/*************************************************************************
+* Function declaration
+ *************************************************************************/
+void FTC_Task(task_entry_struct * task_entry_ptr);
+
+//#pragma arm section zidata = "NONCACHEDZI",  rwdata = "NONCACHEDRW"
+//#pragma arm section zidata, rwdata
+
+/*************************************************************************
+* FUNCTION
+*  ft_create
+*
+* DESCRIPTION
+*
+* PARAMETERS
+*
+* RETURNS
+*  None
+*
+* GLOBALS AFFECTED
+*
+*************************************************************************/
+kal_bool
+ftc_create(comptask_handler_struct **handle)
+{
+    static const comptask_handler_struct ftc_handler_info =
+    {
+        FTC_Task,  /* task entry function */
+        NULL,  /* task initialization function */
+        NULL   /* task configuration function */
+    };
+    *handle = (comptask_handler_struct *)&ftc_handler_info;
+    return KAL_TRUE;
+}
+/*******************************************************************************
+*
+*  Local Functions
+*
+*******************************************************************************/
+void FTC_ALLOC_MSG(ilm_struct* ilm_ptr, kal_uint16 size)
+{
+    ilm_ptr->local_para_ptr = NULL;
+    ilm_ptr->peer_buff_ptr = NULL;
+    if( 0 < size ) {
+        if( NULL == (ilm_ptr->local_para_ptr=construct_local_para(size, TD_RESET)) ) {
+            ASSERT(0); // assert it!
+        }
+    }
+}
+void FTC_SEND_MSG(module_type  src_mod,
+                  module_type  dest_mod,
+                  sap_type  sap,
+                  msg_type  msg,
+                  ilm_struct  *ilm_ptr)
+{
+    msg_send6(src_mod, dest_mod, sap, msg, ilm_ptr->local_para_ptr, ilm_ptr->peer_buff_ptr);
+}
+void FTC_DispatchMessage(ilm_struct* ptrMsg)
+{
+    if( (ptrMsg->src_mod_id == MOD_FT) )
+    {
+        if(ptrMsg->peer_buff_ptr == NULL)
+        {
+            return;
+        }
+        switch (ptrMsg->msg_id)
+        {
+            case MSG_ID_FTC_BASIC_REQ:
+            {
+                // do the echo operation (This is the sample code, please extend the customization in this switch case
+                ftc_basic_cnf_struct *ftc_ptr_loc_para;
+                ilm_struct  ilm_ptr;
+                FTC_ALLOC_MSG(&ilm_ptr, sizeof(ftc_basic_cnf_struct));
+                ftc_ptr_loc_para=(ftc_basic_cnf_struct *)(ilm_ptr.local_para_ptr);
+                ftc_ptr_loc_para->status = FTC_CNF_OK;
+                hold_peer_buff(ptrMsg->peer_buff_ptr);
+                ilm_ptr.peer_buff_ptr = ptrMsg->peer_buff_ptr;
+                FTC_SEND_MSG(MOD_FTC ,MOD_FT, FTC_FT_SAP, MSG_ID_FTC_BASIC_CNF, &ilm_ptr);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    else if( (ptrMsg->src_mod_id == MOD_NVRAM) )
+    {
+    }
+}
+/*******************************************************************************
+* FUNCTION
+*   FT_Task
+*
+* DESCRIPTION
+*   Entry point for the factory testing task. The function performs initialisation,
+*   then sits in an infinite loop reading messages or reports and dispatching
+*   them.
+*
+* CALLS
+*
+* PARAMETERS
+*   None
+*
+* RETURNS
+*   None
+*
+* GLOBALS AFFECTED
+*   None
+*******************************************************************************/
+void FTC_Task(task_entry_struct * task_entry_ptr)
+{
+    ilm_struct current_ilm;
+    while ( 1 )
+    {
+        msg_receive_extq(&current_ilm);
+        FTC_DispatchMessage(&current_ilm);
+        destroy_ilm(&current_ilm);
+    }
+}
diff --git a/mcu/middleware/meta/ftc/ftc_private.h b/mcu/middleware/meta/ftc/ftc_private.h
new file mode 100644
index 0000000..39bf537
--- /dev/null
+++ b/mcu/middleware/meta/ftc/ftc_private.h
@@ -0,0 +1,80 @@
+/*****************************************************************************
+*  Copyright Statement:
+*  --------------------
+*  This software is protected by Copyright and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2005
+*
+*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
+*
+*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*******************************************************************************
+*  Modification Notice:
+*  --------------------------
+*  This software is modified by MediaTek Inc. and the information contained
+*  herein is confidential. The software may not be copied and the information
+*  contained herein may not be used or disclosed except with the written
+*  permission of MediaTek Inc. (C) 2001
+*
+*******************************************************************************/
+
+/*******************************************************************************
+ * Filename:
+ * ---------
+ *   ftc_private.h
+ *
+ * Project:
+ * --------
+ *   MAUI
+ *
+ * Description:
+ * ------------
+ *   FTC private stuff
+ *
+ * Author:
+ * -------
+ * -------
+ *
+ *==============================================================================
+ * 				HISTORY
+ * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * removed!
+ * removed!
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
+ *==============================================================================
+ *******************************************************************************/
+
+#ifndef FTC_PRIVATE_H
+#define FTC_PRIVATE_H
+
+#define FTC_CNF_OK   0
+#define FTC_CNF_FAIL 1
+
+#endif