return skb;
 }
+
+static struct netdev_queue *
+netdev_tx_queue_mapping(struct net_device *dev, struct sk_buff *skb)
+{
+       int qm = skb_get_queue_mapping(skb);
+
+       return netdev_get_tx_queue(dev, netdev_cap_txqueue(dev, qm));
+}
+
+static bool netdev_xmit_txqueue_skipped(void)
+{
+       return __this_cpu_read(softnet_data.xmit.skip_txqueue);
+}
+
+void netdev_xmit_skip_txqueue(bool skip)
+{
+       __this_cpu_write(softnet_data.xmit.skip_txqueue, skip);
+}
+EXPORT_SYMBOL_GPL(netdev_xmit_skip_txqueue);
 #endif /* CONFIG_NET_EGRESS */
 
 #ifdef CONFIG_XPS
 static int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev)
 {
        struct net_device *dev = skb->dev;
-       struct netdev_queue *txq;
+       struct netdev_queue *txq = NULL;
        struct Qdisc *q;
        int rc = -ENOMEM;
        bool again = false;
                        if (!skb)
                                goto out;
                }
+
+               netdev_xmit_skip_txqueue(false);
+
                nf_skip_egress(skb, true);
                skb = sch_handle_egress(skb, &rc, dev);
                if (!skb)
                        goto out;
                nf_skip_egress(skb, false);
+
+               if (netdev_xmit_txqueue_skipped())
+                       txq = netdev_tx_queue_mapping(dev, skb);
        }
 #endif
        /* If device/qdisc don't need skb->dst, release it right now while
        else
                skb_dst_force(skb);
 
-       txq = netdev_core_pick_tx(dev, skb, sb_dev);
+       if (!txq)
+               txq = netdev_core_pick_tx(dev, skb, sb_dev);
+
        q = rcu_dereference_bh(txq->qdisc);
 
        trace_net_dev_queue(skb);
 
                }
        }
        if (params->flags & SKBEDIT_F_QUEUE_MAPPING &&
-           skb->dev->real_num_tx_queues > params->queue_mapping)
+           skb->dev->real_num_tx_queues > params->queue_mapping) {
+#ifdef CONFIG_NET_EGRESS
+               netdev_xmit_skip_txqueue(true);
+#endif
                skb_set_queue_mapping(skb, params->queue_mapping);
+       }
        if (params->flags & SKBEDIT_F_MARK) {
                skb->mark &= ~params->mask;
                skb->mark |= params->mark & params->mask;