@@ -288,10 +288,12 @@ enum ovs_vport_attr {
* enum ovs_vport_upcall_attr - attributes for %OVS_VPORT_UPCALL* commands
* @OVS_VPORT_UPCALL_SUCCESS: 64-bit upcall success packets.
* @OVS_VPORT_UPCALL_FAIL: 64-bit upcall fail packets.
+ * @OVS_VPORT_UPCALL_MCAST: 64-bit multicasted upcall packets.
*/
enum ovs_vport_upcall_attr {
OVS_VPORT_UPCALL_ATTR_SUCCESS,
OVS_VPORT_UPCALL_ATTR_FAIL,
+ OVS_VPORT_UPCALL_ATTR_MCAST,
__OVS_VPORT_UPCALL_ATTR_MAX
};
@@ -217,7 +217,7 @@ static struct vport *new_vport(const struct vport_parms *parms)
static void ovs_vport_update_upcall_stats(struct sk_buff *skb,
const struct dp_upcall_info *upcall_info,
- bool upcall_result)
+ bool mcast, bool upcall_result)
{
struct vport *p = OVS_CB(skb)->input_vport;
struct vport_upcall_stats_percpu *stats;
@@ -229,7 +229,10 @@ static void ovs_vport_update_upcall_stats(struct sk_buff *skb,
stats = this_cpu_ptr(p->upcall_stats);
u64_stats_update_begin(&stats->syncp);
if (upcall_result)
- u64_stats_inc(&stats->n_success);
+ if (mcast)
+ u64_stats_inc(&stats->n_mcast);
+ else
+ u64_stats_inc(&stats->n_success);
else
u64_stats_inc(&stats->n_fail);
u64_stats_update_end(&stats->syncp);
@@ -336,7 +339,7 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
else
err = queue_gso_packets(dp, skb, key, upcall_info, cutlen);
- ovs_vport_update_upcall_stats(skb, upcall_info, !err);
+ ovs_vport_update_upcall_stats(skb, upcall_info, mcast, !err);
if (err)
goto err;
@@ -315,6 +315,7 @@ int ovs_vport_get_upcall_stats(struct vport *vport, struct sk_buff *skb)
__u64 tx_success = 0;
__u64 tx_fail = 0;
+ __u64 mcast = 0;
for_each_possible_cpu(i) {
const struct vport_upcall_stats_percpu *stats;
@@ -325,6 +326,7 @@ int ovs_vport_get_upcall_stats(struct vport *vport, struct sk_buff *skb)
start = u64_stats_fetch_begin(&stats->syncp);
tx_success += u64_stats_read(&stats->n_success);
tx_fail += u64_stats_read(&stats->n_fail);
+ mcast += u64_stats_read(&stats->n_mcast);
} while (u64_stats_fetch_retry(&stats->syncp, start));
}
@@ -343,6 +345,12 @@ int ovs_vport_get_upcall_stats(struct vport *vport, struct sk_buff *skb)
nla_nest_cancel(skb, nla);
return -EMSGSIZE;
}
+
+ if (nla_put_u64_64bit(skb, OVS_VPORT_UPCALL_ATTR_MCAST, mcast,
+ OVS_VPORT_ATTR_PAD)) {
+ nla_nest_cancel(skb, nla);
+ return -EMSGSIZE;
+ }
nla_nest_end(skb, nla);
return 0;
@@ -151,6 +151,7 @@ struct vport_upcall_stats_percpu {
struct u64_stats_sync syncp;
u64_stats_t n_success;
u64_stats_t n_fail;
+ u64_stats_t n_mcast;
};
struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *,
If we mix multicasted and unicasted statistics, there could be a serious discrepancy between the stats reported by the kernel and the ones read by userspace, leading to increased confusion. Signed-off-by: Adrian Moreno <amorenoz@redhat.com> --- include/uapi/linux/openvswitch.h | 2 ++ net/openvswitch/datapath.c | 9 ++++++--- net/openvswitch/vport.c | 8 ++++++++ net/openvswitch/vport.h | 1 + 4 files changed, 17 insertions(+), 3 deletions(-)