Skip to content

Commit

Permalink
net/smc: Add netlink support for SMC fallback statistics
Browse files Browse the repository at this point in the history
Add support to collect more detailed SMC fallback reason statistics and
provide these statistics to user space on the netlink interface.

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 8c40602 commit f0dd7bf
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 1 deletion.
14 changes: 14 additions & 0 deletions include/uapi/linux/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ enum {
SMC_NETLINK_GET_DEV_SMCD,
SMC_NETLINK_GET_DEV_SMCR,
SMC_NETLINK_GET_STATS,
SMC_NETLINK_GET_FBACK_STATS,
};

/* SMC_GENL_FAMILY top level attributes */
Expand All @@ -60,6 +61,7 @@ enum {
SMC_GEN_DEV_SMCD, /* nest */
SMC_GEN_DEV_SMCR, /* nest */
SMC_GEN_STATS, /* nest */
SMC_GEN_FBACK_STATS, /* nest */
__SMC_GEN_MAX,
SMC_GEN_MAX = __SMC_GEN_MAX - 1
};
Expand Down Expand Up @@ -228,4 +230,16 @@ enum {
__SMC_NLA_STATS_MAX,
SMC_NLA_STATS_MAX = __SMC_NLA_STATS_MAX - 1
};

/* SMC_GEN_FBACK_STATS attributes */
enum {
SMC_NLA_FBACK_STATS_PAD,
SMC_NLA_FBACK_STATS_TYPE, /* u8 */
SMC_NLA_FBACK_STATS_SRV_CNT, /* u64 */
SMC_NLA_FBACK_STATS_CLNT_CNT, /* u64 */
SMC_NLA_FBACK_STATS_RSN_CODE, /* u32 */
SMC_NLA_FBACK_STATS_RSN_CNT, /* u16 */
__SMC_NLA_FBACK_STATS_MAX,
SMC_NLA_FBACK_STATS_MAX = __SMC_NLA_FBACK_STATS_MAX - 1
};
#endif /* _UAPI_LINUX_SMC_H */
5 changes: 5 additions & 0 deletions net/smc/smc_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ static const struct genl_ops smc_gen_nl_ops[] = {
/* can be retrieved by unprivileged users */
.dumpit = smc_nl_get_stats,
},
{
.cmd = SMC_NETLINK_GET_FBACK_STATS,
/* can be retrieved by unprivileged users */
.dumpit = smc_nl_get_fback_stats,
},
};

static const struct nla_policy smc_gen_nl_policy[2] = {
Expand Down
2 changes: 1 addition & 1 deletion net/smc/smc_netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
extern struct genl_family smc_gen_nl_family;

struct smc_nl_dmp_ctx {
int pos[2];
int pos[3];
};

static inline struct smc_nl_dmp_ctx *smc_nl_dmp_ctx(struct netlink_callback *c)
Expand Down
92 changes: 92 additions & 0 deletions net/smc/smc_stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,95 @@ int smc_nl_get_stats(struct sk_buff *skb,
errmsg:
return skb->len;
}

static int smc_nl_get_fback_details(struct sk_buff *skb,
struct netlink_callback *cb, int pos,
bool is_srv)
{
struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
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];
else
trgt_arr = &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,
&smc_gen_nl_family, NLM_F_MULTI,
SMC_NETLINK_GET_FBACK_STATS);
if (!nlh)
goto errmsg;
attrs = nla_nest_start(skb, SMC_GEN_FBACK_STATS);
if (!attrs)
goto errout;
if (nla_put_u8(skb, SMC_NLA_FBACK_STATS_TYPE, is_srv))
goto errattr;
if (!cnt_reported) {
if (nla_put_u64_64bit(skb, SMC_NLA_FBACK_STATS_SRV_CNT,
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,
SMC_NLA_FBACK_STATS_PAD))
goto errattr;
cnt_reported = 1;
}

if (nla_put_u32(skb, SMC_NLA_FBACK_STATS_RSN_CODE,
trgt_arr[pos].fback_code))
goto errattr;
if (nla_put_u16(skb, SMC_NLA_FBACK_STATS_RSN_CNT,
trgt_arr[pos].count))
goto errattr;

cb_ctx->pos[2] = cnt_reported;
nla_nest_end(skb, attrs);
genlmsg_end(skb, nlh);
return rc;

errattr:
nla_nest_cancel(skb, attrs);
errout:
genlmsg_cancel(skb, nlh);
errmsg:
return -EMSGSIZE;
}

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);
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);
for (k = 0; k < SMC_MAX_FBACK_RSN_CNT; k++) {
if (k < snum)
continue;
if (!skip_serv) {
rc_srv = smc_nl_get_fback_details(skb, cb, k, is_srv);
if (rc_srv && rc_srv != ENODATA)
break;
} else {
skip_serv = 0;
}
rc_clnt = smc_nl_get_fback_details(skb, cb, k, !is_srv);
if (rc_clnt && rc_clnt != ENODATA) {
skip_serv = 1;
break;
}
if (rc_clnt == ENODATA && rc_srv == ENODATA)
break;
}
mutex_unlock(&smc_stat_fback_rsn);
cb_ctx->pos[1] = skip_serv;
cb_ctx->pos[0] = k;
return skb->len;
}
1 change: 1 addition & 0 deletions net/smc/smc_stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ do { \
while (0)

int smc_nl_get_stats(struct sk_buff *skb, struct netlink_callback *cb);
int smc_nl_get_fback_stats(struct sk_buff *skb, struct netlink_callback *cb);
int smc_stats_init(void) __init;
void smc_stats_exit(void);

Expand Down

0 comments on commit f0dd7bf

Please sign in to comment.