Skip to content

Commit 4095e0e

Browse files
Nikolay Aleksandrovdavem330
authored andcommitted
drivers: vxlan: vnifilter: per vni stats
Add per-vni statistics for vni filter mode. Counting Rx/Tx bytes/packets/drops/errors at the appropriate places. This patch changes vxlan_vs_find_vni to also return the vxlan_vni_node in cases where the vni belongs to a vni filtering vxlan device Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com> Signed-off-by: Roopa Prabhu <roopa@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 3edf5f6 commit 4095e0e

File tree

4 files changed

+128
-9
lines changed

4 files changed

+128
-9
lines changed

drivers/net/vxlan/vxlan_core.c

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,11 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
139139
return NULL;
140140
}
141141

142-
static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, int ifindex,
143-
__be32 vni)
142+
static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs,
143+
int ifindex, __be32 vni,
144+
struct vxlan_vni_node **vninode)
144145
{
146+
struct vxlan_vni_node *vnode;
145147
struct vxlan_dev_node *node;
146148

147149
/* For flow based devices, map all packets to VNI 0 */
@@ -152,8 +154,10 @@ static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, int ifindex,
152154
hlist_for_each_entry_rcu(node, vni_head(vs, vni), hlist) {
153155
if (!node->vxlan)
154156
continue;
157+
vnode = NULL;
155158
if (node->vxlan->cfg.flags & VXLAN_F_VNIFILTER) {
156-
if (!vxlan_vnifilter_lookup(node->vxlan, vni))
159+
vnode = vxlan_vnifilter_lookup(node->vxlan, vni);
160+
if (!vnode)
157161
continue;
158162
} else if (node->vxlan->default_dst.remote_vni != vni) {
159163
continue;
@@ -167,6 +171,8 @@ static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, int ifindex,
167171
continue;
168172
}
169173

174+
if (vninode)
175+
*vninode = vnode;
170176
return node->vxlan;
171177
}
172178

@@ -184,7 +190,7 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, int ifindex,
184190
if (!vs)
185191
return NULL;
186192

187-
return vxlan_vs_find_vni(vs, ifindex, vni);
193+
return vxlan_vs_find_vni(vs, ifindex, vni, NULL);
188194
}
189195

190196
/* Fill in neighbour message in skbuff. */
@@ -1644,6 +1650,7 @@ static bool vxlan_ecn_decapsulate(struct vxlan_sock *vs, void *oiph,
16441650
/* Callback from net/ipv4/udp.c to receive packets */
16451651
static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
16461652
{
1653+
struct vxlan_vni_node *vninode = NULL;
16471654
struct vxlan_dev *vxlan;
16481655
struct vxlan_sock *vs;
16491656
struct vxlanhdr unparsed;
@@ -1676,7 +1683,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
16761683

16771684
vni = vxlan_vni(vxlan_hdr(skb)->vx_vni);
16781685

1679-
vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni);
1686+
vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni, &vninode);
16801687
if (!vxlan)
16811688
goto drop;
16821689

@@ -1746,6 +1753,8 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
17461753
if (!vxlan_ecn_decapsulate(vs, oiph, skb)) {
17471754
++vxlan->dev->stats.rx_frame_errors;
17481755
++vxlan->dev->stats.rx_errors;
1756+
vxlan_vnifilter_count(vxlan, vni, vninode,
1757+
VXLAN_VNI_STATS_RX_ERRORS, 0);
17491758
goto drop;
17501759
}
17511760

@@ -1754,10 +1763,13 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
17541763
if (unlikely(!(vxlan->dev->flags & IFF_UP))) {
17551764
rcu_read_unlock();
17561765
atomic_long_inc(&vxlan->dev->rx_dropped);
1766+
vxlan_vnifilter_count(vxlan, vni, vninode,
1767+
VXLAN_VNI_STATS_RX_DROPS, 0);
17571768
goto drop;
17581769
}
17591770

17601771
dev_sw_netstats_rx_add(vxlan->dev, skb->len);
1772+
vxlan_vnifilter_count(vxlan, vni, vninode, VXLAN_VNI_STATS_RX, skb->len);
17611773
gro_cells_receive(&vxlan->gro_cells, skb);
17621774

17631775
rcu_read_unlock();
@@ -1791,7 +1803,7 @@ static int vxlan_err_lookup(struct sock *sk, struct sk_buff *skb)
17911803
return -ENOENT;
17921804

17931805
vni = vxlan_vni(hdr->vx_vni);
1794-
vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni);
1806+
vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni, NULL);
17951807
if (!vxlan)
17961808
return -ENOENT;
17971809

@@ -1865,8 +1877,12 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
18651877
reply->ip_summed = CHECKSUM_UNNECESSARY;
18661878
reply->pkt_type = PACKET_HOST;
18671879

