Merge branch 'eth_skb_pad'

Alexander Duyck says:

====================
net: Add helper for padding short Ethernet frames

This patch series adds a pair of helpers to pad short Ethernet frames.  The
general idea is to clean up a number of code paths that were all writing
their own versions of the same or similar function.

An added advantage is that this will help to discourage introducing new
bugs as in at least one case I found the skb->len had been updated, but the
tail pointer update was overlooked.

v2: Added skb_put_padto for cases where length is not ETH_ZLEN
    Updated intel drivers and emulex driver to use skb_put_padto
    Updated eth_skb_pad to use skb_put_padto
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2014-12-08 20:47:47 -05:00
commit 99bc5c928d
13 changed files with 67 additions and 92 deletions

View file

@ -1017,9 +1017,8 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
* to pad short packets (<= 32 bytes) to a 36-byte length.
*/
if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
if (skb_padto(skb, 36))
if (skb_put_padto(skb, 36))
return NULL;
skb->len = 36;
}
if (BEx_chip(adapter) || lancer_chip(adapter)) {

View file

@ -3136,12 +3136,8 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
* packets may get corrupted during padding by HW.
* To WA this issue, pad all small packets manually.
*/
if (skb->len < ETH_ZLEN) {
if (skb_pad(skb, ETH_ZLEN - skb->len))
return NETDEV_TX_OK;
skb->len = ETH_ZLEN;
skb_set_tail_pointer(skb, ETH_ZLEN);
}
if (eth_skb_pad(skb))
return NETDEV_TX_OK;
mss = skb_shinfo(skb)->gso_size;
/* The controller does a simple calculation to

View file

@ -5554,12 +5554,8 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
/* The minimum packet size with TCTL.PSP set is 17 bytes so
* pad skb in order to meet this minimum size requirement
*/
if (unlikely(skb->len < 17)) {
if (skb_pad(skb, 17 - skb->len))
return NETDEV_TX_OK;
skb->len = 17;
skb_set_tail_pointer(skb, 17);
}
if (skb_put_padto(skb, 17))
return NETDEV_TX_OK;
mss = skb_shinfo(skb)->gso_size;
if (mss) {

View file

@ -578,14 +578,9 @@ static bool fm10k_cleanup_headers(struct fm10k_ring *rx_ring,
if (skb_is_nonlinear(skb))
fm10k_pull_tail(rx_ring, rx_desc, skb);
/* if skb_pad returns an error the skb was freed */
if (unlikely(skb->len < 60)) {
int pad_len = 60 - skb->len;
if (skb_pad(skb, pad_len))
return true;
__skb_put(skb, pad_len);
}
/* if eth_skb_pad returns an error the skb was freed */
if (eth_skb_pad(skb))
return true;
return false;
}

View file

@ -2399,12 +2399,8 @@ netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* hardware can't handle really short frames, hardware padding works
* beyond this point
*/
if (unlikely(skb->len < I40E_MIN_TX_LEN)) {
if (skb_pad(skb, I40E_MIN_TX_LEN - skb->len))
return NETDEV_TX_OK;
skb->len = I40E_MIN_TX_LEN;
skb_set_tail_pointer(skb, I40E_MIN_TX_LEN);
}
if (skb_put_padto(skb, I40E_MIN_TX_LEN))
return NETDEV_TX_OK;
return i40e_xmit_frame_ring(skb, tx_ring);
}

View file

@ -5091,12 +5091,8 @@ static netdev_tx_t igb_xmit_frame(struct sk_buff *skb,
/* The minimum packet size with TCTL.PSP set is 17 so pad the skb
* in order to meet this minimum size requirement.
*/
if (unlikely(skb->len < 17)) {
if (skb_pad(skb, 17 - skb->len))
return NETDEV_TX_OK;
skb->len = 17;
skb_set_tail_pointer(skb, 17);
}
if (skb_put_padto(skb, 17))
return NETDEV_TX_OK;
return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb));
}
@ -6850,14 +6846,9 @@ static bool igb_cleanup_headers(struct igb_ring *rx_ring,
if (skb_is_nonlinear(skb))
igb_pull_tail(rx_ring, rx_desc, skb);
/* if skb_pad returns an error the skb was freed */
if (unlikely(skb->len < 60)) {
int pad_len = 60 - skb->len;
if (skb_pad(skb, pad_len))
return true;
__skb_put(skb, pad_len);
}
/* if eth_skb_pad returns an error the skb was freed */
if (eth_skb_pad(skb))
return true;
return false;
}

View file

