Skip to content

Commit

Permalink
vrf: Make pcpu_dstats update functions available to other modules.
Browse files Browse the repository at this point in the history
Currently vrf is the only module that uses NETDEV_PCPU_STAT_DSTATS.
In order to make this kind of statistics available to other modules,
we need to define the update functions in netdevice.h.

Therefore, let's define dev_dstats_*() functions for RX and TX packet
updates (packets, bytes and drops). Use these new functions in vrf.c
instead of vrf_rx_stats() and the other manual counter updates.

While there, update the type of the "len" variables to "unsigned int",
so that there're aligned with both skb->len and the new dstats update
functions.

Signed-off-by: Guillaume Nault <gnault@redhat.com>
Link: https://patch.msgid.link/d7a552ee382c79f4854e7fcc224cf176cd21150d.1733313925.git.gnault@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Guillaume Nault authored and Jakub Kicinski committed Dec 7, 2024
1 parent 9ec780b commit 18eabad
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 35 deletions.
49 changes: 14 additions & 35 deletions drivers/net/vrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,6 @@ struct net_vrf {
int ifindex;
};

static void vrf_rx_stats(struct net_device *dev, int len)
{
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);

u64_stats_update_begin(&dstats->syncp);
u64_stats_inc(&dstats->rx_packets);
u64_stats_add(&dstats->rx_bytes, len);
u64_stats_update_end(&dstats->syncp);
}

static void vrf_tx_error(struct net_device *vrf_dev, struct sk_buff *skb)
{
vrf_dev->stats.tx_errors++;
Expand Down Expand Up @@ -369,7 +359,7 @@ static bool qdisc_tx_is_default(const struct net_device *dev)
static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev,
struct dst_entry *dst)
{
int len = skb->len;
unsigned int len = skb->len;

skb_orphan(skb);

Expand All @@ -382,15 +372,10 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev,

skb->protocol = eth_type_trans(skb, dev);

if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) {
vrf_rx_stats(dev, len);
} else {
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);

u64_stats_update_begin(&dstats->syncp);
u64_stats_inc(&dstats->rx_drops);
u64_stats_update_end(&dstats->syncp);
}
if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
dev_dstats_rx_add(dev, len);
else
dev_dstats_rx_dropped(dev);

return NETDEV_TX_OK;
}
Expand Down Expand Up @@ -578,20 +563,14 @@ static netdev_tx_t is_ip_tx_frame(struct sk_buff *skb, struct net_device *dev)

static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);

int len = skb->len;
netdev_tx_t ret = is_ip_tx_frame(skb, dev);

u64_stats_update_begin(&dstats->syncp);
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
unsigned int len = skb->len;
netdev_tx_t ret;

u64_stats_inc(&dstats->tx_packets);
u64_stats_add(&dstats->tx_bytes, len);
} else {
u64_stats_inc(&dstats->tx_drops);
}
u64_stats_update_end(&dstats->syncp);
ret = is_ip_tx_frame(skb, dev);
if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN))
dev_dstats_tx_add(dev, len);
else
dev_dstats_tx_dropped(dev);

return ret;
}
Expand Down Expand Up @@ -1364,7 +1343,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
if (!is_ndisc) {
struct net_device *orig_dev = skb->dev;

vrf_rx_stats(vrf_dev, skb->len);
dev_dstats_rx_add(vrf_dev, skb->len);
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;

Expand Down Expand Up @@ -1420,7 +1399,7 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
goto out;
}

vrf_rx_stats(vrf_dev, skb->len);
dev_dstats_rx_add(vrf_dev, skb->len);

if (!list_empty(&vrf_dev->ptype_all)) {
int err;
Expand Down
40 changes: 40 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2854,6 +2854,46 @@ static inline void dev_lstats_add(struct net_device *dev, unsigned int len)
u64_stats_update_end(&lstats->syncp);
}

static inline void dev_dstats_rx_add(struct net_device *dev,
unsigned int len)
{
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);

u64_stats_update_begin(&dstats->syncp);
u64_stats_inc(&dstats->rx_packets);
u64_stats_add(&dstats->rx_bytes, len);
u64_stats_update_end(&dstats->syncp);
}

static inline void dev_dstats_rx_dropped(struct net_device *dev)
{
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);

u64_stats_update_begin(&dstats->syncp);
u64_stats_inc(&dstats->rx_drops);
u64_stats_update_end(&dstats->syncp);
}

static inline void dev_dstats_tx_add(struct net_device *dev,
unsigned int len)
{
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);

u64_stats_update_begin(&dstats->syncp);
u64_stats_inc(&dstats->tx_packets);
u64_stats_add(&dstats->tx_bytes, len);
u64_stats_update_end(&dstats->syncp);
}

static inline void dev_dstats_tx_dropped(struct net_device *dev)
{
struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);

u64_stats_update_begin(&dstats->syncp);
u64_stats_inc(&dstats->tx_drops);
u64_stats_update_end(&dstats->syncp);
}

#define __netdev_alloc_pcpu_stats(type, gfp) \
({ \
typeof(type) __percpu *pcpu_stats = alloc_percpu_gfp(type, gfp);\
Expand Down

0 comments on commit 18eabad

Please sign in to comment.