1868-
if (netif_rx_ni(reply) == NET_RX_DROP)
1880+
if (netif_rx_ni(reply) == NET_RX_DROP) {
18691881
dev->stats.rx_dropped++;
1882+
vxlan_vnifilter_count(vxlan, vni, NULL,
1883+
VXLAN_VNI_STATS_RX_DROPS, 0);
1884+
}
1885+
18701886
} else if (vxlan->cfg.flags & VXLAN_F_L3MISS) {
18711887
union vxlan_addr ipa = {
18721888
.sin.sin_addr.s_addr = tip,
@@ -2020,9 +2036,11 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
20202036
if (reply == NULL)
20212037
goto out;
20222038

2023-
if (netif_rx_ni(reply) == NET_RX_DROP)
2039+
if (netif_rx_ni(reply) == NET_RX_DROP) {
20242040
dev->stats.rx_dropped++;
2025-
2041+
vxlan_vnifilter_count(vxlan, vni, NULL,
2042+
VXLAN_VNI_STATS_RX_DROPS, 0);
2043+
}
20262044
} else if (vxlan->cfg.flags & VXLAN_F_L3MISS) {
20272045
union vxlan_addr ipa = {
20282046
.sin6.sin6_addr = msg->target,
@@ -2356,15 +2374,20 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
23562374
tx_stats->tx_packets++;
23572375
tx_stats->tx_bytes += len;
23582376
u64_stats_update_end(&tx_stats->syncp);
2377+
vxlan_vnifilter_count(src_vxlan, vni, NULL, VXLAN_VNI_STATS_TX, len);
23592378

23602379
if (__netif_rx(skb) == NET_RX_SUCCESS) {
23612380
u64_stats_update_begin(&rx_stats->syncp);
23622381
rx_stats->rx_packets++;
23632382
rx_stats->rx_bytes += len;
23642383
u64_stats_update_end(&rx_stats->syncp);
2384+
vxlan_vnifilter_count(dst_vxlan, vni, NULL, VXLAN_VNI_STATS_RX,
2385+
len);
23652386
} else {
23662387
drop:
23672388
dev->stats.rx_dropped++;
2389+
vxlan_vnifilter_count(dst_vxlan, vni, NULL,
2390+
VXLAN_VNI_STATS_RX_DROPS, 0);
23682391
}
23692392
rcu_read_unlock();
23702393
}
@@ -2394,6 +2417,8 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
23942417
vxlan->cfg.flags);
23952418
if (!dst_vxlan) {
23962419
dev->stats.tx_errors++;
2420+
vxlan_vnifilter_count(vxlan, vni, NULL,
2421+
VXLAN_VNI_STATS_TX_ERRORS, 0);
23972422
kfree_skb(skb);
23982423

23992424
return -ENOENT;
@@ -2417,6 +2442,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
24172442
union vxlan_addr remote_ip, local_ip;
24182443
struct vxlan_metadata _md;
24192444
struct vxlan_metadata *md = &_md;
2445+
unsigned int pkt_len = skb->len;
24202446
__be16 src_port = 0, dst_port;
24212447
struct dst_entry *ndst = NULL;
24222448
__u8 tos, ttl;
@@ -2644,12 +2670,14 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
26442670
label, src_port, dst_port, !udp_sum);
26452671
#endif
26462672
}
2673+
vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX, pkt_len);
26472674
out_unlock:
26482675
rcu_read_unlock();
26492676
return;
26502677

26512678
drop:
26522679
dev->stats.tx_dropped++;
2680+
vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);
26532681
dev_kfree_skb(skb);
26542682
return;
26552683

@@ -2661,6 +2689,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
26612689
dev->stats.tx_carrier_errors++;
26622690
dst_release(ndst);
26632691
dev->stats.tx_errors++;
2692+
vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0);
26642693
kfree_skb(skb);
26652694
}
26662695

@@ -2693,6 +2722,8 @@ static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,
26932722

26942723
drop:
26952724
dev->stats.tx_dropped++;
2725+
vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
2726+
VXLAN_VNI_STATS_TX_DROPS, 0);
26962727
dev_kfree_skb(skb);
26972728
}
26982729

@@ -2767,6 +2798,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
27672798
vxlan_fdb_miss(vxlan, eth->h_dest);
27682799

27692800
dev->stats.tx_dropped++;
2801+
vxlan_vnifilter_count(vxlan, vni, NULL,
2802+
VXLAN_VNI_STATS_TX_DROPS, 0);
27702803
kfree_skb(skb);
27712804
return NETDEV_TX_OK;
27722805
}

drivers/net/vxlan/vxlan_private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ void vxlan_vnigroup_uninit(struct vxlan_dev *vxlan);
136136

137137
void vxlan_vnifilter_init(void);
138138
void vxlan_vnifilter_uninit(void);
139+
void vxlan_vnifilter_count(struct vxlan_dev *vxlan, __be32 vni,
140+
struct vxlan_vni_node *vninode,
141+
int type, unsigned int len);
139142

