Skip to content

Commit

Permalink
net/smc: Introduce SMCR get link command
Browse files Browse the repository at this point in the history
Introduce get link command which loops through
all available links of all available link groups. It
uses the SMC-R linkgroup list as entry point, not
the socket list, which makes linkgroup diagnosis
possible, in case linkgroup does not contain active
connections anymore.

Signed-off-by: Guvenc Gulce <guvenc@linux.ibm.com>
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Guvenc Gulce authored and Jakub Kicinski committed Dec 2, 2020
1 parent e9b8c84 commit 5a7e09d
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 17 deletions.
18 changes: 18 additions & 0 deletions include/uapi/linux/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ enum { /* SMC PNET Table commands */
enum {
SMC_NETLINK_GET_SYS_INFO = 1,
SMC_NETLINK_GET_LGR_SMCR,
SMC_NETLINK_GET_LINK_SMCR,
};

/* SMC_GENL_FAMILY top level attributes */
enum {
SMC_GEN_UNSPEC,
SMC_GEN_SYS_INFO, /* nest */
SMC_GEN_LGR_SMCR, /* nest */
SMC_GEN_LINK_SMCR, /* nest */
__SMC_GEN_MAX,
SMC_GEN_MAX = __SMC_GEN_MAX - 1
};
Expand Down Expand Up @@ -77,4 +79,20 @@ enum {
SMC_NLA_LGR_R_MAX = __SMC_NLA_LGR_R_MAX - 1
};

/* SMC_GEN_LINK_SMCR attributes */
enum {
SMC_NLA_LINK_UNSPEC,
SMC_NLA_LINK_ID, /* u8 */
SMC_NLA_LINK_IB_DEV, /* string */
SMC_NLA_LINK_IB_PORT, /* u8 */
SMC_NLA_LINK_GID, /* string */
SMC_NLA_LINK_PEER_GID, /* string */
SMC_NLA_LINK_CONN_CNT, /* u32 */
SMC_NLA_LINK_NET_DEV, /* u32 */
SMC_NLA_LINK_UID, /* u32 */
SMC_NLA_LINK_PEER_UID, /* u32 */
SMC_NLA_LINK_STATE, /* u32 */
__SMC_NLA_LINK_MAX,
SMC_NLA_LINK_MAX = __SMC_NLA_LINK_MAX - 1
};
#endif /* _UAPI_LINUX_SMC_H */
91 changes: 87 additions & 4 deletions net/smc/smc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,74 @@ static int smc_nl_fill_lgr(struct smc_link_group *lgr,
return -EMSGSIZE;
}

static int smc_nl_fill_lgr_link(struct smc_link_group *lgr,
struct smc_link *link,
struct sk_buff *skb,
struct netlink_callback *cb)
{
char smc_ibname[IB_DEVICE_NAME_MAX + 1];
u8 smc_gid_target[41];
struct nlattr *attrs;
u32 link_uid = 0;
void *nlh;

nlh = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
&smc_gen_nl_family, NLM_F_MULTI,
SMC_NETLINK_GET_LINK_SMCR);
if (!nlh)
goto errmsg;

attrs = nla_nest_start(skb, SMC_GEN_LINK_SMCR);
if (!attrs)
goto errout;

if (nla_put_u8(skb, SMC_NLA_LINK_ID, link->link_id))
goto errattr;
if (nla_put_u32(skb, SMC_NLA_LINK_STATE, link->state))
goto errattr;
if (nla_put_u32(skb, SMC_NLA_LINK_CONN_CNT,
atomic_read(&link->conn_cnt)))
goto errattr;
if (nla_put_u8(skb, SMC_NLA_LINK_IB_PORT, link->ibport))
goto errattr;
if (nla_put_u32(skb, SMC_NLA_LINK_NET_DEV, link->ndev_ifidx))
goto errattr;
snprintf(smc_ibname, sizeof(smc_ibname), "%s", link->ibname);
if (nla_put_string(skb, SMC_NLA_LINK_IB_DEV, smc_ibname))
goto errattr;
memcpy(&link_uid, link->link_uid, sizeof(link_uid));
if (nla_put_u32(skb, SMC_NLA_LINK_UID, link_uid))
goto errattr;
memcpy(&link_uid, link->peer_link_uid, sizeof(link_uid));
if (nla_put_u32(skb, SMC_NLA_LINK_PEER_UID, link_uid))
goto errattr;
memset(smc_gid_target, 0, sizeof(smc_gid_target));
smc_gid_be16_convert(smc_gid_target, link->gid);
if (nla_put_string(skb, SMC_NLA_LINK_GID, smc_gid_target))
goto errattr;
memset(smc_gid_target, 0, sizeof(smc_gid_target));
smc_gid_be16_convert(smc_gid_target, link->peer_gid);
if (nla_put_string(skb, SMC_NLA_LINK_PEER_GID, smc_gid_target))
goto errattr;

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

static int smc_nl_handle_lgr(struct smc_link_group *lgr,
struct sk_buff *skb,
struct netlink_callback *cb)
struct netlink_callback *cb,
bool list_links)
{
void *nlh;
int i;

nlh = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
&smc_gen_nl_family, NLM_F_MULTI,
Expand All @@ -322,6 +385,15 @@ static int smc_nl_handle_lgr(struct smc_link_group *lgr,
goto errout;

genlmsg_end(skb, nlh);
if (!list_links)
goto out;
for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) {
if (!smc_link_usable(&lgr->lnk[i]))
continue;
if (smc_nl_fill_lgr_link(lgr, &lgr->lnk[i], skb, cb))
goto errout;
}
out:
return 0;

errout:
Expand All @@ -332,7 +404,8 @@ static int smc_nl_handle_lgr(struct smc_link_group *lgr,

static void smc_nl_fill_lgr_list(struct smc_lgr_list *smc_lgr,
struct sk_buff *skb,
struct netlink_callback *cb)
struct netlink_callback *cb,
bool list_links)
{
struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb);
struct smc_link_group *lgr;
Expand All @@ -343,7 +416,7 @@ static void smc_nl_fill_lgr_list(struct smc_lgr_list *smc_lgr,
list_for_each_entry(lgr, &smc_lgr->list, list) {
if (num < snum)
goto next;
if (smc_nl_handle_lgr(lgr, skb, cb))
if (smc_nl_handle_lgr(lgr, skb, cb, list_links))
goto errout;
next:
num++;
Expand All @@ -355,7 +428,17 @@ static void smc_nl_fill_lgr_list(struct smc_lgr_list *smc_lgr,

int smcr_nl_get_lgr(struct sk_buff *skb, struct netlink_callback *cb)
{
smc_nl_fill_lgr_list(&smc_lgr_list, skb, cb);
bool list_links = false;

smc_nl_fill_lgr_list(&smc_lgr_list, skb, cb, list_links);
return skb->len;
}

int smcr_nl_get_link(struct sk_buff *skb, struct netlink_callback *cb)
{
bool list_links = true;

smc_nl_fill_lgr_list(&smc_lgr_list, skb, cb, list_links);
return skb->len;
}

Expand Down
14 changes: 14 additions & 0 deletions net/smc/smc_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,19 @@ static inline bool smc_link_active(struct smc_link *lnk)
return lnk->state == SMC_LNK_ACTIVE;
}

static inline void smc_gid_be16_convert(__u8 *buf, u8 *gid_raw)
{
sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
be16_to_cpu(((__be16 *)gid_raw)[0]),
be16_to_cpu(((__be16 *)gid_raw)[1]),
be16_to_cpu(((__be16 *)gid_raw)[2]),
be16_to_cpu(((__be16 *)gid_raw)[3]),
be16_to_cpu(((__be16 *)gid_raw)[4]),
be16_to_cpu(((__be16 *)gid_raw)[5]),
be16_to_cpu(((__be16 *)gid_raw)[6]),
be16_to_cpu(((__be16 *)gid_raw)[7]));
}

struct smc_sock;
struct smc_clc_msg_accept_confirm;
struct smc_clc_msg_local;
Expand Down Expand Up @@ -416,6 +429,7 @@ void smcr_link_down_cond(struct smc_link *lnk);
void smcr_link_down_cond_sched(struct smc_link *lnk);
int smc_nl_get_sys_info(struct sk_buff *skb, struct netlink_callback *cb);
int smcr_nl_get_lgr(struct sk_buff *skb, struct netlink_callback *cb);
int smcr_nl_get_link(struct sk_buff *skb, struct netlink_callback *cb);

static inline struct smc_link_group *smc_get_lgr(struct smc_link *link)
{
Expand Down
13 changes: 0 additions & 13 deletions net/smc/smc_diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,6 @@ static struct smc_diag_dump_ctx *smc_dump_context(struct netlink_callback *cb)
return (struct smc_diag_dump_ctx *)cb->ctx;
}

static void smc_gid_be16_convert(__u8 *buf, u8 *gid_raw)
{
sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
be16_to_cpu(((__be16 *)gid_raw)[0]),
be16_to_cpu(((__be16 *)gid_raw)[1]),
be16_to_cpu(((__be16 *)gid_raw)[2]),
be16_to_cpu(((__be16 *)gid_raw)[3]),
be16_to_cpu(((__be16 *)gid_raw)[4]),
be16_to_cpu(((__be16 *)gid_raw)[5]),
be16_to_cpu(((__be16 *)gid_raw)[6]),
be16_to_cpu(((__be16 *)gid_raw)[7]));
}

static void smc_diag_msg_common_fill(struct smc_diag_msg *r, struct sock *sk)
{
struct smc_sock *smc = smc_sk(sk);
Expand Down
5 changes: 5 additions & 0 deletions net/smc/smc_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ static const struct genl_ops smc_gen_nl_ops[] = {
/* can be retrieved by unprivileged users */
.dumpit = smcr_nl_get_lgr,
},
{
.cmd = SMC_NETLINK_GET_LINK_SMCR,
/* can be retrieved by unprivileged users */
.dumpit = smcr_nl_get_link,
},
};

static const struct nla_policy smc_gen_nl_policy[2] = {
Expand Down

0 comments on commit 5a7e09d

Please sign in to comment.