|
@@ -4154,7 +4154,10 @@ ncls:
|
|
ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
|
|
ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
|
|
} else {
|
|
} else {
|
|
drop:
|
|
drop:
|
|
- atomic_long_inc(&skb->dev->rx_dropped);
|
|
|
|
|
|
+ if (!deliver_exact)
|
|
|
|
+ atomic_long_inc(&skb->dev->rx_dropped);
|
|
|
|
+ else
|
|
|
|
+ atomic_long_inc(&skb->dev->rx_nohandler);
|
|
kfree_skb(skb);
|
|
kfree_skb(skb);
|
|
/* Jamal, now you will not able to escape explaining
|
|
/* Jamal, now you will not able to escape explaining
|
|
* me how you were going to use this. :-)
|
|
* me how you were going to use this. :-)
|
|
@@ -7253,24 +7256,31 @@ void netdev_run_todo(void)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-/* Convert net_device_stats to rtnl_link_stats64. They have the same
|
|
|
|
- * fields in the same order, with only the type differing.
|
|
|
|
|
|
+/* Convert net_device_stats to rtnl_link_stats64. rtnl_link_stats64 has
|
|
|
|
+ * all the same fields in the same order as net_device_stats, with only
|
|
|
|
+ * the type differing, but rtnl_link_stats64 may have additional fields
|
|
|
|
+ * at the end for newer counters.
|
|
*/
|
|
*/
|
|
void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64,
|
|
void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64,
|
|
const struct net_device_stats *netdev_stats)
|
|
const struct net_device_stats *netdev_stats)
|
|
{
|
|
{
|
|
#if BITS_PER_LONG == 64
|
|
#if BITS_PER_LONG == 64
|
|
- BUILD_BUG_ON(sizeof(*stats64) != sizeof(*netdev_stats));
|
|
|
|
|
|
+ BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats));
|
|
memcpy(stats64, netdev_stats, sizeof(*stats64));
|
|
memcpy(stats64, netdev_stats, sizeof(*stats64));
|
|
|
|
+ /* zero out counters that only exist in rtnl_link_stats64 */
|
|
|
|
+ memset((char *)stats64 + sizeof(*netdev_stats), 0,
|
|
|
|
+ sizeof(*stats64) - sizeof(*netdev_stats));
|
|
#else
|
|
#else
|
|
- size_t i, n = sizeof(*stats64) / sizeof(u64);
|
|
|
|
|
|
+ size_t i, n = sizeof(*netdev_stats) / sizeof(unsigned long);
|
|
const unsigned long *src = (const unsigned long *)netdev_stats;
|
|
const unsigned long *src = (const unsigned long *)netdev_stats;
|
|
u64 *dst = (u64 *)stats64;
|
|
u64 *dst = (u64 *)stats64;
|
|
|
|
|
|
- BUILD_BUG_ON(sizeof(*netdev_stats) / sizeof(unsigned long) !=
|
|
|
|
- sizeof(*stats64) / sizeof(u64));
|
|
|
|
|
|
+ BUILD_BUG_ON(n > sizeof(*stats64) / sizeof(u64));
|
|
for (i = 0; i < n; i++)
|
|
for (i = 0; i < n; i++)
|
|
dst[i] = src[i];
|
|
dst[i] = src[i];
|
|
|
|
+ /* zero out counters that only exist in rtnl_link_stats64 */
|
|
|
|
+ memset((char *)stats64 + n * sizeof(u64), 0,
|
|
|
|
+ sizeof(*stats64) - n * sizeof(u64));
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(netdev_stats_to_stats64);
|
|
EXPORT_SYMBOL(netdev_stats_to_stats64);
|
|
@@ -7300,6 +7310,7 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
|
|
}
|
|
}
|
|
storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
|
|
storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
|
|
storage->tx_dropped += atomic_long_read(&dev->tx_dropped);
|
|
storage->tx_dropped += atomic_long_read(&dev->tx_dropped);
|
|
|
|
+ storage->rx_nohandler += atomic_long_read(&dev->rx_nohandler);
|
|
return storage;
|
|
return storage;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(dev_get_stats);
|
|
EXPORT_SYMBOL(dev_get_stats);
|