@ -1774,14 +1774,9 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
return false;
#endif
/* if skb_pad returns an error the skb was freed */
if (unlikely(skb->len < 60)) {
int pad_len = 60 - skb->len;
if (skb_pad(skb, pad_len))
return true;
__skb_put(skb, pad_len);
}
/* if eth_skb_pad returns an error the skb was freed */
if (eth_skb_pad(skb))
return true;
return false;
}
@ -7334,12 +7329,8 @@ static netdev_tx_t __ixgbe_xmit_frame(struct sk_buff *skb,
* The minimum packet size for olinfo paylen is 17 so pad the skb
* in order to meet this minimum size requirement.
*/
if (unlikely(skb->len < 17)) {
if (skb_pad(skb, 17 - skb->len))
return NETDEV_TX_OK;
skb->len = 17;
skb_set_tail_pointer(skb, 17);
}
if (skb_put_padto(skb, 17))
return NETDEV_TX_OK;
tx_ring = ring ? ring : adapter->tx_ring[skb->queue_mapping];

View file

@ -616,14 +616,9 @@ static bool ixgbevf_cleanup_headers(struct ixgbevf_ring *rx_ring,
if (skb_is_nonlinear(skb))
ixgbevf_pull_tail(rx_ring, skb);
/* if skb_pad returns an error the skb was freed */
if (unlikely(skb->len < 60)) {
int pad_len = 60 - skb->len;
if (skb_pad(skb, pad_len))
return true;
__skb_put(skb, pad_len);
}
/* if eth_skb_pad returns an error the skb was freed */
if (eth_skb_pad(skb))
return true;
return false;
}

View file

@ -2913,16 +2913,11 @@ again:
flags |= MXGEFW_FLAGS_SMALL;
/* pad frames to at least ETH_ZLEN bytes */
if (unlikely(skb->len < ETH_ZLEN)) {
if (skb_padto(skb, ETH_ZLEN)) {
/* The packet is gone, so we must
* return 0 */
ss->stats.tx_dropped += 1;
return NETDEV_TX_OK;
}
/* adjust the len to account for the zero pad
* so that the nic can know how long it is */
skb->len = ETH_ZLEN;
if (eth_skb_pad(skb)) {
/* The packet is gone, so we must
* return 0 */
ss->stats.tx_dropped += 1;
return NETDEV_TX_OK;
}
}

View file

@ -6836,14 +6836,6 @@ err_out:
return -EIO;
}
static bool rtl_skb_pad(struct sk_buff *skb)
{
if (skb_padto(skb, ETH_ZLEN))
return false;
skb_put(skb, ETH_ZLEN - skb->len);
return true;
}
static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb)
{
return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34;
@ -6984,7 +6976,7 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
u8 ip_protocol;
if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb);
return !(skb_checksum_help(skb) || eth_skb_pad(skb));
if (transport_offset > TCPHO_MAX) {
netif_warn(tp, tx_err, tp->dev,
@ -7019,7 +7011,7 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
opts[1] |= transport_offset << TCPHO_SHIFT;
} else {
if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
return rtl_skb_pad(skb);
return !eth_skb_pad(skb);
}
return true;

View file

@ -6651,13 +6651,8 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
if (skb->len < ETH_ZLEN) {
unsigned int pad_bytes = ETH_ZLEN - skb->len;
if (skb_pad(skb, pad_bytes))
goto out;
skb_put(skb, pad_bytes);
}
if (eth_skb_pad(skb))
goto out;
len = sizeof(struct tx_pkt_hdr) + 15;
if (skb_headroom(skb) < len) {

View file

@ -392,4 +392,16 @@ static inline unsigned long compare_ether_header(const void *a, const void *b)
#endif
}
/**
* eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
* @skb: Buffer to pad
*
* An Ethernet frame should have a minimum size of 60 bytes. This function
* takes short frames and pads them with zeros up to the 60 byte limit.
*/
static inline int eth_skb_pad(struct sk_buff *skb)
{
return skb_put_padto(skb, ETH_ZLEN);
}
#endif /* _LINUX_ETHERDEVICE_H */

View file

@ -2461,7 +2461,6 @@ static inline int skb_cow_head(struct sk_buff *skb, unsigned int headroom)
* is untouched. Otherwise it is extended. Returns zero on
* success. The skb is freed on error.
*/
static inline int skb_padto(struct sk_buff *skb, unsigned int len)
{
unsigned int size = skb->len;
@ -2470,6 +2469,29 @@ static inline int skb_padto(struct sk_buff *skb, unsigned int len)
return skb_pad(skb, len - size);
}
/**
* skb_put_padto - increase size and pad an skbuff up to a minimal size
* @skb: buffer to pad
* @len: minimal length
*
* Pads up a buffer to ensure the trailing bytes exist and are
* blanked. If the buffer already contains sufficient data it
* is untouched. Otherwise it is extended. Returns zero on
* success. The skb is freed on error.
*/
static inline int skb_put_padto(struct sk_buff *skb, unsigned int len)
{
unsigned int size = skb->len;
if (unlikely(size < len)) {
len -= size;
if (skb_pad(skb, len))
return -ENOMEM;
__skb_put(skb, len);
}
return 0;
}
static inline int skb_add_data(struct sk_buff *skb,
char __user *from, int copy)
{