Skip to content

Commit

Permalink
net/smc: Make SMC statistics network namespace aware
Browse files Browse the repository at this point in the history
Make the gathered SMC statistics network namespace aware, for each
namespace collect an own set of statistic information.

Signed-off-by: Guvenc Gulce <guvenc@linux.ibm.com>
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Guvenc Gulce authored and David S. Miller committed Jun 16, 2021
1 parent f0dd7bf commit 194730a
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 108 deletions.
4 changes: 4 additions & 0 deletions include/net/net_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <net/netns/mpls.h>
#include <net/netns/can.h>
#include <net/netns/xdp.h>
#include <net/netns/smc.h>
#include <net/netns/bpf.h>
#include <linux/ns_common.h>
#include <linux/idr.h>
Expand Down Expand Up @@ -170,6 +171,9 @@ struct net {
struct sock *crypto_nlsk;
#endif
struct sock *diag_nlsk;
#if IS_ENABLED(CONFIG_SMC)
struct netns_smc smc;
#endif
} __randomize_layout;

#include <linux/seq_file_net.h>
Expand Down
16 changes: 16 additions & 0 deletions include/net/netns/smc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __NETNS_SMC_H__
#define __NETNS_SMC_H__
#include <linux/mutex.h>
#include <linux/percpu.h>

struct smc_stats_rsn;
struct smc_stats;
struct netns_smc {
/* per cpu counters for SMC */
struct smc_stats __percpu *smc_stats;
/* protect fback_rsn */
struct mutex mutex_fback_rsn;
struct smc_stats_rsn *fback_rsn;
};
#endif
65 changes: 40 additions & 25 deletions net/smc/af_smc.c
Original file line number Diff line number Diff line change
Expand Up @@ -529,15 +529,17 @@ static void smc_stat_inc_fback_rsn_cnt(struct smc_sock *smc,

static void smc_stat_fallback(struct smc_sock *smc)
{
mutex_lock(&smc_stat_fback_rsn);
struct net *net = sock_net(&smc->sk);

mutex_lock(&net->smc.mutex_fback_rsn);
if (smc->listen_smc) {
smc_stat_inc_fback_rsn_cnt(smc, fback_rsn.srv);
fback_rsn.srv_fback_cnt++;
smc_stat_inc_fback_rsn_cnt(smc, net->smc.fback_rsn->srv);
net->smc.fback_rsn->srv_fback_cnt++;
} else {
smc_stat_inc_fback_rsn_cnt(smc, fback_rsn.clnt);
fback_rsn.clnt_fback_cnt++;
smc_stat_inc_fback_rsn_cnt(smc, net->smc.fback_rsn->clnt);
net->smc.fback_rsn->clnt_fback_cnt++;
}
mutex_unlock(&smc_stat_fback_rsn);
mutex_unlock(&net->smc.mutex_fback_rsn);
}

static void smc_switch_to_fallback(struct smc_sock *smc, int reason_code)
Expand Down Expand Up @@ -568,18 +570,19 @@ static int smc_connect_fallback(struct smc_sock *smc, int reason_code)
static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code,
u8 version)
{
struct net *net = sock_net(&smc->sk);
int rc;

if (reason_code < 0) { /* error, fallback is not possible */
this_cpu_inc(smc_stats->clnt_hshake_err_cnt);
this_cpu_inc(net->smc.smc_stats->clnt_hshake_err_cnt);
if (smc->sk.sk_state == SMC_INIT)
sock_put(&smc->sk); /* passive closing */
return reason_code;
}
if (reason_code != SMC_CLC_DECL_PEERDECL) {
rc = smc_clc_send_decline(smc, reason_code, version);
if (rc < 0) {
this_cpu_inc(smc_stats->clnt_hshake_err_cnt);
this_cpu_inc(net->smc.smc_stats->clnt_hshake_err_cnt);
if (smc->sk.sk_state == SMC_INIT)
sock_put(&smc->sk); /* passive closing */
return rc;
Expand Down Expand Up @@ -1027,7 +1030,7 @@ static int __smc_connect(struct smc_sock *smc)
if (rc)
goto vlan_cleanup;

SMC_STAT_CLNT_SUCC_INC(aclc);
SMC_STAT_CLNT_SUCC_INC(sock_net(smc->clcsock->sk), aclc);
smc_connect_ism_vlan_cleanup(smc, ini);
kfree(buf);
kfree(ini);
Expand Down Expand Up @@ -1343,8 +1346,9 @@ static void smc_listen_out_connected(struct smc_sock *new_smc)
static void smc_listen_out_err(struct smc_sock *new_smc)
{
struct sock *newsmcsk = &new_smc->sk;
struct net *net = sock_net(newsmcsk);

this_cpu_inc(smc_stats->srv_hshake_err_cnt);
this_cpu_inc(net->smc.smc_stats->srv_hshake_err_cnt);
if (newsmcsk->sk_state == SMC_INIT)
sock_put(&new_smc->sk); /* passive closing */
newsmcsk->sk_state = SMC_CLOSED;
Expand Down Expand Up @@ -1813,7 +1817,7 @@ static void smc_listen_work(struct work_struct *work)
}
smc_conn_save_peer_info(new_smc, cclc);
smc_listen_out_connected(new_smc);
SMC_STAT_SERV_SUCC_INC(ini);
SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk), ini);
goto out_free;

out_unlock:
Expand Down Expand Up @@ -2242,7 +2246,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
sk->sk_state != SMC_LISTEN &&
sk->sk_state != SMC_CLOSED) {
if (val) {
SMC_STAT_INC(!smc->conn.lnk, ndly_cnt);
SMC_STAT_INC(smc, ndly_cnt);
mod_delayed_work(smc->conn.lgr->tx_wq,
&smc->conn.tx_work, 0);
}
Expand All @@ -2253,7 +2257,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
sk->sk_state != SMC_LISTEN &&
sk->sk_state != SMC_CLOSED) {
if (!val) {
SMC_STAT_INC(!smc->conn.lnk, cork_cnt);
SMC_STAT_INC(smc, cork_cnt);
mod_delayed_work(smc->conn.lgr->tx_wq,
&smc->conn.tx_work, 0);
}
Expand Down Expand Up @@ -2383,7 +2387,7 @@ static ssize_t smc_sendpage(struct socket *sock, struct page *page,
rc = kernel_sendpage(smc->clcsock, page, offset,
size, flags);
} else {
SMC_STAT_INC(!smc->conn.lnk, sendpage_cnt);
SMC_STAT_INC(smc, sendpage_cnt);
rc = sock_no_sendpage(sock, page, offset, size, flags);
}

Expand Down Expand Up @@ -2434,7 +2438,7 @@ static ssize_t smc_splice_read(struct socket *sock, loff_t *ppos,
flags = MSG_DONTWAIT;
else
flags = 0;
SMC_STAT_INC(!smc->conn.lnk, splice_cnt);
SMC_STAT_INC(smc, splice_cnt);
rc = smc_rx_recvmsg(smc, NULL, pipe, len, flags);
}
out:
Expand Down Expand Up @@ -2523,13 +2527,28 @@ static void __net_exit smc_net_exit(struct net *net)
smc_pnet_net_exit(net);
}

