aboutsummaryrefslogtreecommitdiff
path: root/net/xfrm/xfrm_interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_interface.c')
-rw-r--r--net/xfrm/xfrm_interface.c29
1 files changed, 11 insertions, 18 deletions
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index 9b8e292a7c6a..495b1f5c979b 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -296,7 +296,8 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
}
mtu = dst_mtu(dst);
- if (skb->len > mtu) {
+ if ((!skb_is_gso(skb) && skb->len > mtu) ||
+ (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu))) {
skb_dst_update_pmtu_no_confirm(skb, mtu);
if (skb->protocol == htons(ETH_P_IPV6)) {
@@ -319,12 +320,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
err = dst_output(xi->net, skb->sk, skb);
if (net_xmit_eval(err) == 0) {
- struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
-
- u64_stats_update_begin(&tstats->syncp);
- tstats->tx_bytes += length;
- tstats->tx_packets++;
- u64_stats_update_end(&tstats->syncp);
+ dev_sw_netstats_tx_add(dev, 1, length);
} else {
stats->tx_errors++;
stats->tx_aborted_errors++;
@@ -538,15 +534,6 @@ static int xfrmi_update(struct xfrm_if *xi, struct xfrm_if_parms *p)
return err;
}
-static void xfrmi_get_stats64(struct net_device *dev,
- struct rtnl_link_stats64 *s)
-{
- dev_fetch_sw_netstats(s, dev->tstats);
-
- s->rx_dropped = dev->stats.rx_dropped;
- s->tx_dropped = dev->stats.tx_dropped;
-}
-
static int xfrmi_get_iflink(const struct net_device *dev)
{
struct xfrm_if *xi = netdev_priv(dev);
@@ -554,12 +541,11 @@ static int xfrmi_get_iflink(const struct net_device *dev)
return xi->p.link;
}
-
static const struct net_device_ops xfrmi_netdev_ops = {
.ndo_init = xfrmi_dev_init,
.ndo_uninit = xfrmi_dev_uninit,
.ndo_start_xmit = xfrmi_xmit,
- .ndo_get_stats64 = xfrmi_get_stats64,
+ .ndo_get_stats64 = dev_get_tstats64,
.ndo_get_iflink = xfrmi_get_iflink,
};
@@ -579,6 +565,11 @@ static void xfrmi_dev_setup(struct net_device *dev)
eth_broadcast_addr(dev->broadcast);
}
+#define XFRMI_FEATURES (NETIF_F_SG | \
+ NETIF_F_FRAGLIST | \
+ NETIF_F_GSO_SOFTWARE | \
+ NETIF_F_HW_CSUM)
+
static int xfrmi_dev_init(struct net_device *dev)
{
struct xfrm_if *xi = netdev_priv(dev);
@@ -596,6 +587,8 @@ static int xfrmi_dev_init(struct net_device *dev)
}
dev->features |= NETIF_F_LLTX;
+ dev->features |= XFRMI_FEATURES;
+ dev->hw_features |= XFRMI_FEATURES;
if (phydev) {
dev->needed_headroom = phydev->needed_headroom;