diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 4beea5b..b96d12d 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -2475,6 +2475,7 @@ dp_netdev_flow_offload_put(struct dp_flow_offload_item *offload)
     info.mod_flag = offload->mod_flag;
     info.nat_action = offload->nat_action;
     info.ct_enable = false;
+    info.group_id = 0;
 
     port = netdev_ports_get(in_port, dpif_type_str);
     if (!port) {
@@ -2587,14 +2588,17 @@ queue_netdev_flow_del(struct dp_netdev_pmd_thread *pmd,
 /* return value show if this flow should be offloaded*/
 static bool
 parse_netdev_flow_put(struct match *match, const struct nlattr *actions,
-                      size_t actions_len,  struct nat_action_info_t *nat_action,
-                      uint8_t mod_flag)
+                      size_t actions_len,  struct nat_action_info_t *nat_action
+                      )
 {
     bool action_has_recirc = false;
     bool action_has_set = false;
+    bool action_has_dnat = false;
+    bool action_has_ct = false;
     bool ret = false;
     struct nlattr *nla;
     size_t left;
+    uint32_t mod_flag = match->flow.skb_priority;
 
     /* filter non IP pkt out */
     if ((match->flow.dl_type != htons(ETH_TYPE_IP)) &&
@@ -2612,6 +2616,7 @@ parse_netdev_flow_put(struct match *match, const struct nlattr *actions,
             const struct nlattr *b;
             unsigned int ct_left;
 
+            action_has_ct = true;
             if (nat_action == NULL) {
                 continue;
             }
@@ -2636,6 +2641,8 @@ parse_netdev_flow_put(struct match *match, const struct nlattr *actions,
                             nat_action->nat_action |=
                                 ((sub_type_nest == OVS_NAT_ATTR_SRC)
                                     ? NAT_ACTION_SRC : NAT_ACTION_DST);
+                            action_has_dnat = (sub_type_nest == OVS_NAT_ATTR_DST)?
+                                               true : action_has_dnat;
                             break;
                         case OVS_NAT_ATTR_IP_MIN:
                             memcpy(&(nat_action->min_addr),
@@ -2711,12 +2718,23 @@ parse_netdev_flow_put(struct match *match, const struct nlattr *actions,
         goto out;
     }
 
+    /*if only has one conntrack action, won't need to offload */
+    if ((actions_len == 1) && action_has_ct) {
+        goto out;
+    }
     /* no mod_flag means: 1. no set action at all
      *                    2. set action but is the first translated pkt
+     *                    3. nat action then set mac/ttl: such as DNAT
      * For 1 , only established pkt should try to offload
      * For 2 , still established pkt should be offload
-     * so in this condition: we cannot offload non-est pkt
+     * For 3 , we don't care ct_state,and try to offload
+     * so for 1 && 2: we cannot offload non-est pkt
+     * for 3, we try to offload non-est pkt
      */
+    if (action_has_dnat) {
+        ret = true;
+        goto out;
+    }
     if (match->wc.masks.ct_state &&
         !(match->wc.masks.ct_state & match->flow.ct_state & CS_ESTABLISHED) ){
         goto out;
@@ -2746,7 +2764,7 @@ out:
 static void
 queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
                       struct dp_netdev_flow *flow, struct match *match,
-                      const struct nlattr *actions, size_t actions_len,uint8_t mod_flag)
+                      const struct nlattr *actions, size_t actions_len)
 {
     struct dp_flow_offload_item *offload;
     int op;
@@ -2755,10 +2773,20 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
     if (!netdev_is_flow_api_enabled()) {
         return;
     }
-    if (!parse_netdev_flow_put(match,actions,actions_len,&nat_action,mod_flag)) {
+    if (!parse_netdev_flow_put(match,actions,actions_len,&nat_action)) {
         return;
     }
 
+    VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:recirc %x mod %x \n", match->flow.recirc_id,
+             match->flow.skb_priority);
+    VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:nw_src %x ct_nw_src %x \n",
+             ntohl(match->flow.nw_src), ntohl(match->flow.ct_nw_src));
+    VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:nat action %x \n",
+             nat_action.nat_action);
+    VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:nat min addr %x \n",
+             ntohl(nat_action.min_addr.ipv4));
+    VLOG_DBG("TIMO DBG: in queue_netdev_flow_put:nat max addr %x \n",
+             ntohl(nat_action.max_addr.ipv4));
     if (ovsthread_once_start(&offload_thread_once)) {
         xpthread_cond_init(&dp_flow_offload.cond, NULL);
         ovs_thread_create("dp_netdev_flow_offload",
@@ -2776,7 +2804,7 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
     offload->actions = xmalloc(actions_len);
     memcpy(offload->actions, actions, actions_len);
     offload->actions_len = actions_len;
-    offload->mod_flag = mod_flag;
+    offload->mod_flag = match->flow.skb_priority;
     offload->nat_action = nat_action;
 
     dp_netdev_append_flow_offload(offload);
@@ -3538,8 +3566,7 @@ dp_netdev_get_mega_ufid(const struct match *match, ovs_u128 *mega_ufid)
 static struct dp_netdev_flow *
 dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
                    struct match *match, const ovs_u128 *ufid,
-                   const struct nlattr *actions, size_t actions_len,
-                   uint8_t mod_flag)
+                   const struct nlattr *actions, size_t actions_len)
     OVS_REQUIRES(pmd->flow_mutex)
 {
     struct ds extra_info = DS_EMPTY_INITIALIZER;
@@ -3604,7 +3631,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
 
     /*Don't try to offload flows that has been offloaded failed */
     if (megaflow_to_offload_st_find(&flow->ufid) == false) {
-        queue_netdev_flow_put(pmd, flow, match, actions, actions_len,mod_flag);
+        queue_netdev_flow_put(pmd, flow, match, actions, actions_len);
     }
 
     if (OVS_UNLIKELY(!VLOG_DROP_DBG((&upcall_rl)))) {
@@ -3675,7 +3702,7 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
         if (put->flags & DPIF_FP_CREATE) {
             if (cmap_count(&pmd->flow_table) < MAX_FLOWS) {
                 dp_netdev_flow_add(pmd, match, ufid, put->actions,
-                                   put->actions_len,(uint8_t)0);
+                                   put->actions_len);
                 error = 0;
             } else {
                 error = EFBIG;
@@ -3697,7 +3724,7 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
             /*Don't try to offload flows that has been offloaded failed */
             if (megaflow_to_offload_st_find(&netdev_flow->ufid) == false) {
                 queue_netdev_flow_put(pmd, netdev_flow, match,
-                                      put->actions, put->actions_len,(uint8_t)0);
+                                      put->actions, put->actions_len);
             }
 
             if (stats) {
@@ -6966,7 +6993,6 @@ handle_packet_upcall(struct dp_netdev_pmd_thread *pmd,
     ovs_u128 ufid;
     int error;
     uint64_t cycles = cycles_counter_update(&pmd->perf_stats);
-    uint8_t mod_flag;
 
     match.tun_md.valid = false;
     miniflow_expand(&key->mf, &match.flow);
@@ -6999,10 +7025,6 @@ handle_packet_upcall(struct dp_netdev_pmd_thread *pmd,
      * the actions.  Otherwise, if there are any slow path actions,
      * we'll send the packet up twice. */
 
-    /* get mod_flag before execute action, so can set group_id=0 for first
-     * loopbacked pkt with set action
-     */
-    mod_flag = packet->md.mod_flag;
     dp_packet_batch_init_packet(&b, packet);
     dp_netdev_execute_actions(pmd, &b, true, &match.flow,
                               actions->data, actions->size);
@@ -7022,8 +7044,7 @@ handle_packet_upcall(struct dp_netdev_pmd_thread *pmd,
         if (OVS_LIKELY(!netdev_flow)) {
             netdev_flow = dp_netdev_flow_add(pmd, &match, &ufid,
                                              add_actions->data,
-                                             add_actions->size,
-                                             mod_flag);
+                                             add_actions->size);
         }
         ovs_mutex_unlock(&pmd->flow_mutex);
         uint32_t hash = dp_netdev_flow_hash(&netdev_flow->ufid);
@@ -7651,6 +7672,13 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
                         nat_action_info.nat_action |=
                             ((sub_type_nest == OVS_NAT_ATTR_SRC)
                                 ? NAT_ACTION_SRC : NAT_ACTION_DST);
+                        /*For DNAT, we should also set mod_flag */
+                        if (sub_type_nest == OVS_NAT_ATTR_DST) {
+                            struct dp_packet *packet;
+                            DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
+                                packet->md.skb_priority |= 1 << SET_ACTION_SET ;
+                            }
+                        }
                         break;
                     case OVS_NAT_ATTR_IP_MIN:
                         memcpy(&nat_action_info.min_addr,
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index d4a80bb..12aa5c1 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -507,7 +507,7 @@ dump_flow_action(struct ds *s, const struct rte_flow_action *actions)
          
         if (vlan_tci) {
             ds_put_format(s, "rte flow vlan-push action:\n");
-            ds_put_format(s, "vlan-encap: tpid=%"PRIu16"\n",ntohs(vlan_tci->ethertype));
+            ds_put_format(s, "vlan-encap: tpid=0x%06x\n",ntohs(vlan_tci->ethertype));
         } else {
             ds_put_format(s, "vlan-encap: null\n");
         }
@@ -1322,6 +1322,7 @@ add_ipv4_nat_action(struct flow_actions *actions,
                     struct nat_action_info_t *nat_action)
 {
 
+    VLOG_DBG("TIMO DBG: in add_ipv4_nat_action");
     if (nat_action->nat_action & NAT_ACTION_SRC) {
         __be32 ipv4_src;
 
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index b3cb71b..559f260 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -955,14 +955,14 @@ odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
         case OVS_ACTION_ATTR_SET:
             DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
                 odp_execute_set_action(packet, nl_attr_get(a));
-                packet->md.mod_flag |= 1 << SET_ACTION_SET ;
+                packet->md.skb_priority |= 1 << SET_ACTION_SET ;
             }
             break;
 
         case OVS_ACTION_ATTR_SET_MASKED:
             DP_PACKET_BATCH_FOR_EACH(i, packet, batch) {
                 odp_execute_masked_set_action(packet, nl_attr_get(a));
-                packet->md.mod_flag |= 1 << SET_ACTION_SET ;
+                packet->md.skb_priority |= 1 << SET_ACTION_SET ;
             }
             break;
 
diff --git a/lib/packets.h b/lib/packets.h
index 4eafaca..84c554e 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -101,7 +101,9 @@ PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0,
                                    received from the wire. */
     uint32_t dp_hash;           /* hash value computed by the recirculation
                                    action. */
-    uint32_t skb_priority;      /* Packet priority for QoS. */
+    uint32_t skb_priority;      /* Packet priority for QoS.
+                                 * together with mod_flag
+                                 */
     uint32_t pkt_mark;          /* Packet mark. */
     uint8_t  ct_state;          /* Connection state. */
     bool ct_orig_tuple_ipv6;
@@ -112,7 +114,6 @@ PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0,
     struct conn *conn;          /* Cached conntrack connection. */
     bool reply;                 /* True if reply direction. */
     bool icmp_related;          /* True if ICMP related. */
-    uint8_t  mod_flag;          /* Modify flag */
 
 );
 
@@ -170,7 +171,6 @@ pkt_metadata_init(struct pkt_metadata *md, odp_port_t port)
     md->tunnel.ipv6_dst = in6addr_any;
     md->in_port.odp_port = port;
     md->conn = NULL;
-    md->mod_flag = 0;
 }
 
 /* This function prefetches the cachelines touched by pkt_metadata_init()
