This series introduces stats counters for psp. Device key rotations, and so called 'stale-events' are common to all drivers and are tracked by the core.
A driver facing api is provided for reporting stats required by the "Implementation Requirements" section of the PSP Architecture Specification. Drivers must implement these stats.
Lastly, implementations of the driver stats api for mlx5 and netdevsim are included.
Here is the output of running the psp selftest suite and then printing out stats with the ynl cli on system with a psp-capable CX7:
$ ./ksft-psp-stats/drivers/net/psp.py TAP version 13 1..28 ok 1 psp.test_case # SKIP Test requires IPv4 connectivity ok 2 psp.data_basic_send_v0_ip6 ok 3 psp.test_case # SKIP Test requires IPv4 connectivity ok 4 psp.data_basic_send_v1_ip6 ok 5 psp.test_case # SKIP Test requires IPv4 connectivity ok 6 psp.data_basic_send_v2_ip6 # SKIP ('PSP version not supported', 'hdr0-aes-gmac-128') ok 7 psp.test_case # SKIP Test requires IPv4 connectivity ok 8 psp.data_basic_send_v3_ip6 # SKIP ('PSP version not supported', 'hdr0-aes-gmac-256') ok 9 psp.test_case # SKIP Test requires IPv4 connectivity ok 10 psp.data_mss_adjust_ip6 ok 11 psp.dev_list_devices ok 12 psp.dev_get_device ok 13 psp.dev_get_device_bad ok 14 psp.dev_rotate ok 15 psp.dev_rotate_spi ok 16 psp.assoc_basic ok 17 psp.assoc_bad_dev ok 18 psp.assoc_sk_only_conn ok 19 psp.assoc_sk_only_mismatch ok 20 psp.assoc_sk_only_mismatch_tx ok 21 psp.assoc_sk_only_unconn ok 22 psp.assoc_version_mismatch ok 23 psp.assoc_twice ok 24 psp.data_send_bad_key ok 25 psp.data_send_disconnect ok 26 psp.data_stale_key ok 27 psp.removal_device_rx # XFAIL Test only works on netdevsim ok 28 psp.removal_device_bi # XFAIL Test only works on netdevsim # Totals: pass:19 fail:0 xfail:2 xpass:0 skip:7 error:0 # # Responder logs (0): # STDERR: # Set PSP enable on device 1 to 0x3 # Set PSP enable on device 1 to 0x0
$ cd ynl/ $ ./pyynl/cli.py --spec netlink/specs/psp.yaml --dump get-stats [{'dev-id': 1, 'key-rotations': 5, 'rx-auth-fail': 21, 'rx-bad': 0, 'rx-bytes': 11844, 'rx-error': 0, 'rx-packets': 94, 'stale-events': 6, 'tx-bytes': 1128456, 'tx-error': 0, 'tx-packets': 780}]
Daniel Zahka (2): selftests: drv-net: psp: add assertions on core-tracked psp dev stats netdevsim: implement psp device stats
Jakub Kicinski (3): psp: report basic stats from the core psp: add stats from psp spec to driver facing api net/mlx5e: Add PSP stats support for Rx/Tx flows
Documentation/netlink/specs/psp.yaml | 95 +++++++ .../mellanox/mlx5/core/en_accel/psp.c | 239 ++++++++++++++++-- .../mellanox/mlx5/core/en_accel/psp.h | 18 ++ .../mellanox/mlx5/core/en_accel/psp_rxtx.c | 1 + .../net/ethernet/mellanox/mlx5/core/en_main.c | 5 + drivers/net/netdevsim/netdevsim.h | 5 + drivers/net/netdevsim/psp.c | 27 ++ include/net/psp/types.h | 35 +++ include/uapi/linux/psp.h | 18 ++ net/psp/psp-nl-gen.c | 19 ++ net/psp/psp-nl-gen.h | 2 + net/psp/psp_main.c | 3 +- net/psp/psp_nl.c | 99 ++++++++ net/psp/psp_sock.c | 4 +- tools/testing/selftests/drivers/net/psp.py | 13 + 15 files changed, 566 insertions(+), 17 deletions(-)
From: Jakub Kicinski kuba@kernel.org
Track and report stats common to all psp devices from the core. A 'stale-event' is when the core marks the rx state of an active psp_assoc as incapable of authenticating psp encapsulated data.
Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Daniel Zahka daniel.zahka@gmail.com --- Documentation/netlink/specs/psp.yaml | 40 ++++++++++++++ include/net/psp/types.h | 9 ++++ include/uapi/linux/psp.h | 10 ++++ net/psp/psp-nl-gen.c | 19 +++++++ net/psp/psp-nl-gen.h | 2 + net/psp/psp_nl.c | 79 ++++++++++++++++++++++++++++ net/psp/psp_sock.c | 4 +- 7 files changed, 162 insertions(+), 1 deletion(-)
diff --git a/Documentation/netlink/specs/psp.yaml b/Documentation/netlink/specs/psp.yaml index 944429e5c9a8..914148221384 100644 --- a/Documentation/netlink/specs/psp.yaml +++ b/Documentation/netlink/specs/psp.yaml @@ -76,6 +76,28 @@ attribute-sets: name: spi doc: Security Parameters Index (SPI) of the association. type: u32 + - + name: stats + attributes: + - + name: dev-id + doc: PSP device ID. + type: u32 + checks: + min: 1 + - + name: key-rotations + type: uint + doc: | + Number of key rotations during the lifetime of the device. + Kernel statistic. + - + name: stale-events + type: uint + doc: | + Number of times a socket's Rx got shut down due to using + a key which went stale (fully rotated out). + Kernel statistic.
operations: list: @@ -177,6 +199,24 @@ operations: pre: psp-assoc-device-get-locked post: psp-device-unlock
+ - + name: get-stats + doc: Get device statistics. + attribute-set: stats + do: + request: + attributes: + - dev-id + reply: &stats-all + attributes: + - dev-id + - key-rotations + - stale-events + pre: psp-device-get-locked + post: psp-device-unlock + dump: + reply: *stats-all + mcast-groups: list: - diff --git a/include/net/psp/types.h b/include/net/psp/types.h index 31cee64b7c86..5b0ccaac3882 100644 --- a/include/net/psp/types.h +++ b/include/net/psp/types.h @@ -59,6 +59,10 @@ struct psp_dev_config { * device key * @stale_assocs: associations which use a rotated out key * + * @stats: statistics maintained by the core + * @stats.rotations: See stats attr key-rotations + * @stats.stales: See stats attr stale-events + * * @rcu: RCU head for freeing the structure */ struct psp_dev { @@ -81,6 +85,11 @@ struct psp_dev { struct list_head prev_assocs; struct list_head stale_assocs;
+ struct { + unsigned long rotations; + unsigned long stales; + } stats; + struct rcu_head rcu; };
diff --git a/include/uapi/linux/psp.h b/include/uapi/linux/psp.h index 607c42c39ba5..31592760ad79 100644 --- a/include/uapi/linux/psp.h +++ b/include/uapi/linux/psp.h @@ -45,6 +45,15 @@ enum { PSP_A_KEYS_MAX = (__PSP_A_KEYS_MAX - 1) };
+enum { + PSP_A_STATS_DEV_ID = 1, + PSP_A_STATS_KEY_ROTATIONS, + PSP_A_STATS_STALE_EVENTS, + + __PSP_A_STATS_MAX, + PSP_A_STATS_MAX = (__PSP_A_STATS_MAX - 1) +}; + enum { PSP_CMD_DEV_GET = 1, PSP_CMD_DEV_ADD_NTF, @@ -55,6 +64,7 @@ enum { PSP_CMD_KEY_ROTATE_NTF, PSP_CMD_RX_ASSOC, PSP_CMD_TX_ASSOC, + PSP_CMD_GET_STATS,
__PSP_CMD_MAX, PSP_CMD_MAX = (__PSP_CMD_MAX - 1) diff --git a/net/psp/psp-nl-gen.c b/net/psp/psp-nl-gen.c index 9fdd6f831803..73f8b06d66f0 100644 --- a/net/psp/psp-nl-gen.c +++ b/net/psp/psp-nl-gen.c @@ -47,6 +47,11 @@ static const struct nla_policy psp_tx_assoc_nl_policy[PSP_A_ASSOC_SOCK_FD + 1] = [PSP_A_ASSOC_SOCK_FD] = { .type = NLA_U32, }, };
+/* PSP_CMD_GET_STATS - do */ +static const struct nla_policy psp_get_stats_nl_policy[PSP_A_STATS_DEV_ID + 1] = { + [PSP_A_STATS_DEV_ID] = NLA_POLICY_MIN(NLA_U32, 1), +}; + /* Ops table for psp */ static const struct genl_split_ops psp_nl_ops[] = { { @@ -99,6 +104,20 @@ static const struct genl_split_ops psp_nl_ops[] = { .maxattr = PSP_A_ASSOC_SOCK_FD, .flags = GENL_CMD_CAP_DO, }, + { + .cmd = PSP_CMD_GET_STATS, + .pre_doit = psp_device_get_locked, + .doit = psp_nl_get_stats_doit, + .post_doit = psp_device_unlock, + .policy = psp_get_stats_nl_policy, + .maxattr = PSP_A_STATS_DEV_ID, + .flags = GENL_CMD_CAP_DO, + }, + { + .cmd = PSP_CMD_GET_STATS, + .dumpit = psp_nl_get_stats_dumpit, + .flags = GENL_CMD_CAP_DUMP, + }, };
static const struct genl_multicast_group psp_nl_mcgrps[] = { diff --git a/net/psp/psp-nl-gen.h b/net/psp/psp-nl-gen.h index 25268ed11fb5..5bc3b5d5a53e 100644 --- a/net/psp/psp-nl-gen.h +++ b/net/psp/psp-nl-gen.h @@ -28,6 +28,8 @@ int psp_nl_dev_set_doit(struct sk_buff *skb, struct genl_info *info); int psp_nl_key_rotate_doit(struct sk_buff *skb, struct genl_info *info); int psp_nl_rx_assoc_doit(struct sk_buff *skb, struct genl_info *info); int psp_nl_tx_assoc_doit(struct sk_buff *skb, struct genl_info *info); +int psp_nl_get_stats_doit(struct sk_buff *skb, struct genl_info *info); +int psp_nl_get_stats_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
enum { PSP_NLGRP_MGMT, diff --git a/net/psp/psp_nl.c b/net/psp/psp_nl.c index 8aaca62744c3..094da52e357e 100644 --- a/net/psp/psp_nl.c +++ b/net/psp/psp_nl.c @@ -262,6 +262,7 @@ int psp_nl_key_rotate_doit(struct sk_buff *skb, struct genl_info *info) psd->generation & ~PSP_GEN_VALID_MASK);
psp_assocs_key_rotated(psd); + psd->stats.rotations++;
nlmsg_end(ntf, (struct nlmsghdr *)ntf->data); genlmsg_multicast_netns(&psp_nl_family, dev_net(psd->main_netdev), ntf, @@ -503,3 +504,81 @@ int psp_nl_tx_assoc_doit(struct sk_buff *skb, struct genl_info *info) nlmsg_free(rsp); return err; } + +static int +psp_nl_stats_fill(struct psp_dev *psd, struct sk_buff *rsp, + const struct genl_info *info) +{ + void *hdr; + + hdr = genlmsg_iput(rsp, info); + if (!hdr) + return -EMSGSIZE; + + if (nla_put_u32(rsp, PSP_A_STATS_DEV_ID, psd->id) || + nla_put_uint(rsp, PSP_A_STATS_KEY_ROTATIONS, + psd->stats.rotations) || + nla_put_uint(rsp, PSP_A_STATS_STALE_EVENTS, psd->stats.stales)) + goto err_cancel_msg; + + genlmsg_end(rsp, hdr); + return 0; + +err_cancel_msg: + genlmsg_cancel(rsp, hdr); + return -EMSGSIZE; +} + +int psp_nl_get_stats_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct psp_dev *psd = info->user_ptr[0]; + struct sk_buff *rsp; + int err; + + rsp = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!rsp) + return -ENOMEM; + + err = psp_nl_stats_fill(psd, rsp, info); + if (err) + goto err_free_msg; + + return genlmsg_reply(rsp, info); + +err_free_msg: + nlmsg_free(rsp); + return err; +} + +static int +psp_nl_stats_get_dumpit_one(struct sk_buff *rsp, struct netlink_callback *cb, + struct psp_dev *psd) +{ + if (psp_dev_check_access(psd, sock_net(rsp->sk))) + return 0; + + return psp_nl_stats_fill(psd, rsp, genl_info_dump(cb)); +} + +int psp_nl_get_stats_dumpit(struct sk_buff *rsp, struct netlink_callback *cb) +{ + struct psp_dev *psd; + unsigned long index; + int err = 0; + + mutex_lock(&psp_devs_lock); + xa_for_each_start(&psp_devs, index, psd, cb->args[0]) { + mutex_lock(&psd->lock); + err = psp_nl_stats_get_dumpit_one(rsp, cb, psd); + mutex_unlock(&psd->lock); + if (err) + break; + } + mutex_unlock(&psp_devs_lock); + + if (err != -EMSGSIZE) + return err; + + cb->args[0] = index; + return err; +} diff --git a/net/psp/psp_sock.c b/net/psp/psp_sock.c index a931d825d1cc..f785672b7df6 100644 --- a/net/psp/psp_sock.c +++ b/net/psp/psp_sock.c @@ -253,8 +253,10 @@ void psp_assocs_key_rotated(struct psp_dev *psd) /* Mark the stale associations as invalid, they will no longer * be able to Rx any traffic. */ - list_for_each_entry_safe(pas, next, &psd->prev_assocs, assocs_list) + list_for_each_entry_safe(pas, next, &psd->prev_assocs, assocs_list) { pas->generation |= ~PSP_GEN_VALID_MASK; + psd->stats.stales++; + } list_splice_init(&psd->prev_assocs, &psd->stale_assocs); list_splice_init(&psd->active_assocs, &psd->prev_assocs);
Add assertions to existing test cases to cover key rotations and 'stale-events'.
Signed-off-by: Daniel Zahka daniel.zahka@gmail.com --- tools/testing/selftests/drivers/net/psp.py | 13 +++++++++++++ 1 file changed, 13 insertions(+)
diff --git a/tools/testing/selftests/drivers/net/psp.py b/tools/testing/selftests/drivers/net/psp.py index 4ae7a785ff10..06559ef49b9a 100755 --- a/tools/testing/selftests/drivers/net/psp.py +++ b/tools/testing/selftests/drivers/net/psp.py @@ -109,6 +109,10 @@ def _check_data_outq(s, exp_len, force_wait=False): time.sleep(0.01) ksft_eq(outq, exp_len)
+ +def _get_stat(cfg, key): + return cfg.pspnl.get_stats({'dev-id': cfg.psp_dev_id})[key] + # # Test case boiler plate # @@ -171,11 +175,16 @@ def dev_rotate(cfg): """ Test key rotation """ _init_psp_dev(cfg)
+ prev_rotations = _get_stat(cfg, 'key-rotations') + rot = cfg.pspnl.key_rotate({"id": cfg.psp_dev_id}) ksft_eq(rot['id'], cfg.psp_dev_id) rot = cfg.pspnl.key_rotate({"id": cfg.psp_dev_id}) ksft_eq(rot['id'], cfg.psp_dev_id)
+ cur_rotations = _get_stat(cfg, 'key-rotations') + ksft_eq(cur_rotations, prev_rotations + 2) +
def dev_rotate_spi(cfg): """ Test key rotation and SPI check """ @@ -475,6 +484,7 @@ def data_stale_key(cfg): """ Test send on a double-rotated key """ _init_psp_dev(cfg)
+ prev_stale = _get_stat(cfg, 'stale-events') s = _make_psp_conn(cfg) try: rx_assoc = cfg.pspnl.rx_assoc({"version": 0, @@ -495,6 +505,9 @@ def data_stale_key(cfg): cfg.pspnl.key_rotate({"id": cfg.psp_dev_id}) cfg.pspnl.key_rotate({"id": cfg.psp_dev_id})
+ cur_stale = _get_stat(cfg, 'stale-events') + ksft_gt(cur_stale, prev_stale) + s.send(b'0123456789' * 200) _check_data_outq(s, 2000, force_wait=True) finally:
From: Jakub Kicinski kuba@kernel.org
Provide a driver api for reporting device statistics required by the "Implementation Requirements" section of the PSP Architecture Specification. Use a warning to ensure drivers report stats required by the spec.
Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Daniel Zahka daniel.zahka@gmail.com --- Documentation/netlink/specs/psp.yaml | 55 ++++++++++++++++++++++++++++ include/net/psp/types.h | 26 +++++++++++++ include/uapi/linux/psp.h | 8 ++++ net/psp/psp_main.c | 3 +- net/psp/psp_nl.c | 22 ++++++++++- 5 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/Documentation/netlink/specs/psp.yaml b/Documentation/netlink/specs/psp.yaml index 914148221384..f3a57782d2cf 100644 --- a/Documentation/netlink/specs/psp.yaml +++ b/Documentation/netlink/specs/psp.yaml @@ -98,6 +98,61 @@ attribute-sets: Number of times a socket's Rx got shut down due to using a key which went stale (fully rotated out). Kernel statistic. + - + name: rx-packets + type: uint + doc: | + Number of successfully processed and authenticated PSP packets. + Device statistic (from the PSP spec). + - + name: rx-bytes + type: uint + doc: | + Number of successfully authenticated PSP bytes received, counting from + the first byte after the IV through the last byte of payload. + The fixed initial portion of the PSP header (16 bytes) + and the PSP trailer/ICV (16 bytes) are not included in this count. + Device statistic (from the PSP spec). + - + name: rx-auth-fail + type: uint + doc: | + Number of received PSP packets with unsuccessful authentication. + Device statistic (from the PSP spec). + - + name: rx-error + type: uint + doc: | + Number of received PSP packets with length/framing errors. + Device statistic (from the PSP spec). + - + name: rx-bad + type: uint + doc: | + Number of received PSP packets with miscellaneous errors + (invalid master key indicated by SPI, unsupported version, etc.) + Device statistic (from the PSP spec). + - + name: tx-packets + type: uint + doc: | + Number of successfully processed PSP packets for transmission. + Device statistic (from the PSP spec). + - + name: tx-bytes + type: uint + doc: | + Number of successfully processed PSP bytes for transmit, counting from + the first byte after the IV through the last byte of payload. + The fixed initial portion of the PSP header (16 bytes) + and the PSP trailer/ICV (16 bytes) are not included in this count. + Device statistic (from the PSP spec). + - + name: tx-error + type: uint + doc: | + Number of PSP packets for transmission with errors. + Device statistic (from the PSP spec).
operations: list: diff --git a/include/net/psp/types.h b/include/net/psp/types.h index 5b0ccaac3882..1aa3857a85c1 100644 --- a/include/net/psp/types.h +++ b/include/net/psp/types.h @@ -150,6 +150,25 @@ struct psp_assoc { u8 drv_data[] __aligned(8); };
+struct psp_dev_stats { + union { + struct { + u64 rx_packets; + u64 rx_bytes; + u64 rx_auth_fail; + u64 rx_error; + u64 rx_bad; + u64 tx_packets; + u64 tx_bytes; + u64 tx_error; + }; + DECLARE_FLEX_ARRAY(u64, required); + }; + char required_end[0]; + + /* optional stats would go here */ +}; + /** * struct psp_dev_ops - netdev driver facing PSP callbacks */ @@ -188,6 +207,13 @@ struct psp_dev_ops { * Remove an association from the device. */ void (*tx_key_del)(struct psp_dev *psd, struct psp_assoc *pas); + + /** + * @get_stats: get statistics from the device + * Stats required by the spec must be maintained and filled in. + * Stats must be filled in member-by-member, never memset the struct. + */ + void (*get_stats)(struct psp_dev *psd, struct psp_dev_stats *stats); };
#endif /* __NET_PSP_H */ diff --git a/include/uapi/linux/psp.h b/include/uapi/linux/psp.h index 31592760ad79..d8449c043ba1 100644 --- a/include/uapi/linux/psp.h +++ b/include/uapi/linux/psp.h @@ -49,6 +49,14 @@ enum { PSP_A_STATS_DEV_ID = 1, PSP_A_STATS_KEY_ROTATIONS, PSP_A_STATS_STALE_EVENTS, + PSP_A_STATS_RX_PACKETS, + PSP_A_STATS_RX_BYTES, + PSP_A_STATS_RX_AUTH_FAIL, + PSP_A_STATS_RX_ERROR, + PSP_A_STATS_RX_BAD, + PSP_A_STATS_TX_PACKETS, + PSP_A_STATS_TX_BYTES, + PSP_A_STATS_TX_ERROR,
__PSP_A_STATS_MAX, PSP_A_STATS_MAX = (__PSP_A_STATS_MAX - 1) diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c index 481aaf0fc9fc..a8534124f626 100644 --- a/net/psp/psp_main.c +++ b/net/psp/psp_main.c @@ -60,7 +60,8 @@ psp_dev_create(struct net_device *netdev, !psd_ops->key_rotate || !psd_ops->rx_spi_alloc || !psd_ops->tx_key_add || - !psd_ops->tx_key_del)) + !psd_ops->tx_key_del || + !psd_ops->get_stats)) return ERR_PTR(-EINVAL);
psd = kzalloc(sizeof(*psd), GFP_KERNEL); diff --git a/net/psp/psp_nl.c b/net/psp/psp_nl.c index 094da52e357e..9fe683c952f9 100644 --- a/net/psp/psp_nl.c +++ b/net/psp/psp_nl.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only
+#include <linux/ethtool.h> #include <linux/skbuff.h> #include <linux/xarray.h> #include <net/genetlink.h> @@ -509,7 +510,18 @@ static int psp_nl_stats_fill(struct psp_dev *psd, struct sk_buff *rsp, const struct genl_info *info) { + const unsigned int required_cnt = offsetof(struct psp_dev_stats, + required_end) / sizeof(u64); + struct psp_dev_stats stats; void *hdr; + int i; + + memset(&stats, 0xff, sizeof(stats)); + psd->ops->get_stats(psd, &stats); + + for (i = 0; i < required_cnt; i++) + if (WARN_ON_ONCE(stats.required[i] == ETHTOOL_STAT_NOT_SET)) + return -EOPNOTSUPP;
hdr = genlmsg_iput(rsp, info); if (!hdr) @@ -518,7 +530,15 @@ psp_nl_stats_fill(struct psp_dev *psd, struct sk_buff *rsp, if (nla_put_u32(rsp, PSP_A_STATS_DEV_ID, psd->id) || nla_put_uint(rsp, PSP_A_STATS_KEY_ROTATIONS, psd->stats.rotations) || - nla_put_uint(rsp, PSP_A_STATS_STALE_EVENTS, psd->stats.stales)) + nla_put_uint(rsp, PSP_A_STATS_STALE_EVENTS, psd->stats.stales) || + nla_put_uint(rsp, PSP_A_STATS_RX_PACKETS, stats.rx_packets) || + nla_put_uint(rsp, PSP_A_STATS_RX_BYTES, stats.rx_bytes) || + nla_put_uint(rsp, PSP_A_STATS_RX_AUTH_FAIL, stats.rx_auth_fail) || + nla_put_uint(rsp, PSP_A_STATS_RX_ERROR, stats.rx_error) || + nla_put_uint(rsp, PSP_A_STATS_RX_BAD, stats.rx_bad) || + nla_put_uint(rsp, PSP_A_STATS_TX_PACKETS, stats.tx_packets) || + nla_put_uint(rsp, PSP_A_STATS_TX_BYTES, stats.tx_bytes) || + nla_put_uint(rsp, PSP_A_STATS_TX_ERROR, stats.tx_error)) goto err_cancel_msg;
genlmsg_end(rsp, hdr);
From: Jakub Kicinski kuba@kernel.org
Add all statistics described under the "Implementation Requirements" section of the PSP Architecture Specification:
Rx successfully decrypted PSP packets: psp_rx_pkts : Number of packets decrypted successfully psp_rx_bytes : Number of bytes decrypted successfully
Rx PSP authentication failure statistics: psp_rx_pkts_auth_fail : Number of PSP packets that failed authentication psp_rx_bytes_auth_fail : Number of PSP bytes that failed authentication
Rx PSP bad frame error statistics: psp_rx_pkts_frame_err; psp_rx_bytes_frame_err;
Rx PSP drop statistics: psp_rx_pkts_drop : Number of PSP packets dropped psp_rx_bytes_drop : Number of PSP bytes dropped
Tx successfully encrypted PSP packets: psp_tx_pkts : Number of packets encrypted successfully psp_tx_bytes : Number of bytes encrypted successfully
Tx drops: tx_drop : Number of misc psp related drops
The above can be seen using the ynl cli: ./pyynl/cli.py --spec netlink/specs/psp.yaml --dump get-stats
Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Raed Salem raeds@nvidia.com Signed-off-by: Rahul Rameshbabu rrameshbabu@nvidia.com Signed-off-by: Daniel Zahka daniel.zahka@gmail.com --- .../mellanox/mlx5/core/en_accel/psp.c | 239 ++++++++++++++++-- .../mellanox/mlx5/core/en_accel/psp.h | 18 ++ .../mellanox/mlx5/core/en_accel/psp_rxtx.c | 1 + .../net/ethernet/mellanox/mlx5/core/en_main.c | 5 + 4 files changed, 248 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.c index 8565cfe8d7dc..93c8f1f19d6b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.c @@ -28,12 +28,15 @@ struct mlx5e_psp_tx { struct mlx5_flow_handle *rule; struct mutex mutex; /* Protect PSP TX steering */ u32 refcnt; + struct mlx5_fc *tx_counter; };
struct mlx5e_psp_rx_err { struct mlx5_flow_table *ft; struct mlx5_flow_handle *rule; - struct mlx5_flow_handle *drop_rule; + struct mlx5_flow_handle *auth_fail_rule; + struct mlx5_flow_handle *err_rule; + struct mlx5_flow_handle *bad_rule; struct mlx5_modify_hdr *copy_modify_hdr; };
@@ -50,6 +53,10 @@ struct mlx5e_accel_fs_psp_prot {
struct mlx5e_accel_fs_psp { struct mlx5e_accel_fs_psp_prot fs_prot[ACCEL_FS_PSP_NUM_TYPES]; + struct mlx5_fc *rx_counter; + struct mlx5_fc *rx_auth_fail_counter; + struct mlx5_fc *rx_err_counter; + struct mlx5_fc *rx_bad_counter; };
struct mlx5e_psp_fs { @@ -72,9 +79,19 @@ static enum mlx5_traffic_types fs_psp2tt(enum accel_fs_psp_type i) static void accel_psp_fs_rx_err_del_rules(struct mlx5e_psp_fs *fs, struct mlx5e_psp_rx_err *rx_err) { - if (rx_err->drop_rule) { - mlx5_del_flow_rules(rx_err->drop_rule); - rx_err->drop_rule = NULL; + if (rx_err->bad_rule) { + mlx5_del_flow_rules(rx_err->bad_rule); + rx_err->bad_rule = NULL; + } + + if (rx_err->err_rule) { + mlx5_del_flow_rules(rx_err->err_rule); + rx_err->err_rule = NULL; + } + + if (rx_err->auth_fail_rule) { + mlx5_del_flow_rules(rx_err->auth_fail_rule); + rx_err->auth_fail_rule = NULL; }
if (rx_err->rule) { @@ -117,6 +134,7 @@ static int accel_psp_fs_rx_err_add_rule(struct mlx5e_psp_fs *fs, { u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; struct mlx5_core_dev *mdev = fs->mdev; + struct mlx5_flow_destination dest[2]; struct mlx5_flow_act flow_act = {}; struct mlx5_modify_hdr *modify_hdr; struct mlx5_flow_handle *fte; @@ -147,10 +165,14 @@ static int accel_psp_fs_rx_err_add_rule(struct mlx5e_psp_fs *fs, accel_psp_setup_syndrome_match(spec, PSP_OK); /* create fte */ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_MOD_HDR | - MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | + MLX5_FLOW_CONTEXT_ACTION_COUNT; flow_act.modify_hdr = modify_hdr; - fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, - &fs_prot->default_dest, 1); + dest[0].type = fs_prot->default_dest.type; + dest[0].ft = fs_prot->default_dest.ft; + dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest[1].counter = fs->rx_fs->rx_counter; + fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, dest, 2); if (IS_ERR(fte)) { err = PTR_ERR(fte); mlx5_core_err(mdev, "fail to add psp rx err copy rule err=%d\n", err); @@ -158,22 +180,69 @@ static int accel_psp_fs_rx_err_add_rule(struct mlx5e_psp_fs *fs, } rx_err->rule = fte;
- /* add default drop rule */ + /* add auth fail drop rule */ memset(spec, 0, sizeof(*spec)); memset(&flow_act, 0, sizeof(flow_act)); + accel_psp_setup_syndrome_match(spec, PSP_ICV_FAIL); /* create fte */ - flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; - fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, NULL, 0); + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | + MLX5_FLOW_CONTEXT_ACTION_COUNT; + dest[0].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest[0].counter = fs->rx_fs->rx_auth_fail_counter; + fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, dest, 1); if (IS_ERR(fte)) { err = PTR_ERR(fte); - mlx5_core_err(mdev, "fail to add psp rx err drop rule err=%d\n", err); + mlx5_core_err(mdev, "fail to add psp rx auth fail drop rule err=%d\n", + err); goto out_drop_rule; } - rx_err->drop_rule = fte; + rx_err->auth_fail_rule = fte; + + /* add framing drop rule */ + memset(spec, 0, sizeof(*spec)); + memset(&flow_act, 0, sizeof(flow_act)); + accel_psp_setup_syndrome_match(spec, PSP_BAD_TRAILER); + /* create fte */ + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | + MLX5_FLOW_CONTEXT_ACTION_COUNT; + dest[0].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest[0].counter = fs->rx_fs->rx_err_counter; + fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, dest, 1); + if (IS_ERR(fte)) { + err = PTR_ERR(fte); + mlx5_core_err(mdev, "fail to add psp rx framing err drop rule err=%d\n", + err); + goto out_drop_auth_fail_rule; + } + rx_err->err_rule = fte; + + /* add misc. errors drop rule */ + memset(spec, 0, sizeof(*spec)); + memset(&flow_act, 0, sizeof(flow_act)); + /* create fte */ + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | + MLX5_FLOW_CONTEXT_ACTION_COUNT; + dest[0].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest[0].counter = fs->rx_fs->rx_bad_counter; + fte = mlx5_add_flow_rules(rx_err->ft, spec, &flow_act, dest, 1); + if (IS_ERR(fte)) { + err = PTR_ERR(fte); + mlx5_core_err(mdev, "fail to add psp rx misc. err drop rule err=%d\n", + err); + goto out_drop_error_rule; + } + rx_err->bad_rule = fte; + rx_err->copy_modify_hdr = modify_hdr;
goto out_spec;
+out_drop_error_rule: + mlx5_del_flow_rules(rx_err->err_rule); + rx_err->err_rule = NULL; +out_drop_auth_fail_rule: + mlx5_del_flow_rules(rx_err->auth_fail_rule); + rx_err->auth_fail_rule = NULL; out_drop_rule: mlx5_del_flow_rules(rx_err->rule); rx_err->rule = NULL; @@ -461,6 +530,10 @@ static void accel_psp_fs_cleanup_rx(struct mlx5e_psp_fs *fs) return;
accel_psp = fs->rx_fs; + mlx5_fc_destroy(fs->mdev, accel_psp->rx_bad_counter); + mlx5_fc_destroy(fs->mdev, accel_psp->rx_err_counter); + mlx5_fc_destroy(fs->mdev, accel_psp->rx_auth_fail_counter); + mlx5_fc_destroy(fs->mdev, accel_psp->rx_counter); for (i = 0; i < ACCEL_FS_PSP_NUM_TYPES; i++) { fs_prot = &accel_psp->fs_prot[i]; mutex_destroy(&fs_prot->prot_mutex); @@ -474,7 +547,10 @@ static int accel_psp_fs_init_rx(struct mlx5e_psp_fs *fs) { struct mlx5e_accel_fs_psp_prot *fs_prot; struct mlx5e_accel_fs_psp *accel_psp; + struct mlx5_core_dev *mdev = fs->mdev; + struct mlx5_fc *flow_counter; enum accel_fs_psp_type i; + int err;
accel_psp = kzalloc(sizeof(*accel_psp), GFP_KERNEL); if (!accel_psp) @@ -485,9 +561,68 @@ static int accel_psp_fs_init_rx(struct mlx5e_psp_fs *fs) mutex_init(&fs_prot->prot_mutex); }
+ flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + mlx5_core_warn(mdev, + "fail to create psp rx flow counter err(%ld)\n", + PTR_ERR(flow_counter)); + err = PTR_ERR(flow_counter); + goto out_err; + } + accel_psp->rx_counter = flow_counter; + + flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + mlx5_core_warn(mdev, + "fail to create psp rx auth fail flow counter err(%ld)\n", + PTR_ERR(flow_counter)); + err = PTR_ERR(flow_counter); + goto out_counter_err; + } + accel_psp->rx_auth_fail_counter = flow_counter; + + flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + mlx5_core_warn(mdev, + "fail to create psp rx error flow counter err(%ld)\n", + PTR_ERR(flow_counter)); + err = PTR_ERR(flow_counter); + goto out_auth_fail_counter_err; + } + accel_psp->rx_err_counter = flow_counter; + + flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + mlx5_core_warn(mdev, + "fail to create psp rx auth fail flow counter err(%ld)\n", + PTR_ERR(flow_counter)); + err = PTR_ERR(flow_counter); + goto out_err_counter_err; + } + accel_psp->rx_bad_counter = flow_counter; + fs->rx_fs = accel_psp;
return 0; + +out_err_counter_err: + mlx5_fc_destroy(mdev, accel_psp->rx_err_counter); + accel_psp->rx_err_counter = NULL; +out_auth_fail_counter_err: + mlx5_fc_destroy(mdev, accel_psp->rx_auth_fail_counter); + accel_psp->rx_auth_fail_counter = NULL; +out_counter_err: + mlx5_fc_destroy(mdev, accel_psp->rx_counter); + accel_psp->rx_counter = NULL; +out_err: + for (i = 0; i < ACCEL_FS_PSP_NUM_TYPES; i++) { + fs_prot = &accel_psp->fs_prot[i]; + mutex_destroy(&fs_prot->prot_mutex); + } + kfree(accel_psp); + fs->rx_fs = NULL; + + return err; }
void mlx5_accel_psp_fs_cleanup_rx_tables(struct mlx5e_priv *priv) @@ -532,6 +667,7 @@ static int accel_psp_fs_tx_create_ft_table(struct mlx5e_psp_fs *fs) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); struct mlx5_flow_table_attr ft_attr = {}; + struct mlx5_flow_destination dest = {}; struct mlx5_core_dev *mdev = fs->mdev; struct mlx5_flow_act flow_act = {}; u32 *in, *mc, *outer_headers_c; @@ -580,8 +716,11 @@ static int accel_psp_fs_tx_create_ft_table(struct mlx5e_psp_fs *fs) flow_act.crypto.type = MLX5_FLOW_CONTEXT_ENCRYPT_DECRYPT_TYPE_PSP; flow_act.flags |= FLOW_ACT_NO_APPEND; flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW | - MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT; - rule = mlx5_add_flow_rules(ft, spec, &flow_act, NULL, 0); + MLX5_FLOW_CONTEXT_ACTION_CRYPTO_ENCRYPT | + MLX5_FLOW_CONTEXT_ACTION_COUNT; + dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; + dest.counter = tx_fs->tx_counter; + rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); if (IS_ERR(rule)) { err = PTR_ERR(rule); mlx5_core_err(mdev, "PSP: fail to add psp tx flow rule, err = %d\n", err); @@ -650,6 +789,7 @@ static void accel_psp_fs_cleanup_tx(struct mlx5e_psp_fs *fs) if (!tx_fs) return;
+ mlx5_fc_destroy(fs->mdev, tx_fs->tx_counter); mutex_destroy(&tx_fs->mutex); WARN_ON(tx_fs->refcnt); kfree(tx_fs); @@ -658,10 +798,13 @@ static void accel_psp_fs_cleanup_tx(struct mlx5e_psp_fs *fs)
static int accel_psp_fs_init_tx(struct mlx5e_psp_fs *fs) { + struct mlx5_core_dev *mdev = fs->mdev; struct mlx5_flow_namespace *ns; + struct mlx5_fc *flow_counter; struct mlx5e_psp_tx *tx_fs; + int err;
- ns = mlx5_get_flow_namespace(fs->mdev, MLX5_FLOW_NAMESPACE_EGRESS_IPSEC); + ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_EGRESS_IPSEC); if (!ns) return -EOPNOTSUPP;
@@ -670,9 +813,57 @@ static int accel_psp_fs_init_tx(struct mlx5e_psp_fs *fs) return -ENOMEM;
mutex_init(&tx_fs->mutex); + flow_counter = mlx5_fc_create(mdev, false); + if (IS_ERR(flow_counter)) { + mlx5_core_warn(mdev, + "fail to create psp tx flow counter err(%ld)\n", + PTR_ERR(flow_counter)); + err = PTR_ERR(flow_counter); + goto out_err; + } + tx_fs->tx_counter = flow_counter; tx_fs->ns = ns; fs->tx_fs = tx_fs; return 0; + +out_err: + mutex_destroy(&tx_fs->mutex); + kfree(tx_fs); + return err; +} + +static void +mlx5e_accel_psp_fs_get_stats_fill(struct mlx5e_priv *priv, void *psp_stats) +{ + struct mlx5e_psp_stats *stats = (struct mlx5e_psp_stats *)psp_stats; + struct mlx5e_psp_tx *tx_fs = priv->psp->fs->tx_fs; + struct mlx5_core_dev *mdev = priv->mdev; + struct mlx5e_accel_fs_psp *accel_psp; + + accel_psp = (struct mlx5e_accel_fs_psp *)priv->psp->fs->rx_fs; + + if (tx_fs->tx_counter) + mlx5_fc_query(mdev, tx_fs->tx_counter, &stats->psp_tx_pkts, + &stats->psp_tx_bytes); + + if (accel_psp->rx_counter) + mlx5_fc_query(mdev, accel_psp->rx_counter, &stats->psp_rx_pkts, + &stats->psp_rx_bytes); + + if (accel_psp->rx_auth_fail_counter) + mlx5_fc_query(mdev, accel_psp->rx_auth_fail_counter, + &stats->psp_rx_pkts_auth_fail, + &stats->psp_rx_bytes_auth_fail); + + if (accel_psp->rx_err_counter) + mlx5_fc_query(mdev, accel_psp->rx_err_counter, + &stats->psp_rx_pkts_frame_err, + &stats->psp_rx_bytes_frame_err); + + if (accel_psp->rx_bad_counter) + mlx5_fc_query(mdev, accel_psp->rx_bad_counter, + &stats->psp_rx_pkts_drop, + &stats->psp_rx_bytes_drop); }
void mlx5_accel_psp_fs_cleanup_tx_tables(struct mlx5e_priv *priv) @@ -849,12 +1040,30 @@ mlx5e_psp_key_rotate(struct psp_dev *psd, struct netlink_ext_ack *exack) return mlx5e_psp_rotate_key(priv->mdev); }
+static void +mlx5e_psp_get_stats(struct psp_dev *psd, struct psp_dev_stats *stats) +{ + struct mlx5e_priv *priv = netdev_priv(psd->main_netdev); + struct mlx5e_psp_stats nstats; + + mlx5e_accel_psp_fs_get_stats_fill(priv, &nstats); + stats->rx_packets = nstats.psp_rx_pkts; + stats->rx_bytes = nstats.psp_rx_bytes; + stats->rx_auth_fail = nstats.psp_rx_pkts_auth_fail; + stats->rx_error = nstats.psp_rx_pkts_frame_err; + stats->rx_bad = nstats.psp_rx_pkts_drop; + stats->tx_packets = nstats.psp_tx_pkts; + stats->tx_bytes = nstats.psp_tx_bytes; + stats->tx_error = atomic_read(&priv->psp->tx_drop); +} + static struct psp_dev_ops mlx5_psp_ops = { .set_config = mlx5e_psp_set_config, .rx_spi_alloc = mlx5e_psp_rx_spi_alloc, .tx_key_add = mlx5e_psp_assoc_add, .tx_key_del = mlx5e_psp_assoc_del, .key_rotate = mlx5e_psp_key_rotate, + .get_stats = mlx5e_psp_get_stats, };
void mlx5e_psp_unregister(struct mlx5e_priv *priv) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.h index 42bb671fb2cb..b3284d00415f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.h @@ -7,11 +7,29 @@ #include <net/psp/types.h> #include "en.h"
+struct mlx5e_psp_stats { + u64 psp_rx_pkts; + u64 psp_rx_bytes; + u64 psp_rx_pkts_auth_fail; + u64 psp_rx_bytes_auth_fail; + u64 psp_rx_pkts_frame_err; + u64 psp_rx_bytes_frame_err; + u64 psp_rx_pkts_drop; + u64 psp_rx_bytes_drop; + u64 psp_tx_pkts; + u64 psp_tx_bytes; + u64 psp_tx_pkts_drop; + u64 psp_tx_bytes_drop; +}; + struct mlx5e_psp { struct psp_dev *psp; struct psp_dev_caps caps; struct mlx5e_psp_fs *fs; atomic_t tx_key_cnt; + atomic_t tx_drop; + /* Stats manage */ + struct mlx5e_psp_stats stats; };
static inline bool mlx5_is_psp_device(struct mlx5_core_dev *mdev) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c index 828bff1137af..c17ea0fcd8ef 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c @@ -186,6 +186,7 @@ bool mlx5e_psp_handle_tx_skb(struct net_device *netdev, /* psp_encap of the packet */ if (!psp_dev_encapsulate(net, skb, psp_st->spi, psp_st->ver, 0)) { kfree_skb_reason(skb, SKB_DROP_REASON_PSP_OUTPUT); + atomic_inc(&priv->psp->tx_drop); return false; } if (skb_is_gso(skb)) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index a56825921c23..9fe18ae1e4e1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -3998,6 +3998,11 @@ void mlx5e_fold_sw_stats64(struct mlx5e_priv *priv, struct rtnl_link_stats64 *s) s->rx_bytes += rq_stats->bytes; s->multicast += rq_stats->mcast_packets; } + +#ifdef CONFIG_MLX5_EN_PSP + if (priv->psp) + s->tx_dropped += atomic_read(&priv->psp->tx_drop); +#endif }
void
On Wed, 22 Oct 2025 12:37:36 -0700 Daniel Zahka wrote:
mlx5_core_warn(mdev,
"fail to create psp rx flow counter err(%ld)\n",PTR_ERR(flow_counter));err = PTR_ERR(flow_counter);goto out_err;- }
- accel_psp->rx_counter = flow_counter;
- flow_counter = mlx5_fc_create(mdev, false);
- if (IS_ERR(flow_counter)) {
mlx5_core_warn(mdev,"fail to create psp rx auth fail flow counter err(%ld)\n",PTR_ERR(flow_counter));err = PTR_ERR(flow_counter);goto out_counter_err;- }
- accel_psp->rx_auth_fail_counter = flow_counter;
- flow_counter = mlx5_fc_create(mdev, false);
- if (IS_ERR(flow_counter)) {
mlx5_core_warn(mdev,"fail to create psp rx error flow counter err(%ld)\n",PTR_ERR(flow_counter));err = PTR_ERR(flow_counter);goto out_auth_fail_counter_err;- }
- accel_psp->rx_err_counter = flow_counter;
- flow_counter = mlx5_fc_create(mdev, false);
- if (IS_ERR(flow_counter)) {
mlx5_core_warn(mdev,"fail to create psp rx auth fail flow counter err(%ld)\n",PTR_ERR(flow_counter));
Coccicheck sayeth (5x):
drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp.c: WARNING: Consider using %pe to print PTR_ERR()
That's %pe, flow_counter instead of %d, PTR_ERR(flow_counter)
For now only tx/rx packets/bytes are reported. This is not compliant with the PSP Architecture Specification.
Signed-off-by: Daniel Zahka daniel.zahka@gmail.com --- drivers/net/netdevsim/netdevsim.h | 5 +++++ drivers/net/netdevsim/psp.c | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+)
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 02c1c97b7008..af6fcfcda8ba 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -109,6 +109,11 @@ struct netdevsim { int rq_reset_mode;
struct { + u64 rx_packets; + u64 rx_bytes; + u64 tx_packets; + u64 tx_bytes; + struct u64_stats_sync syncp; struct psp_dev *dev; u32 spi; u32 assoc_cnt; diff --git a/drivers/net/netdevsim/psp.c b/drivers/net/netdevsim/psp.c index 332b5b744f01..3912f2611862 100644 --- a/drivers/net/netdevsim/psp.c +++ b/drivers/net/netdevsim/psp.c @@ -70,6 +70,13 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns, *psp_ext = skb->extensions; refcount_inc(&(*psp_ext)->refcnt); skb->decrypted = 1; + + u64_stats_update_begin(&ns->psp.syncp); + ns->psp.tx_packets++; + ns->psp.rx_packets++; + ns->psp.tx_bytes += skb->len - skb_inner_transport_offset(skb); + ns->psp.rx_bytes += skb->len - skb_inner_transport_offset(skb); + u64_stats_update_end(&ns->psp.syncp); } else { struct ipv6hdr *ip6h __maybe_unused; struct iphdr *iph; @@ -164,12 +171,32 @@ static void nsim_assoc_del(struct psp_dev *psd, struct psp_assoc *pas) ns->psp.assoc_cnt--; }
+static void nsim_get_stats(struct psp_dev *psd, struct psp_dev_stats *stats) +{ + struct netdevsim *ns = psd->drv_priv; + unsigned int start; + + /* WARNING: do *not* blindly zero stats in real drivers! + * All required stats must be reported by the device! + */ + memset(stats, 0, offsetof(struct psp_dev_stats, required_end)); + + do { + start = u64_stats_fetch_begin(&ns->psp.syncp); + stats->rx_bytes = ns->psp.rx_bytes; + stats->rx_packets = ns->psp.rx_packets; + stats->tx_bytes = ns->psp.tx_bytes; + stats->tx_packets = ns->psp.tx_packets; + } while (u64_stats_fetch_retry(&ns->psp.syncp, start)); +} + static struct psp_dev_ops nsim_psp_ops = { .set_config = nsim_psp_set_config, .rx_spi_alloc = nsim_rx_spi_alloc, .tx_key_add = nsim_assoc_add, .tx_key_del = nsim_assoc_del, .key_rotate = nsim_key_rotate, + .get_stats = nsim_get_stats, };
static struct psp_dev_caps nsim_psp_caps = {
linux-kselftest-mirror@lists.linaro.org