140143
void vxlan_vs_add_vnigrp(struct vxlan_dev *vxlan,
141144
struct vxlan_sock *vs,

drivers/net/vxlan/vxlan_vnifilter.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,57 @@ void vxlan_vs_del_vnigrp(struct vxlan_dev *vxlan)
116116
spin_unlock(&vn->sock_lock);
117117
}
118118

119+
static void vxlan_vnifilter_stats_add(struct vxlan_vni_node *vninode,
120+
int type, unsigned int len)
121+
{
122+
struct vxlan_vni_stats_pcpu *pstats = this_cpu_ptr(vninode->stats);
123+
124+
u64_stats_update_begin(&pstats->syncp);
125+
switch (type) {
126+
case VXLAN_VNI_STATS_RX:
127+
pstats->stats.rx_bytes += len;
128+
pstats->stats.rx_packets++;
129+
break;
130+
case VXLAN_VNI_STATS_RX_DROPS:
131+
pstats->stats.rx_drops++;
132+
break;
133+
case VXLAN_VNI_STATS_RX_ERRORS:
134+
pstats->stats.rx_errors++;
135+
break;
136+
case VXLAN_VNI_STATS_TX:
137+
pstats->stats.tx_bytes += len;
138+
pstats->stats.tx_packets++;
139+
break;
140+
case VXLAN_VNI_STATS_TX_DROPS:
141+
pstats->stats.tx_drops++;
142+
break;
143+
case VXLAN_VNI_STATS_TX_ERRORS:
144+
pstats->stats.tx_errors++;
145+
break;
146+
}
147+
u64_stats_update_end(&pstats->syncp);
148+
}
149+
150+
void vxlan_vnifilter_count(struct vxlan_dev *vxlan, __be32 vni,
151+
struct vxlan_vni_node *vninode,
152+
int type, unsigned int len)
153+
{
154+
struct vxlan_vni_node *vnode;
155+
156+
if (!(vxlan->cfg.flags & VXLAN_F_VNIFILTER))
157+
return;
158+
159+
if (vninode) {
160+
vnode = vninode;
161+
} else {
162+
vnode = vxlan_vnifilter_lookup(vxlan, vni);
163+
if (!vnode)
164+
return;
165+
}
166+
167+
vxlan_vnifilter_stats_add(vnode, type, len);
168+
}
169+
119170
static u32 vnirange(struct vxlan_vni_node *vbegin,
120171
struct vxlan_vni_node *vend)
121172
{
@@ -562,6 +613,11 @@ static struct vxlan_vni_node *vxlan_vni_alloc(struct vxlan_dev *vxlan,
562613
vninode = kzalloc(sizeof(*vninode), GFP_ATOMIC);
563614
if (!vninode)
564615
return NULL;
616+
vninode->stats = netdev_alloc_pcpu_stats(struct vxlan_vni_stats_pcpu);
617+
if (!vninode->stats) {
618+
kfree(vninode);
619+
return NULL;
620+
}
565621
vninode->vni = vni;
566622
vninode->hlist4.vxlan = vxlan;
567623
#if IS_ENABLED(CONFIG_IPV6)
@@ -621,6 +677,7 @@ static void vxlan_vni_node_rcu_free(struct rcu_head *rcu)
621677
struct vxlan_vni_node *v;
622678

623679
v = container_of(rcu, struct vxlan_vni_node, rcu);
680+
free_percpu(v->stats);
624681
kfree(v);
625682
}
626683

include/net/vxlan.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,31 @@ struct vxlan_config {
227227
enum ifla_vxlan_df df;
228228
};
229229

230+
enum {
231+
VXLAN_VNI_STATS_RX,
232+
VXLAN_VNI_STATS_RX_DROPS,
233+
VXLAN_VNI_STATS_RX_ERRORS,
234+
VXLAN_VNI_STATS_TX,
235+
VXLAN_VNI_STATS_TX_DROPS,
236+
VXLAN_VNI_STATS_TX_ERRORS,
237+
};
238+
239+
struct vxlan_vni_stats {
240+
u64 rx_packets;
241+
u64 rx_bytes;
242+
u64 rx_drops;
243+
u64 rx_errors;
244+
u64 tx_packets;
245+
u64 tx_bytes;
246+
u64 tx_drops;
247+
u64 tx_errors;
248+
};
249+
250+
struct vxlan_vni_stats_pcpu {
251+
struct vxlan_vni_stats stats;
252+
struct u64_stats_sync syncp;
253+
};
254+
230255
struct vxlan_dev_node {
231256
struct hlist_node hlist;
232257
struct vxlan_dev *vxlan;
@@ -241,6 +266,7 @@ struct vxlan_vni_node {
241266
struct list_head vlist;
242267
__be32 vni;
243268
union vxlan_addr remote_ip; /* default remote ip for this vni */
269+
struct vxlan_vni_stats_pcpu __percpu *stats;
244270

245271
struct rcu_head rcu;
246272
};

0 commit comments

Comments
 (0)