2 * Shared Memory Communications over RDMA (SMC-R) and RoCE
4 * Monitoring SMC transport protocol sockets
6 * Copyright IBM Corp. 2016
8 * Author(s): Ursula Braun <ubraun@linux.vnet.ibm.com>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/types.h>
14 #include <linux/init.h>
15 #include <linux/sock_diag.h>
16 #include <linux/inet_diag.h>
17 #include <linux/smc_diag.h>
18 #include <net/netlink.h>
24 static void smc_gid_be16_convert(__u8
*buf
, u8
*gid_raw
)
26 sprintf(buf
, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
27 be16_to_cpu(((__be16
*)gid_raw
)[0]),
28 be16_to_cpu(((__be16
*)gid_raw
)[1]),
29 be16_to_cpu(((__be16
*)gid_raw
)[2]),
30 be16_to_cpu(((__be16
*)gid_raw
)[3]),
31 be16_to_cpu(((__be16
*)gid_raw
)[4]),
32 be16_to_cpu(((__be16
*)gid_raw
)[5]),
33 be16_to_cpu(((__be16
*)gid_raw
)[6]),
34 be16_to_cpu(((__be16
*)gid_raw
)[7]));
37 static void smc_diag_msg_common_fill(struct smc_diag_msg
*r
, struct sock
*sk
)
39 struct smc_sock
*smc
= smc_sk(sk
);
41 r
->diag_family
= sk
->sk_family
;
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 sock_diag_save_cookie(sk
, r
->id
.idiag_cookie
);
48 memset(&r
->id
.idiag_src
, 0, sizeof(r
->id
.idiag_src
));
49 memset(&r
->id
.idiag_dst
, 0, sizeof(r
->id
.idiag_dst
));
50 r
->id
.idiag_src
[0] = smc
->clcsock
->sk
->sk_rcv_saddr
;
51 r
->id
.idiag_dst
[0] = smc
->clcsock
->sk
->sk_daddr
;
54 static int smc_diag_msg_attrs_fill(struct sock
*sk
, struct sk_buff
*skb
,
55 struct smc_diag_msg
*r
,
56 struct user_namespace
*user_ns
)
58 if (nla_put_u8(skb
, SMC_DIAG_SHUTDOWN
, sk
->sk_shutdown
))
61 r
->diag_uid
= from_kuid_munged(user_ns
, sock_i_uid(sk
));
62 r
->diag_inode
= sock_i_ino(sk
);
66 static int __smc_diag_dump(struct sock
*sk
, struct sk_buff
*skb
,
67 struct netlink_callback
*cb
,
68 const struct smc_diag_req
*req
,
71 struct smc_sock
*smc
= smc_sk(sk
);
72 struct user_namespace
*user_ns
;
73 struct smc_diag_msg
*r
;
76 nlh
= nlmsg_put(skb
, NETLINK_CB(cb
->skb
).portid
, cb
->nlh
->nlmsg_seq
,
77 cb
->nlh
->nlmsg_type
, sizeof(*r
), NLM_F_MULTI
);
82 smc_diag_msg_common_fill(r
, sk
);
83 r
->diag_state
= sk
->sk_state
;
84 r
->diag_fallback
= smc
->use_fallback
;
85 user_ns
= sk_user_ns(NETLINK_CB(cb
->skb
).sk
);
86 if (smc_diag_msg_attrs_fill(sk
, skb
, r
, user_ns
))
89 if ((req
->diag_ext
& (1 << (SMC_DIAG_CONNINFO
- 1))) && smc
->conn
.lgr
) {
90 struct smc_connection
*conn
= &smc
->conn
;
91 struct smc_diag_conninfo cinfo
= {
92 .token
= conn
->alert_token_local
,
93 .sndbuf_size
= conn
->sndbuf_size
,
94 .rmbe_size
= conn
->rmbe_size
,
95 .peer_rmbe_size
= conn
->peer_rmbe_size
,
97 .rx_prod
.wrap
= conn
->local_rx_ctrl
.prod
.wrap
,
98 .rx_prod
.count
= conn
->local_rx_ctrl
.prod
.count
,
99 .rx_cons
.wrap
= conn
->local_rx_ctrl
.cons
.wrap
,
100 .rx_cons
.count
= conn
->local_rx_ctrl
.cons
.count
,
102 .tx_prod
.wrap
= conn
->local_tx_ctrl
.prod
.wrap
,
103 .tx_prod
.count
= conn
->local_tx_ctrl
.prod
.count
,
104 .tx_cons
.wrap
= conn
->local_tx_ctrl
.cons
.wrap
,
105 .tx_cons
.count
= conn
->local_tx_ctrl
.cons
.count
,
108 *(u8
*)&conn
->local_tx_ctrl
.prod_flags
,
109 .tx_conn_state_flags
=
110 *(u8
*)&conn
->local_tx_ctrl
.conn_state_flags
,
111 .rx_prod_flags
= *(u8
*)&conn
->local_rx_ctrl
.prod_flags
,
112 .rx_conn_state_flags
=
113 *(u8
*)&conn
->local_rx_ctrl
.conn_state_flags
,
115 .tx_prep
.wrap
= conn
->tx_curs_prep
.wrap
,
116 .tx_prep
.count
= conn
->tx_curs_prep
.count
,
117 .tx_sent
.wrap
= conn
->tx_curs_sent
.wrap
,
118 .tx_sent
.count
= conn
->tx_curs_sent
.count
,
119 .tx_fin
.wrap
= conn
->tx_curs_fin
.wrap
,
120 .tx_fin
.count
= conn
->tx_curs_fin
.count
,
123 if (nla_put(skb
, SMC_DIAG_CONNINFO
, sizeof(cinfo
), &cinfo
) < 0)
127 if ((req
->diag_ext
& (1 << (SMC_DIAG_LGRINFO
- 1))) && smc
->conn
.lgr
) {
128 struct smc_diag_lgrinfo linfo
= {
129 .role
= smc
->conn
.lgr
->role
,
130 .lnk
[0].ibport
= smc
->conn
.lgr
->lnk
[0].ibport
,
131 .lnk
[0].link_id
= smc
->conn
.lgr
->lnk
[0].link_id
,
134 memcpy(linfo
.lnk
[0].ibname
,
135 smc
->conn
.lgr
->lnk
[0].smcibdev
->ibdev
->name
,
136 sizeof(smc
->conn
.lgr
->lnk
[0].smcibdev
->ibdev
->name
));
137 smc_gid_be16_convert(linfo
.lnk
[0].gid
,
138 smc
->conn
.lgr
->lnk
[0].gid
.raw
);
139 smc_gid_be16_convert(linfo
.lnk
[0].peer_gid
,
140 smc
->conn
.lgr
->lnk
[0].peer_gid
);
142 if (nla_put(skb
, SMC_DIAG_LGRINFO
, sizeof(linfo
), &linfo
) < 0)
150 nlmsg_cancel(skb
, nlh
);
154 static int smc_diag_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
)
156 struct net
*net
= sock_net(skb
->sk
);
157 struct nlattr
*bc
= NULL
;
158 struct hlist_head
*head
;
162 read_lock(&smc_proto
.h
.smc_hash
->lock
);
163 head
= &smc_proto
.h
.smc_hash
->ht
;
164 if (hlist_empty(head
))
167 sk_for_each(sk
, head
) {
168 if (!net_eq(sock_net(sk
), net
))
170 rc
= __smc_diag_dump(sk
, skb
, cb
, nlmsg_data(cb
->nlh
), bc
);
176 read_unlock(&smc_proto
.h
.smc_hash
->lock
);
180 static int smc_diag_handler_dump(struct sk_buff
*skb
, struct nlmsghdr
*h
)
182 struct net
*net
= sock_net(skb
->sk
);
184 if (h
->nlmsg_type
== SOCK_DIAG_BY_FAMILY
&&
185 h
->nlmsg_flags
& NLM_F_DUMP
) {
187 struct netlink_dump_control c
= {
188 .dump
= smc_diag_dump
,
189 .min_dump_alloc
= SKB_WITH_OVERHEAD(32768),
191 return netlink_dump_start(net
->diag_nlsk
, skb
, h
, &c
);
197 static const struct sock_diag_handler smc_diag_handler
= {
199 .dump
= smc_diag_handler_dump
,
202 static int __init
smc_diag_init(void)
204 return sock_diag_register(&smc_diag_handler
);
207 static void __exit
smc_diag_exit(void)
209 sock_diag_unregister(&smc_diag_handler
);
212 module_init(smc_diag_init
);
213 module_exit(smc_diag_exit
);
214 MODULE_LICENSE("GPL");
215 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK
, NETLINK_SOCK_DIAG
, 43 /* AF_SMC */);