From e22e1f6725b99007b469fcccdbb48f525f302757 Mon Sep 17 00:00:00 2001 From: wangchuanlei Date: Wed, 18 Jan 2023 20:31:17 -0500 Subject: dpctl: Add support to count upcall packets. Add support to count upcall packets per port, both succeed and failed, which is a better way to see how many packets upcalled on each interface. Acked-by: Eelco Chaudron Signed-off-by: wangchuanlei Signed-off-by: Ilya Maximets --- NEWS | 4 ++++ include/linux/openvswitch.h | 14 ++++++++++++++ include/openvswitch/netdev.h | 4 ++++ lib/dpctl.c | 4 ++++ lib/dpif-netlink.c | 17 +++++++++++++++++ lib/dpif-netlink.h | 2 ++ lib/netdev-linux.c | 24 +++++++++++++----------- vswitchd/bridge.c | 4 +++- 8 files changed, 61 insertions(+), 12 deletions(-) diff --git a/NEWS b/NEWS index 83c126b00..fe6055a27 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,9 @@ Post-v3.1.0 -------------------- + - Linux kernel datapath: + * OVS now collects per-interface upcall statistics that can be obtained + via 'ovs-appctl dpctl/show -s' or the interface's statistics column + in OVSDB. Available with upstream kernel 6.2+. v3.1.0 - xx xxx xxxx diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h index 8bb5abdc8..bc8f74991 100644 --- a/include/linux/openvswitch.h +++ b/include/linux/openvswitch.h @@ -301,11 +301,25 @@ enum ovs_vport_attr { OVS_VPORT_ATTR_PAD, OVS_VPORT_ATTR_IFINDEX, OVS_VPORT_ATTR_NETNSID, + OVS_VPORT_ATTR_UPCALL_STATS, __OVS_VPORT_ATTR_MAX }; #define OVS_VPORT_ATTR_MAX (__OVS_VPORT_ATTR_MAX - 1) +/** + * enum ovs_vport_upcall_attr - attributes for %OVS_VPORT_UPCALL* commands + * @OVS_VPORT_UPCALL_ATTR_SUCCESS: 64-bit upcall success packets. + * @OVS_VPORT_UPCALL_ATTR_FAIL: 64-bit upcall fail packets. + */ +enum ovs_vport_upcall_attr { + OVS_VPORT_UPCALL_ATTR_SUCCESS, + OVS_VPORT_UPCALL_ATTR_FAIL, + __OVS_VPORT_UPCALL_ATTR_MAX, +}; + +#define OVS_VPORT_UPCALL_ATTR_MAX (__OVS_VPORT_UPCALL_ATTR_MAX - 1) + enum { OVS_VXLAN_EXT_UNSPEC, OVS_VXLAN_EXT_GBP, diff --git a/include/openvswitch/netdev.h b/include/openvswitch/netdev.h index cf48f8691..cafd6fd7b 100644 --- a/include/openvswitch/netdev.h +++ b/include/openvswitch/netdev.h @@ -87,6 +87,10 @@ struct netdev_stats { uint64_t rx_oversize_errors; uint64_t rx_fragmented_errors; uint64_t rx_jabber_errors; + + /* Datapath upcall statistics. */ + uint64_t upcall_packets; /* Rx packets forwarded to userspace. */ + uint64_t upcall_errors; /* Rx packets failed forwarding to userspace. */ }; /* Structure representation of custom statistics counter */ diff --git a/lib/dpctl.c b/lib/dpctl.c index d12d9b8a5..c501a0cd7 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -750,6 +750,10 @@ show_dpif(struct dpif *dpif, struct dpctl_params *dpctl_p) print_stat(dpctl_p, " TX bytes:", s.tx_bytes); print_human_size(dpctl_p, s.tx_bytes); dpctl_print(dpctl_p, "\n"); + + print_stat(dpctl_p, " UPCALL packets:", s.upcall_packets); + print_stat(dpctl_p, " errors:", s.upcall_errors); + dpctl_print(dpctl_p, "\n"); } else { dpctl_print(dpctl_p, ", could not retrieve stats (%s)", ovs_strerror(error)); diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 026b0daa8..586fb8893 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -4685,6 +4685,8 @@ dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *vport, .optional = true }, [OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = true }, [OVS_VPORT_ATTR_NETNSID] = { .type = NL_A_U32, .optional = true }, + [OVS_VPORT_ATTR_UPCALL_STATS] = { .type = NL_A_NESTED, + .optional = true }, }; dpif_netlink_vport_init(vport); @@ -4716,6 +4718,21 @@ dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *vport, if (a[OVS_VPORT_ATTR_STATS]) { vport->stats = nl_attr_get(a[OVS_VPORT_ATTR_STATS]); } + if (a[OVS_VPORT_ATTR_UPCALL_STATS]) { + const struct nlattr *nla; + size_t left; + + NL_NESTED_FOR_EACH (nla, left, a[OVS_VPORT_ATTR_UPCALL_STATS]) { + if (nl_attr_type(nla) == OVS_VPORT_UPCALL_ATTR_SUCCESS) { + vport->upcall_success = nl_attr_get_u64(nla); + } else if (nl_attr_type(nla) == OVS_VPORT_UPCALL_ATTR_FAIL) { + vport->upcall_fail = nl_attr_get_u64(nla); + } + } + } else { + vport->upcall_success = UINT64_MAX; + vport->upcall_fail = UINT64_MAX; + } if (a[OVS_VPORT_ATTR_OPTIONS]) { vport->options = nl_attr_get(a[OVS_VPORT_ATTR_OPTIONS]); vport->options_len = nl_attr_get_size(a[OVS_VPORT_ATTR_OPTIONS]); diff --git a/lib/dpif-netlink.h b/lib/dpif-netlink.h index 24294bc42..4909fe160 100644 --- a/lib/dpif-netlink.h +++ b/lib/dpif-netlink.h @@ -44,6 +44,8 @@ struct dpif_netlink_vport { uint32_t n_upcall_pids; const uint32_t *upcall_pids; /* OVS_VPORT_ATTR_UPCALL_PID. */ const struct ovs_vport_stats *stats; /* OVS_VPORT_ATTR_STATS. */ + uint64_t upcall_success; /* OVS_VPORT_UPCALL_ATTR_SUCCESS. */ + uint64_t upcall_fail; /* OVS_VPORT_UPCALL_ATTR_FAIL. */ const struct nlattr *options; /* OVS_VPORT_ATTR_OPTIONS. */ size_t options_len; }; diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 65bdd51db..7c19c4016 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -2156,16 +2156,16 @@ swap_uint64(uint64_t *a, uint64_t *b) * 'src' is allowed to be misaligned. */ static void netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst, - const struct ovs_vport_stats *src) -{ - dst->rx_packets = get_32aligned_u64(&src->rx_packets); - dst->tx_packets = get_32aligned_u64(&src->tx_packets); - dst->rx_bytes = get_32aligned_u64(&src->rx_bytes); - dst->tx_bytes = get_32aligned_u64(&src->tx_bytes); - dst->rx_errors = get_32aligned_u64(&src->rx_errors); - dst->tx_errors = get_32aligned_u64(&src->tx_errors); - dst->rx_dropped = get_32aligned_u64(&src->rx_dropped); - dst->tx_dropped = get_32aligned_u64(&src->tx_dropped); + const struct dpif_netlink_vport *vport) +{ + dst->rx_packets = get_32aligned_u64(&vport->stats->rx_packets); + dst->tx_packets = get_32aligned_u64(&vport->stats->tx_packets); + dst->rx_bytes = get_32aligned_u64(&vport->stats->rx_bytes); + dst->tx_bytes = get_32aligned_u64(&vport->stats->tx_bytes); + dst->rx_errors = get_32aligned_u64(&vport->stats->rx_errors); + dst->tx_errors = get_32aligned_u64(&vport->stats->tx_errors); + dst->rx_dropped = get_32aligned_u64(&vport->stats->rx_dropped); + dst->tx_dropped = get_32aligned_u64(&vport->stats->tx_dropped); dst->multicast = 0; dst->collisions = 0; dst->rx_length_errors = 0; @@ -2179,6 +2179,8 @@ netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst, dst->tx_fifo_errors = 0; dst->tx_heartbeat_errors = 0; dst->tx_window_errors = 0; + dst->upcall_packets = vport->upcall_success; + dst->upcall_errors = vport->upcall_fail; } static int @@ -2196,7 +2198,7 @@ get_stats_via_vport__(const struct netdev *netdev, struct netdev_stats *stats) return EOPNOTSUPP; } - netdev_stats_from_ovs_vport_stats(stats, reply.stats); + netdev_stats_from_ovs_vport_stats(stats, &reply); ofpbuf_delete(buf); diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index bfb2adef1..abf2afe57 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -2626,7 +2626,9 @@ iface_refresh_stats(struct iface *iface) IFACE_STAT(rx_undersized_errors, "rx_undersized_errors") \ IFACE_STAT(rx_oversize_errors, "rx_oversize_errors") \ IFACE_STAT(rx_fragmented_errors, "rx_fragmented_errors") \ - IFACE_STAT(rx_jabber_errors, "rx_jabber_errors") + IFACE_STAT(rx_jabber_errors, "rx_jabber_errors") \ + IFACE_STAT(upcall_packets, "upcall_packets") \ + IFACE_STAT(upcall_errors, "upcall_errors") #define IFACE_STAT(MEMBER, NAME) + 1 enum { N_IFACE_STATS = IFACE_STATS }; -- cgit v1.2.1