static __net_init int smc_net_stat_init(struct net *net)
{
return smc_stats_init(net);
}

static void __net_exit smc_net_stat_exit(struct net *net)
{
smc_stats_exit(net);
}

static struct pernet_operations smc_net_ops = {
.init = smc_net_init,
.exit = smc_net_exit,
.id = &smc_net_id,
.size = sizeof(struct smc_net),
};

static struct pernet_operations smc_net_stat_ops = {
.init = smc_net_stat_init,
.exit = smc_net_stat_exit,
};

static int __init smc_init(void)
{
int rc;
Expand All @@ -2538,6 +2557,10 @@ static int __init smc_init(void)
if (rc)
return rc;

rc = register_pernet_subsys(&smc_net_stat_ops);
if (rc)
return rc;

smc_ism_init();
smc_clc_init();

Expand All @@ -2558,16 +2581,10 @@ static int __init smc_init(void)
if (!smc_close_wq)
goto out_alloc_hs_wq;

rc = smc_stats_init();
if (rc) {
pr_err("%s: smc_stats_init fails with %d\n", __func__, rc);
goto out_alloc_wqs;
}

rc = smc_core_init();
if (rc) {
pr_err("%s: smc_core_init fails with %d\n", __func__, rc);
goto out_smc_stat;
goto out_alloc_wqs;
}

rc = smc_llc_init();
Expand Down Expand Up @@ -2619,8 +2636,6 @@ static int __init smc_init(void)
proto_unregister(&smc_proto);
out_core:
smc_core_exit();
out_smc_stat:
smc_stats_exit();
out_alloc_wqs:
destroy_workqueue(smc_close_wq);
out_alloc_hs_wq:
Expand All @@ -2643,11 +2658,11 @@ static void __exit smc_exit(void)
smc_ib_unregister_client();
destroy_workqueue(smc_close_wq);
destroy_workqueue(smc_hs_wq);
smc_stats_exit();
proto_unregister(&smc_proto6);
proto_unregister(&smc_proto);
smc_pnet_exit();
smc_nl_exit();
unregister_pernet_subsys(&smc_net_stat_ops);
unregister_pernet_subsys(&smc_net_ops);
rcu_barrier();
}
Expand Down
10 changes: 5 additions & 5 deletions net/smc/smc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2058,8 +2058,8 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
/* check for reusable slot in the link group */
buf_desc = smc_buf_get_slot(bufsize_short, lock, buf_list);
if (buf_desc) {
SMC_STAT_RMB_SIZE(is_smcd, is_rmb, bufsize);
SMC_STAT_BUF_REUSE(is_smcd, is_rmb);
SMC_STAT_RMB_SIZE(smc, is_smcd, is_rmb, bufsize);
SMC_STAT_BUF_REUSE(smc, is_smcd, is_rmb);
memset(buf_desc->cpu_addr, 0, bufsize);
break; /* found reusable slot */
}
Expand All @@ -2074,13 +2074,13 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb)
if (IS_ERR(buf_desc)) {
if (!is_dgraded) {
is_dgraded = true;
SMC_STAT_RMB_DOWNGRADED(is_smcd, is_rmb);
SMC_STAT_RMB_DOWNGRADED(smc, is_smcd, is_rmb);
}
continue;
}

