--- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -15,6 +15,13 @@ struct macvlan_port; #define MACVLAN_MC_FILTER_BITS 8 #define MACVLAN_MC_FILTER_SZ (1 << MACVLAN_MC_FILTER_BITS) +/* QCA NSS ECM Support - Start */ +/* + * Callback for updating interface statistics for macvlan flows offloaded from host CPU. + */ +typedef void (*macvlan_offload_stats_update_cb_t)(struct net_device *dev, struct rtnl_link_stats64 *stats, bool update_mcast_rx_stats); +/* QCA NSS ECM Support - End */ + struct macvlan_dev { struct net_device *dev; struct list_head list; @@ -35,6 +42,7 @@ struct macvlan_dev { #ifdef CONFIG_NET_POLL_CONTROLLER struct netpoll *netpoll; #endif + macvlan_offload_stats_update_cb_t offload_stats_update; /* QCA NSS ECM support */ }; static inline void macvlan_count_rx(const struct macvlan_dev *vlan, @@ -107,4 +115,26 @@ static inline int macvlan_release_l2fw_o macvlan->accel_priv = NULL; return dev_uc_add(macvlan->lowerdev, dev->dev_addr); } + +/* QCA NSS ECM Support - Start */ +#if IS_ENABLED(CONFIG_MACVLAN) +static inline void +macvlan_offload_stats_update(struct net_device *dev, + struct rtnl_link_stats64 *stats, + bool update_mcast_rx_stats) +{ + struct macvlan_dev *macvlan = netdev_priv(dev); + + macvlan->offload_stats_update(dev, stats, update_mcast_rx_stats); +} + +static inline enum +macvlan_mode macvlan_get_mode(struct net_device *dev) +{ + struct macvlan_dev *macvlan = netdev_priv(dev); + + return macvlan->mode; +} +#endif +/* QCA NSS ECM Support - End */ #endif /* _LINUX_IF_MACVLAN_H */ --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -960,6 +960,34 @@ static void macvlan_uninit(struct net_de macvlan_port_destroy(port->dev); } +/* QCA NSS ECM Support - Start */ +/* Update macvlan statistics processed by offload engines */ +static void macvlan_dev_update_stats(struct net_device *dev, + struct rtnl_link_stats64 *offl_stats, + bool update_mcast_rx_stats) +{ + struct vlan_pcpu_stats *stats; + struct macvlan_dev *macvlan; + + /* Is this a macvlan? */ + if (!netif_is_macvlan(dev)) + return; + + macvlan = netdev_priv(dev); + stats = this_cpu_ptr(macvlan->pcpu_stats); + u64_stats_update_begin(&stats->syncp); + u64_stats_add(&stats->rx_packets, offl_stats->rx_packets); + u64_stats_add(&stats->rx_bytes, offl_stats->rx_bytes); + u64_stats_add(&stats->tx_packets, offl_stats->tx_packets); + u64_stats_add(&stats->tx_bytes, offl_stats->tx_bytes); + /* Update multicast statistics */ + if (unlikely(update_mcast_rx_stats)) { + u64_stats_add(&stats->rx_multicast, offl_stats->rx_packets); + } + u64_stats_update_end(&stats->syncp); +} +/* QCA NSS ECM Support - End */ + static void macvlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { @@ -1506,6 +1534,7 @@ int macvlan_common_newlink(struct net *s vlan->dev = dev; vlan->port = port; vlan->set_features = MACVLAN_FEATURES; + vlan->offload_stats_update = macvlan_dev_update_stats; /* QCA NSS ECM Support */ vlan->mode = MACVLAN_MODE_VEPA; if (data && data[IFLA_MACVLAN_MODE])