1 // SPDX-License-Identifier: GPL-2.0-only
3 * Shared Memory Communications over RDMA (SMC-R) and RoCE
5 * Monitoring SMC transport protocol sockets
7 * Copyright IBM Corp. 2016
9 * Author(s): Ursula Braun <ubraun@linux.vnet.ibm.com>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/types.h>
15 #include <linux/init.h>
16 #include <linux/sock_diag.h>
17 #include <linux/inet_diag.h>
18 #include <linux/smc_diag.h>
19 #include <net/netlink.h>
26 struct smc_diag_dump_ctx
{
30 static struct smc_diag_dump_ctx
*smc_dump_context(struct netlink_callback
*cb
)
32 return (struct smc_diag_dump_ctx
*)cb
->ctx
;
35 static void smc_diag_msg_common_fill(struct smc_diag_msg
*r
, struct sock
*sk
)
37 struct smc_sock
*smc
= smc_sk(sk
);
39 memset(r
, 0, sizeof(*r
));
40 r
->diag_family
= sk
->sk_family
;
41 sock_diag_save_cookie(sk
, r
->id
.idiag_cookie
);
44 r
->id
.idiag_sport
= htons(smc
->clcsock
->sk
->sk_num
);
45 r
->id
.idiag_dport
= smc
->clcsock
->sk
->sk_dport
;
46 r
->id
.idiag_if
= smc
->clcsock
->sk
->sk_bound_dev_if
;
47 if (sk
->sk_protocol
== SMCPROTO_SMC
) {
48 r
->id
.idiag_src
[0] = smc
->clcsock
->sk
->sk_rcv_saddr
;
49 r
->id
.idiag_dst
[0] = smc
->clcsock
->sk
->sk_daddr
;
50 #if IS_ENABLED(CONFIG_IPV6)
51 } else if (sk
->sk_protocol
== SMCPROTO_SMC6
) {
52 memcpy(&r
->id
.idiag_src
, &smc
->clcsock
->sk
->sk_v6_rcv_saddr
,
53 sizeof(smc
->clcsock
->sk
->sk_v6_rcv_saddr
));
54 memcpy(&r
->id
.idiag_dst
, &smc
->clcsock
->sk
->sk_v6_daddr
,
55 sizeof(smc
->clcsock
->sk
->sk_v6_daddr
));
60 static int smc_diag_msg_attrs_fill(struct sock
*sk
, struct sk_buff
*skb
,
61 struct smc_diag_msg
*r
,
62 struct user_namespace
*user_ns
)
64 if (nla_put_u8(skb
, SMC_DIAG_SHUTDOWN
, sk
->sk_shutdown
))
67 r
->diag_uid
= from_kuid_munged(user_ns
, sock_i_uid(sk
));
68 r
->diag_inode
= sock_i_ino(sk
);
72 static int __smc_diag_dump(struct sock
*sk
, struct sk_buff
*skb
,
73 struct netlink_callback
*cb
,
74 const struct smc_diag_req
*req
,
77 struct smc_sock
*smc
= smc_sk(sk
);
78 struct smc_diag_fallback fallback
;
79 struct user_namespace
*user_ns
;
80 struct smc_diag_msg
*r
;
83 nlh
= nlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
, cb
->nlh
->nlmsg_seq
,
84 cb
->nlh
->nlmsg_type
, sizeof(*r
), NLM_F_MULTI
);
89 smc_diag_msg_common_fill(r
, sk
);
90 r
->diag_state
= sk
->sk_state
;
91 if (smc
->use_fallback
)
92 r
->diag_mode
= SMC_DIAG_MODE_FALLBACK_TCP
;
93 else if (smc_conn_lgr_valid(&smc
->conn
) && smc
->conn
.lgr
->is_smcd
)
94 r
->diag_mode
= SMC_DIAG_MODE_SMCD
;
96 r
->diag_mode
= SMC_DIAG_MODE_SMCR
;
97 user_ns
= sk_user_ns(NETLINK_CB(cb
->skb
).sk
);
98 if (smc_diag_msg_attrs_fill(sk
, skb
, r
, user_ns
))
101 fallback
.reason
= smc
->fallback_rsn
;
102 fallback
.peer_diagnosis
= smc
->peer_diagnosis
;
103 if (nla_put(skb
, SMC_DIAG_FALLBACK
, sizeof(fallback
), &fallback
) < 0)
106 if ((req
->diag_ext
& (1 << (SMC_DIAG_CONNINFO
- 1))) &&
107 smc
->conn
.alert_token_local
) {
108 struct smc_connection
*conn
= &smc
->conn
;
109 struct smc_diag_conninfo cinfo
= {
110 .token
= conn
->alert_token_local
,
111 .sndbuf_size
= conn
->sndbuf_desc
?
112 conn
->sndbuf_desc
->len
: 0,
113 .rmbe_size
= conn
->rmb_desc
? conn
->rmb_desc
->len
: 0,
114 .peer_rmbe_size
= conn
->peer_rmbe_size
,
116 .rx_prod
.wrap
= conn
->local_rx_ctrl
.prod
.wrap
,
117 .rx_prod
.count
= conn
->local_rx_ctrl
.prod
.count
,
118 .rx_cons
.wrap
= conn
->local_rx_ctrl
.cons
.wrap
,
119 .rx_cons
.count
= conn
->local_rx_ctrl
.cons
.count
,
121 .tx_prod
.wrap
= conn
->local_tx_ctrl
.prod
.wrap
,
122 .tx_prod
.count
= conn
->local_tx_ctrl
.prod
.count
,
123 .tx_cons
.wrap
= conn
->local_tx_ctrl
.cons
.wrap
,
124 .tx_cons
.count
= conn
->local_tx_ctrl
.cons
.count
,
127 *(u8
*)&conn
->local_tx_ctrl
.prod_flags
,
128 .tx_conn_state_flags
=
129 *(u8
*)&conn
->local_tx_ctrl
.conn_state_flags
,
130 .rx_prod_flags
= *(u8
*)&conn
->local_rx_ctrl
.prod_flags
,
131 .rx_conn_state_flags
=
132 *(u8
*)&conn
->local_rx_ctrl
.conn_state_flags
,
134 .tx_prep
.wrap
= conn
->tx_curs_prep
.wrap
,
135 .tx_prep
.count
= conn
->tx_curs_prep
.count
,
136 .tx_sent
.wrap
= conn
->tx_curs_sent
.wrap
,
137 .tx_sent
.count
= conn
->tx_curs_sent
.count
,
138 .tx_fin
.wrap
= conn
->tx_curs_fin
.wrap
,
139 .tx_fin
.count
= conn
->tx_curs_fin
.count
,
142 if (nla_put(skb
, SMC_DIAG_CONNINFO
, sizeof(cinfo
), &cinfo
) < 0)
146 if (smc_conn_lgr_valid(&smc
->conn
) && !smc
->conn
.lgr
->is_smcd
&&
147 (req
->diag_ext
& (1 << (SMC_DIAG_LGRINFO
- 1))) &&
148 !list_empty(&smc
->conn
.lgr
->list
)) {
149 struct smc_link
*link
= smc
->conn
.lnk
;
151 struct smc_diag_lgrinfo linfo
= {
152 .role
= smc
->conn
.lgr
->role
,
153 .lnk
[0].ibport
= link
->ibport
,
154 .lnk
[0].link_id
= link
->link_id
,
157 memcpy(linfo
.lnk
[0].ibname
, link
->smcibdev
->ibdev
->name
,
158 sizeof(link
->smcibdev
->ibdev
->name
));
159 smc_gid_be16_convert(linfo
.lnk
[0].gid
, link
->gid
);
160 smc_gid_be16_convert(linfo
.lnk
[0].peer_gid
, link
->peer_gid
);
162 if (nla_put(skb
, SMC_DIAG_LGRINFO
, sizeof(linfo
), &linfo
) < 0)
165 if (smc_conn_lgr_valid(&smc
->conn
) && smc
->conn
.lgr
->is_smcd
&&
166 (req
->diag_ext
& (1 << (SMC_DIAG_DMBINFO
- 1))) &&
167 !list_empty(&smc
->conn
.lgr
->list
) && smc
->conn
.rmb_desc
) {
168 struct smc_connection
*conn
= &smc
->conn
;
169 struct smcd_diag_dmbinfo dinfo
;
170 struct smcd_dev
*smcd
= conn
->lgr
->smcd
;
171 struct smcd_gid smcd_gid
;
173 memset(&dinfo
, 0, sizeof(dinfo
));
175 dinfo
.linkid
= *((u32
*)conn
->lgr
->id
);
176 dinfo
.peer_gid
= conn
->lgr
->peer_gid
.gid
;
177 dinfo
.peer_gid_ext
= conn
->lgr
->peer_gid
.gid_ext
;
178 smcd
->ops
->get_local_gid(smcd
, &smcd_gid
);
179 dinfo
.my_gid
= smcd_gid
.gid
;
180 dinfo
.my_gid_ext
= smcd_gid
.gid_ext
;
181 dinfo
.token
= conn
->rmb_desc
->token
;
182 dinfo
.peer_token
= conn
->peer_token
;
184 if (nla_put(skb
, SMC_DIAG_DMBINFO
, sizeof(dinfo
), &dinfo
) < 0)
192 nlmsg_cancel(skb
, nlh
);
196 static int smc_diag_dump_proto(struct proto
*prot
, struct sk_buff
*skb
,
197 struct netlink_callback
*cb
, int p_type
)
199 struct smc_diag_dump_ctx
*cb_ctx
= smc_dump_context(cb
);
200 struct net
*net
= sock_net(skb
->sk
);
201 int snum
= cb_ctx
->pos
[p_type
];
202 struct nlattr
*bc
= NULL
;
203 struct hlist_head
*head
;
207 read_lock(&prot
->h
.smc_hash
->lock
);
208 head
= &prot
->h
.smc_hash
->ht
;
209 if (hlist_empty(head
))
212 sk_for_each(sk
, head
) {
213 if (!net_eq(sock_net(sk
), net
))
217 rc
= __smc_diag_dump(sk
, skb
, cb
, nlmsg_data(cb
->nlh
), bc
);
225 read_unlock(&prot
->h
.smc_hash
->lock
);
226 cb_ctx
->pos
[p_type
] = num
;
230 static int smc_diag_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
)
234 rc
= smc_diag_dump_proto(&smc_proto
, skb
, cb
, SMCPROTO_SMC
);
236 smc_diag_dump_proto(&smc_proto6
, skb
, cb
, SMCPROTO_SMC6
);
240 static int smc_diag_handler_dump(struct sk_buff
*skb
, struct nlmsghdr
*h
)
242 struct net
*net
= sock_net(skb
->sk
);
244 if (h
->nlmsg_type
== SOCK_DIAG_BY_FAMILY
&&
245 h
->nlmsg_flags
& NLM_F_DUMP
) {
247 struct netlink_dump_control c
= {
248 .dump
= smc_diag_dump
,
249 .min_dump_alloc
= SKB_WITH_OVERHEAD(32768),
251 return netlink_dump_start(net
->diag_nlsk
, skb
, h
, &c
);
257 static const struct sock_diag_handler smc_diag_handler
= {
258 .owner
= THIS_MODULE
,
260 .dump
= smc_diag_handler_dump
,
263 static int __init
smc_diag_init(void)
265 return sock_diag_register(&smc_diag_handler
);
268 static void __exit
smc_diag_exit(void)
270 sock_diag_unregister(&smc_diag_handler
);
273 module_init(smc_diag_init
);
274 module_exit(smc_diag_exit
);
275 MODULE_LICENSE("GPL");
276 MODULE_DESCRIPTION("SMC socket monitoring via SOCK_DIAG");
277 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
, 43 /* AF_SMC */);
278 MODULE_ALIAS_GENL_FAMILY(SMCR_GENL_FAMILY_NAME
);