SMC_STAT_RMB_ALLOC(is_smcd, is_rmb);
SMC_STAT_RMB_SIZE(is_smcd, is_rmb, bufsize);
SMC_STAT_RMB_ALLOC(smc, is_smcd, is_rmb);
SMC_STAT_RMB_SIZE(smc, is_smcd, is_rmb, bufsize);
buf_desc->used = 1;
mutex_lock(lock);
list_add(&buf_desc->list, buf_list);
Expand Down
6 changes: 3 additions & 3 deletions net/smc/smc_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ static int smc_rx_recv_urg(struct smc_sock *smc, struct msghdr *msg, int len,
conn->urg_state == SMC_URG_READ)
return -EINVAL;

SMC_STAT_INC(!conn->lnk, urg_data_cnt);
SMC_STAT_INC(smc, urg_data_cnt);
if (conn->urg_state == SMC_URG_VALID) {
if (!(flags & MSG_PEEK))
smc->conn.urg_state = SMC_URG_READ;
Expand Down Expand Up @@ -307,10 +307,10 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,

readable = atomic_read(&conn->bytes_to_rcv);
if (readable >= conn->rmb_desc->len)
SMC_STAT_RMB_RX_FULL(!conn->lnk);
SMC_STAT_RMB_RX_FULL(smc, !conn->lnk);

if (len < readable)
SMC_STAT_RMB_RX_SIZE_SMALL(!conn->lnk);
SMC_STAT_RMB_RX_SIZE_SMALL(smc, !conn->lnk);
/* we currently use 1 RMBE per RMB, so RMBE == RMB base addr */
rcvbuf_base = conn->rx_off + conn->rmb_desc->cpu_addr;

Expand Down
47 changes: 27 additions & 20 deletions net/smc/smc_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,28 @@
#include "smc_netlink.h"
#include "smc_stats.h"

/* serialize fallback reason statistic gathering */
DEFINE_MUTEX(smc_stat_fback_rsn);
struct smc_stats __percpu *smc_stats; /* per cpu counters for SMC */
struct smc_stats_reason fback_rsn;

int __init smc_stats_init(void)
int smc_stats_init(struct net *net)
{
memset(&fback_rsn, 0, sizeof(fback_rsn));
smc_stats = alloc_percpu(struct smc_stats);
if (!smc_stats)
return -ENOMEM;

net->smc.fback_rsn = kzalloc(sizeof(*net->smc.fback_rsn), GFP_KERNEL);
if (!net->smc.fback_rsn)
goto err_fback;
net->smc.smc_stats = alloc_percpu(struct smc_stats);
if (!net->smc.smc_stats)
goto err_stats;
mutex_init(&net->smc.mutex_fback_rsn);
return 0;

err_stats:
kfree(net->smc.fback_rsn);
err_fback:
return -ENOMEM;
}

void smc_stats_exit(void)
void smc_stats_exit(struct net *net)
{
free_percpu(smc_stats);
kfree(net->smc.fback_rsn);
if (net->smc.smc_stats)
free_percpu(net->smc.smc_stats);
}

static int smc_nl_fill_stats_rmb_data(struct sk_buff *skb,
Expand Down Expand Up @@ -256,6 +260,7 @@ int smc_nl_get_stats(struct sk_buff *skb,
struct netlink_callback *cb)
{
struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
struct net *net = sock_net(skb->sk);
struct smc_stats *stats;
struct nlattr *attrs;
int cpu, i, size;
Expand All @@ -279,7 +284,7 @@ int smc_nl_get_stats(struct sk_buff *skb,
goto erralloc;
size = sizeof(*stats) / sizeof(u64);
for_each_possible_cpu(cpu) {
src = (u64 *)per_cpu_ptr(smc_stats, cpu);
src = (u64 *)per_cpu_ptr(net->smc.smc_stats, cpu);
sum = (u64 *)stats;
for (i = 0; i < size; i++)
*(sum++) += *(src++);
Expand Down Expand Up @@ -318,16 +323,17 @@ static int smc_nl_get_fback_details(struct sk_buff *skb,
bool is_srv)
{
struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
struct net *net = sock_net(skb->sk);
int cnt_reported = cb_ctx->pos[2];
struct smc_stats_fback *trgt_arr;
struct nlattr *attrs;
int rc = 0;
void *nlh;

if (is_srv)
trgt_arr = &fback_rsn.srv[0];
trgt_arr = &net->smc.fback_rsn->srv[0];
else
trgt_arr = &fback_rsn.clnt[0];
trgt_arr = &net->smc.fback_rsn->clnt[0];
if (!trgt_arr[pos].fback_code)
return -ENODATA;
nlh = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
Expand All @@ -342,11 +348,11 @@ static int smc_nl_get_fback_details(struct sk_buff *skb,
goto errattr;
if (!cnt_reported) {
if (nla_put_u64_64bit(skb, SMC_NLA_FBACK_STATS_SRV_CNT,
fback_rsn.srv_fback_cnt,
net->smc.fback_rsn->srv_fback_cnt,
SMC_NLA_FBACK_STATS_PAD))
goto errattr;
if (nla_put_u64_64bit(skb, SMC_NLA_FBACK_STATS_CLNT_CNT,
fback_rsn.clnt_fback_cnt,
net->smc.fback_rsn->clnt_fback_cnt,
SMC_NLA_FBACK_STATS_PAD))
goto errattr;
cnt_reported = 1;
Expand Down Expand Up @@ -375,12 +381,13 @@ static int smc_nl_get_fback_details(struct sk_buff *skb,
int smc_nl_get_fback_stats(struct sk_buff *skb, struct netlink_callback *cb)
{
struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
struct net *net = sock_net(skb->sk);
int rc_srv = 0, rc_clnt = 0, k;
int skip_serv = cb_ctx->pos[1];
int snum = cb_ctx->pos[0];
bool is_srv = true;

mutex_lock(&smc_stat_fback_rsn);
mutex_lock(&net->smc.mutex_fback_rsn);
for (k = 0; k < SMC_MAX_FBACK_RSN_CNT; k++) {
if (k < snum)
continue;
Expand All @@ -399,7 +406,7 @@ int smc_nl_get_fback_stats(struct sk_buff *skb, struct netlink_callback *cb)
if (rc_clnt == ENODATA && rc_srv == ENODATA)
break;
}
mutex_unlock(&smc_stat_fback_rsn);
mutex_unlock(&net->smc.mutex_fback_rsn);
cb_ctx->pos[1] = skip_serv;
cb_ctx->pos[0] = k;
return skb->len;
Expand Down
Loading

0 comments on commit 194730a

Please sign in to comment.