--- zzzz-none-000/linux-4.4.271/drivers/net/tun.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/drivers/net/tun.c 2023-04-19 10:22:29.000000000 +0000 @@ -191,6 +191,8 @@ kgid_t group; struct net_device *dev; + struct rtnl_link_stats64 stats; + spinlock_t stats64_lock; /* protects statistics counters */ netdev_features_t set_features; #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ NETIF_F_TSO6|NETIF_F_UFO) @@ -214,6 +216,8 @@ u32 flow_count; }; +static tun_get_offload_stats_t tun_get_offload_stats_cb; + #ifdef CONFIG_TUN_VNET_CROSS_LE static inline bool tun_legacy_is_little_endian(struct tun_struct *tun) { @@ -931,6 +935,28 @@ return (features & tun->set_features) | (features & ~TUN_USER_FEATURES); } + +struct rtnl_link_stats64 *tun_net_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct tun_struct *tun = netdev_priv(dev); + + memset(stats, 0, sizeof(struct rtnl_link_stats64)); + spin_lock(&tun->stats64_lock); + + if (tun_get_offload_stats_cb) + tun_get_offload_stats_cb(dev, stats); + + stats->rx_frame_errors += dev->stats.rx_frame_errors; + stats->rx_packets += dev->stats.rx_packets; + stats->rx_bytes += dev->stats.rx_bytes; + stats->tx_packets += dev->stats.tx_packets; + stats->tx_bytes += dev->stats.tx_bytes; + + spin_unlock(&tun->stats64_lock); + return stats; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void tun_poll_controller(struct net_device *dev) { @@ -956,6 +982,7 @@ .ndo_change_mtu = tun_net_change_mtu, .ndo_fix_features = tun_net_fix_features, .ndo_select_queue = tun_select_queue, + .ndo_get_stats64 = tun_net_get_stats64, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = tun_poll_controller, #endif @@ -1730,6 +1757,7 @@ dev->vlan_features = dev->features & ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX); + dev->priv_flags_ext |= IFF_EXT_TUN_TAP; INIT_LIST_HEAD(&tun->disabled); err = tun_attach(tun, file, false, false); @@ -2423,7 +2451,6 @@ .get_ts_info = ethtool_op_get_ts_info, }; - static int __init tun_init(void) { int ret = 0; @@ -2471,6 +2498,21 @@ } EXPORT_SYMBOL_GPL(tun_get_socket); +/* Register tun offload statistics callback */ +void tun_register_offload_stats_callback(tun_get_offload_stats_t stats_cb) +{ + BUG_ON(tun_get_offload_stats_cb); + rcu_assign_pointer(tun_get_offload_stats_cb, stats_cb); +} +EXPORT_SYMBOL(tun_register_offload_stats_callback); + +/* Unregister tun offload statistics callback */ +void tun_unregister_offload_stats_callback(void) +{ + rcu_assign_pointer(tun_get_offload_stats_cb, NULL); +} +EXPORT_SYMBOL(tun_unregister_offload_stats_callback); + module_init(tun_init); module_exit(tun_cleanup); MODULE_DESCRIPTION(DRV_DESCRIPTION);