@@ -209,13 +209,36 @@ static struct vport *new_vport(const struct vport_parms *parms)
209209 return vport ;
210210}
211211
212+ static void ovs_vport_update_upcall_stats (struct sk_buff * skb ,
213+ const struct dp_upcall_info * upcall_info ,
214+ bool upcall_result )
215+ {
216+ struct vport * p = OVS_CB (skb )-> input_vport ;
217+ struct vport_upcall_stats_percpu * stats ;
218+
219+ if (upcall_info -> cmd != OVS_PACKET_CMD_MISS &&
220+ upcall_info -> cmd != OVS_PACKET_CMD_ACTION )
221+ return ;
222+
223+ stats = this_cpu_ptr (p -> upcall_stats );
224+ u64_stats_update_begin (& stats -> syncp );
225+ if (upcall_result )
226+ u64_stats_inc (& stats -> n_success );
227+ else
228+ u64_stats_inc (& stats -> n_fail );
229+ u64_stats_update_end (& stats -> syncp );
230+ }
231+
212232void ovs_dp_detach_port (struct vport * p )
213233{
214234 ASSERT_OVSL ();
215235
216236 /* First drop references to device. */
217237 hlist_del_rcu (& p -> dp_hash_node );
218238
239+ /* Free percpu memory */
240+ free_percpu (p -> upcall_stats );
241+
219242 /* Then destroy it. */
220243 ovs_vport_del (p );
221244}
@@ -305,6 +328,8 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
305328 err = queue_userspace_packet (dp , skb , key , upcall_info , cutlen );
306329 else
307330 err = queue_gso_packets (dp , skb , key , upcall_info , cutlen );
331+
332+ ovs_vport_update_upcall_stats (skb , upcall_info , !err );
308333 if (err )
309334 goto err ;
310335
@@ -1826,6 +1851,12 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
18261851 goto err_destroy_portids ;
18271852 }
18281853
1854+ vport -> upcall_stats = netdev_alloc_pcpu_stats (struct vport_upcall_stats_percpu );
1855+ if (!vport -> upcall_stats ) {
1856+ err = - ENOMEM ;
1857+ goto err_destroy_portids ;
1858+ }
1859+
18291860 err = ovs_dp_cmd_fill_info (dp , reply , info -> snd_portid ,
18301861 info -> snd_seq , 0 , OVS_DP_CMD_NEW );
18311862 BUG_ON (err < 0 );
@@ -2098,6 +2129,9 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
20982129 OVS_VPORT_ATTR_PAD ))
20992130 goto nla_put_failure ;
21002131
2132+ if (ovs_vport_get_upcall_stats (vport , skb ))
2133+ goto nla_put_failure ;
2134+
21012135 if (ovs_vport_get_upcall_portids (vport , skb ))
21022136 goto nla_put_failure ;
21032137
@@ -2279,6 +2313,12 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
22792313 goto exit_unlock_free ;
22802314 }
22812315
2316+ vport -> upcall_stats = netdev_alloc_pcpu_stats (struct vport_upcall_stats_percpu );
2317+ if (!vport -> upcall_stats ) {
2318+ err = - ENOMEM ;
2319+ goto exit_unlock_free ;
2320+ }
2321+
22822322 err = ovs_vport_cmd_fill_info (vport , reply , genl_info_net (info ),
22832323 info -> snd_portid , info -> snd_seq , 0 ,
22842324 OVS_VPORT_CMD_NEW , GFP_KERNEL );
@@ -2508,6 +2548,7 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
25082548 [OVS_VPORT_ATTR_OPTIONS ] = { .type = NLA_NESTED },
25092549 [OVS_VPORT_ATTR_IFINDEX ] = { .type = NLA_U32 },
25102550 [OVS_VPORT_ATTR_NETNSID ] = { .type = NLA_S32 },
2551+ [OVS_VPORT_ATTR_UPCALL_STATS ] = { .type = NLA_NESTED },
25112552};
25122553
25132554static const struct genl_small_ops dp_vport_genl_ops [] = {
0 commit comments