bool use_reinsert;
        bool want_ingress;
        bool is_redirect;
+       bool expects_nh;
        int m_eaction;
        int mac_len;
+       bool at_nh;
 
        rec_level = __this_cpu_inc_return(mirred_rec_level);
        if (unlikely(rec_level > MIRRED_RECURSION_LIMIT)) {
                        goto out;
        }
 
-       /* If action's target direction differs than filter's direction,
-        * and devices expect a mac header on xmit, then mac push/pull is
-        * needed.
-        */
        want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
-       if (skb_at_tc_ingress(skb) != want_ingress && m_mac_header_xmit) {
-               if (!skb_at_tc_ingress(skb)) {
-                       /* caught at egress, act ingress: pull mac */
-                       mac_len = skb_network_header(skb) - skb_mac_header(skb);
+
+       expects_nh = want_ingress || !m_mac_header_xmit;
+       at_nh = skb->data == skb_network_header(skb);
+       if (at_nh != expects_nh) {
+               mac_len = skb_at_tc_ingress(skb) ? skb->mac_len :
+                         skb_network_header(skb) - skb_mac_header(skb);
+               if (expects_nh) {
+                       /* target device/action expect data at nh */
                        skb_pull_rcsum(skb2, mac_len);
                } else {
-                       /* caught at ingress, act egress: push mac */
-                       skb_push_rcsum(skb2, skb->mac_len);
+                       /* target device/action expect data at mac */
+                       skb_push_rcsum(skb2, mac_len);
                }
        }