diff options
-rw-r--r-- | net/core/dev.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 8092f01713fb..8eb50e2292fb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1880,6 +1880,17 @@ static int dev_gso_segment(struct sk_buff *skb) | |||
1880 | return 0; | 1880 | return 0; |
1881 | } | 1881 | } |
1882 | 1882 | ||
1883 | /* | ||
1884 | * Try to orphan skb early, right before transmission by the device. | ||
1885 | * We cannot orphan skb if tx timestamp is requested, since | ||
1886 | * drivers need to call skb_tstamp_tx() to send the timestamp. | ||
1887 | */ | ||
1888 | static inline void skb_orphan_try(struct sk_buff *skb) | ||
1889 | { | ||
1890 | if (!skb_tx(skb)->flags) | ||
1891 | skb_orphan(skb); | ||
1892 | } | ||
1893 | |||
1883 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | 1894 | int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, |
1884 | struct netdev_queue *txq) | 1895 | struct netdev_queue *txq) |
1885 | { | 1896 | { |
@@ -1904,23 +1915,10 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | |||
1904 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) | 1915 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) |
1905 | skb_dst_drop(skb); | 1916 | skb_dst_drop(skb); |
1906 | 1917 | ||
1918 | skb_orphan_try(skb); | ||
1907 | rc = ops->ndo_start_xmit(skb, dev); | 1919 | rc = ops->ndo_start_xmit(skb, dev); |
1908 | if (rc == NETDEV_TX_OK) | 1920 | if (rc == NETDEV_TX_OK) |
1909 | txq_trans_update(txq); | 1921 | txq_trans_update(txq); |
1910 | /* | ||
1911 | * TODO: if skb_orphan() was called by | ||
1912 | * dev->hard_start_xmit() (for example, the unmodified | ||
1913 | * igb driver does that; bnx2 doesn't), then | ||
1914 | * skb_tx_software_timestamp() will be unable to send | ||
1915 | * back the time stamp. | ||
1916 | * | ||
1917 | * How can this be prevented? Always create another | ||
1918 | * reference to the socket before calling | ||
1919 | * dev->hard_start_xmit()? Prevent that skb_orphan() | ||
1920 | * does anything in dev->hard_start_xmit() by clearing | ||
1921 | * the skb destructor before the call and restoring it | ||
1922 | * afterwards, then doing the skb_orphan() ourselves? | ||
1923 | */ | ||
1924 | return rc; | 1922 | return rc; |
1925 | } | 1923 | } |
1926 | 1924 | ||
@@ -1938,6 +1936,7 @@ gso: | |||
1938 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) | 1936 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) |
1939 | skb_dst_drop(nskb); | 1937 | skb_dst_drop(nskb); |
1940 | 1938 | ||
1939 | skb_orphan_try(nskb); | ||
1941 | rc = ops->ndo_start_xmit(nskb, dev); | 1940 | rc = ops->ndo_start_xmit(nskb, dev); |
1942 | if (unlikely(rc != NETDEV_TX_OK)) { | 1941 | if (unlikely(rc != NETDEV_TX_OK)) { |
1943 | if (rc & ~NETDEV_TX_MASK) | 1942 | if (rc & ~NETDEV_TX_MASK) |