Skip to content

Commit 0cfdd8f

Browse files
Ursula Braundavem330
authored andcommitted
smc: connection and link group creation
* create smc_connection for SMC-sockets * determine suitable link group for a connection * create a new link group if necessary Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent a046d57 commit 0cfdd8f

File tree

7 files changed

+605
-17
lines changed

7 files changed

+605
-17
lines changed

net/smc/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
obj-$(CONFIG_SMC) += smc.o
2-
smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o
2+
smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o smc_core.o

net/smc/af_smc.c

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,19 @@
3131

3232
#include "smc.h"
3333
#include "smc_clc.h"
34+
#include "smc_core.h"
3435
#include "smc_ib.h"
3536
#include "smc_pnet.h"
3637

38+
static DEFINE_MUTEX(smc_create_lgr_pending); /* serialize link group
39+
* creation
40+
*/
41+
42+
struct smc_lgr_list smc_lgr_list = { /* established link groups */
43+
.lock = __SPIN_LOCK_UNLOCKED(smc_lgr_list.lock),
44+
.list = LIST_HEAD_INIT(smc_lgr_list.list),
45+
};
46+
3747
static void smc_tcp_listen_work(struct work_struct *);
3848

3949
static void smc_set_keepalive(struct sock *sk, int val)
@@ -235,11 +245,31 @@ int smc_netinfo_by_tcpsk(struct socket *clcsock,
235245
return rc;
236246
}
237247

248+
static void smc_conn_save_peer_info(struct smc_sock *smc,
249+
struct smc_clc_msg_accept_confirm *clc)
250+
{
251+
smc->conn.peer_conn_idx = clc->conn_idx;
252+
}
253+
254+
static void smc_link_save_peer_info(struct smc_link *link,
255+
struct smc_clc_msg_accept_confirm *clc)
256+
{
257+
link->peer_qpn = ntoh24(clc->qpn);
258+
memcpy(link->peer_gid, clc->lcl.gid, SMC_GID_SIZE);
259+
memcpy(link->peer_mac, clc->lcl.mac, sizeof(link->peer_mac));
260+
link->peer_psn = ntoh24(clc->psn);
261+
link->peer_mtu = clc->qp_mtu;
262+
}
263+
238264
/* setup for RDMA connection of client */
239265
static int smc_connect_rdma(struct smc_sock *smc)
240266
{
267+
struct sockaddr_in *inaddr = (struct sockaddr_in *)smc->addr;
241268
struct smc_clc_msg_accept_confirm aclc;
269+
int local_contact = SMC_FIRST_CONTACT;
242270
struct smc_ib_device *smcibdev;
271+
struct smc_link *link;
272+
u8 srv_first_contact;
243273
int reason_code = 0;
244274
int rc = 0;
245275
u8 ibport;
@@ -278,26 +308,43 @@ static int smc_connect_rdma(struct smc_sock *smc)
278308
if (reason_code > 0)
279309
goto decline_rdma;
280310

281-
/* tbd in follow-on patch: more steps to setup RDMA communcication,
282-
* create connection, link group, link
283-
*/
311+
srv_first_contact = aclc.hdr.flag;
312+
mutex_lock(&smc_create_lgr_pending);
313+
local_contact = smc_conn_create(smc, inaddr->sin_addr.s_addr, smcibdev,
314+
ibport, &aclc.lcl, srv_first_contact);
315+
if (local_contact < 0) {
316+
rc = local_contact;
317+
if (rc == -ENOMEM)
318+
reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/
319+
else if (rc == -ENOLINK)
320+
reason_code = SMC_CLC_DECL_SYNCERR; /* synchr. error */
321+
goto decline_rdma_unlock;
322+
}
323+
link = &smc->conn.lgr->lnk[SMC_SINGLE_LINK];
284324

325+
smc_conn_save_peer_info(smc, &aclc);
326+
if (local_contact == SMC_FIRST_CONTACT)
327+
smc_link_save_peer_info(link, &aclc);
285328
/* tbd in follow-on patch: more steps to setup RDMA communcication,
286329
* create rmbs, map rmbs, rtoken_handling, modify_qp
287330
*/
288331

289332
rc = smc_clc_send_confirm(smc);
290333
if (rc)
291-
goto out_err;
334+
goto out_err_unlock;
292335

293336
/* tbd in follow-on patch: llc_confirm */
294337

338+
mutex_unlock(&smc_create_lgr_pending);
295339
out_connected:
296340
smc_copy_sock_settings_to_clc(smc);
297341
smc->sk.sk_state = SMC_ACTIVE;
298342

299-
return rc;
343+
return rc ? rc : local_contact;
300344

345+
decline_rdma_unlock:
346+
mutex_unlock(&smc_create_lgr_pending);
347+
smc_conn_free(&smc->conn);
301348
decline_rdma:
302349
/* RDMA setup failed, switch back to TCP */
303350
smc->use_fallback = true;
@@ -308,6 +355,9 @@ static int smc_connect_rdma(struct smc_sock *smc)
308355
}
309356
goto out_connected;
310357

358+
out_err_unlock:
359+
mutex_unlock(&smc_create_lgr_pending);
360+
smc_conn_free(&smc->conn);
311361
out_err:
312362
return rc;
313363
}
@@ -476,10 +526,12 @@ static void smc_listen_work(struct work_struct *work)
476526
struct socket *newclcsock = new_smc->clcsock;
477527
struct smc_sock *lsmc = new_smc->listen_smc;
478528
struct smc_clc_msg_accept_confirm cclc;
529+
int local_contact = SMC_REUSE_CONTACT;
479530
struct sock *newsmcsk = &new_smc->sk;
480531
struct smc_clc_msg_proposal pclc;
481532
struct smc_ib_device *smcibdev;
482533
struct sockaddr_in peeraddr;
534+
struct smc_link *link;
483535
int reason_code = 0;
484536
int rc = 0, len;
485537
__be32 subnet;
@@ -527,15 +579,30 @@ static void smc_listen_work(struct work_struct *work)
527579
/* get address of the peer connected to the internal TCP socket */
528580
kernel_getpeername(newclcsock, (struct sockaddr *)&peeraddr, &len);
529581

530-
/* tbd in follow-on patch: more steps to setup RDMA communcication,
531-
* create connection, link_group, link
532-
*/
582+
/* allocate connection / link group */
583+
mutex_lock(&smc_create_lgr_pending);
584+
local_contact = smc_conn_create(new_smc, peeraddr.sin_addr.s_addr,
585+
smcibdev, ibport, &pclc.lcl, 0);
586+
if (local_contact == SMC_REUSE_CONTACT)
587+
/* lock no longer needed, free it due to following
588+
* smc_clc_wait_msg() call
589+
*/
590+
mutex_unlock(&smc_create_lgr_pending);
591+
if (local_contact < 0) {
592+
rc = local_contact;
593+
if (rc == -ENOMEM)
594+
reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/
595+
else if (rc == -ENOLINK)
596+
reason_code = SMC_CLC_DECL_SYNCERR; /* synchr. error */
597+
goto decline_rdma;
598+
}
599+
link = &new_smc->conn.lgr->lnk[SMC_SINGLE_LINK];
533600

534601
/* tbd in follow-on patch: more steps to setup RDMA communcication,
535602
* create rmbs, map rmbs
536603
*/
537604

538-
rc = smc_clc_send_accept(new_smc);
605+
rc = smc_clc_send_accept(new_smc, local_contact);
539606
if (rc)
540607
goto out_err;
541608

@@ -546,6 +613,9 @@ static void smc_listen_work(struct work_struct *work)
546613
goto out_err;
547614
if (reason_code > 0)
548615
goto decline_rdma;
616+
smc_conn_save_peer_info(new_smc, &cclc);
617+
if (local_contact == SMC_FIRST_CONTACT)
618+
smc_link_save_peer_info(link, &cclc);
549619

550620
/* tbd in follow-on patch: more steps to setup RDMA communcication,
551621
* rtoken_handling, modify_qp
@@ -555,6 +625,8 @@ static void smc_listen_work(struct work_struct *work)
555625
sk_refcnt_debug_inc(newsmcsk);
556626
newsmcsk->sk_state = SMC_ACTIVE;
557627
enqueue:
628+
if (local_contact == SMC_FIRST_CONTACT)
629+
mutex_unlock(&smc_create_lgr_pending);
558630
lock_sock(&lsmc->sk);
559631
if (lsmc->sk.sk_state == SMC_LISTEN) {
560632
smc_accept_enqueue(&lsmc->sk, newsmcsk);
@@ -570,6 +642,7 @@ static void smc_listen_work(struct work_struct *work)
570642

571643
decline_rdma:
572644
/* RDMA setup failed, switch back to TCP */
645+
smc_conn_free(&new_smc->conn);
573646
new_smc->use_fallback = true;
574647
if (reason_code && (reason_code != SMC_CLC_DECL_REPLY)) {
575648
rc = smc_clc_send_decline(new_smc, reason_code, 0);
@@ -1024,6 +1097,17 @@ static int __init smc_init(void)
10241097

10251098
static void __exit smc_exit(void)
10261099
{
1100+
struct smc_link_group *lgr, *lg;
1101+
LIST_HEAD(lgr_freeing_list);
1102+
1103+
spin_lock_bh(&smc_lgr_list.lock);
1104+
if (!list_empty(&smc_lgr_list.list))
1105+
list_splice_init(&smc_lgr_list.list, &lgr_freeing_list);
1106+
spin_unlock_bh(&smc_lgr_list.lock);
1107+
list_for_each_entry_safe(lgr, lg, &lgr_freeing_list, list) {
1108+
list_del_init(&lgr->list);
1109+
smc_lgr_free(lgr); /* free link group */
1110+
}
10271111
smc_ib_unregister_client();
10281112
sock_unregister(PF_SMC);
10291113
proto_unregister(&smc_proto);

net/smc/smc.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <linux/types.h>
1515
#include <net/sock.h>
1616

17+
#include "smc_ib.h"
18+
1719
#define SMCPROTO_SMC 0 /* SMC protocol */
1820

1921
#define SMC_MAX_PORTS 2 /* Max # of ports */
@@ -25,9 +27,19 @@ enum smc_state { /* possible states of an SMC socket */
2527
SMC_LISTEN = 10,
2628
};
2729

30+
struct smc_link_group;
31+
32+
struct smc_connection {
33+
struct rb_node alert_node;
34+
struct smc_link_group *lgr; /* link group of connection */
35+
u32 alert_token_local; /* unique conn. id */
36+
u8 peer_conn_idx; /* from tcp handshake */
37+
};
38+
2839
struct smc_sock { /* smc sock container */
2940
struct sock sk;
3041
struct socket *clcsock; /* internal tcp socket */
42+
struct smc_connection conn; /* smc connection */
3143
struct sockaddr *addr; /* inet connect address */
3244
struct smc_sock *listen_smc; /* listen parent */
3345
struct work_struct tcp_listen_work;/* handle tcp socket accepts */
@@ -46,6 +58,24 @@ static inline struct smc_sock *smc_sk(const struct sock *sk)
4658

4759
extern u8 local_systemid[SMC_SYSTEMID_LEN]; /* unique system identifier */
4860

61+
/* convert an u32 value into network byte order, store it into a 3 byte field */
62+
static inline void hton24(u8 *net, u32 host)
63+
{
64+
__be32 t;
65+
66+
t = cpu_to_be32(host);
67+
memcpy(net, ((u8 *)&t) + 1, 3);
68+
}
69+
70+
/* convert a received 3 byte field into host byte order*/
71+
static inline u32 ntoh24(u8 *net)
72+
{
73+
__be32 t = 0;
74+
75+
memcpy(((u8 *)&t) + 1, net, 3);
76+
return be32_to_cpu(t);
77+
}
78+
4979
#ifdef CONFIG_XFRM
5080
static inline bool using_ipsec(struct smc_sock *smc)
5181
{
@@ -59,7 +89,13 @@ static inline bool using_ipsec(struct smc_sock *smc)
5989
}
6090
#endif
6191

92+
struct smc_clc_msg_local;
93+
6294
int smc_netinfo_by_tcpsk(struct socket *clcsock, __be32 *subnet,
6395
u8 *prefix_len);
96+
void smc_conn_free(struct smc_connection *conn);
97+
int smc_conn_create(struct smc_sock *smc, __be32 peer_in_addr,
98+
struct smc_ib_device *smcibdev, u8 ibport,
99+
struct smc_clc_msg_local *lcl, int srv_first_contact);
64100

65101
#endif /* __SMC_H */

net/smc/smc_clc.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <net/tcp.h>
1515

1616
#include "smc.h"
17+
#include "smc_core.h"
1718
#include "smc_clc.h"
1819
#include "smc_ib.h"
1920

@@ -89,8 +90,13 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
8990
reason_code = -EPROTO;
9091
goto out;
9192
}
92-
if (clcm->type == SMC_CLC_DECLINE)
93+
if (clcm->type == SMC_CLC_DECLINE) {
9394
reason_code = SMC_CLC_DECL_REPLY;
95+
if (ntohl(((struct smc_clc_msg_decline *)buf)->peer_diagnosis)
96+
== SMC_CLC_DECL_SYNCERR)
97+
smc->conn.lgr->sync_err = true;
98+
}
99+
94100
out:
95101
return reason_code;
96102
}
@@ -175,25 +181,34 @@ int smc_clc_send_proposal(struct smc_sock *smc,
175181
/* send CLC CONFIRM message across internal TCP socket */
176182
int smc_clc_send_confirm(struct smc_sock *smc)
177183
{
184+
struct smc_connection *conn = &smc->conn;
178185
struct smc_clc_msg_accept_confirm cclc;
186+
struct smc_link *link;
179187
int reason_code = 0;
180188
struct msghdr msg;
181189
struct kvec vec;
182190
int len;
183191

192+
link = &conn->lgr->lnk[SMC_SINGLE_LINK];
184193
/* send SMC Confirm CLC msg */
185194
memset(&cclc, 0, sizeof(cclc));
186195
memcpy(cclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
187196
cclc.hdr.type = SMC_CLC_CONFIRM;
188197
cclc.hdr.length = htons(sizeof(cclc));
189198
cclc.hdr.version = SMC_CLC_V1; /* SMC version */
190199
memcpy(cclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid));
191-
192-
/* tbd in follow-on patch: fill in link-related values */
200+
memcpy(&cclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
201+
SMC_GID_SIZE);
202+
memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1],
203+
sizeof(link->smcibdev->mac));
193204

194205
/* tbd in follow-on patch: fill in rmb-related values */
195206

207+
hton24(cclc.qpn, link->roce_qp->qp_num);
196208
cclc.conn_idx = 1; /* for now: 1 RMB = 1 RMBE */
209+
cclc.rmbe_alert_token = htonl(conn->alert_token_local);
210+
cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
211+
hton24(cclc.psn, link->psn_initial);
197212

198213
memcpy(cclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
199214

@@ -214,26 +229,37 @@ int smc_clc_send_confirm(struct smc_sock *smc)
214229
}
215230

216231
/* send CLC ACCEPT message across internal TCP socket */
217-
int smc_clc_send_accept(struct smc_sock *new_smc)
232+
int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
218233
{
234+
struct smc_connection *conn = &new_smc->conn;
219235
struct smc_clc_msg_accept_confirm aclc;
236+
struct smc_link *link;
220237
struct msghdr msg;
221238
struct kvec vec;
222239
int rc = 0;
223240
int len;
224241

242+
link = &conn->lgr->lnk[SMC_SINGLE_LINK];
225243
memset(&aclc, 0, sizeof(aclc));
226244
memcpy(aclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
227245
aclc.hdr.type = SMC_CLC_ACCEPT;
228246
aclc.hdr.length = htons(sizeof(aclc));
229247
aclc.hdr.version = SMC_CLC_V1; /* SMC version */
248+
if (srv_first_contact)
249+
aclc.hdr.flag = 1;
230250
memcpy(aclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid));
231-
232-
/* tbd in follow-on patch: fill in link-related values */
251+
memcpy(&aclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
252+
SMC_GID_SIZE);
253+
memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1],
254+
sizeof(link->smcibdev->mac[link->ibport - 1]));
233255

234256
/* tbd in follow-on patch: fill in rmb-related values */
235257

258+
hton24(aclc.qpn, link->roce_qp->qp_num);
236259
aclc.conn_idx = 1; /* as long as 1 RMB = 1 RMBE */
260+
aclc.rmbe_alert_token = htonl(conn->alert_token_local);
261+
aclc.qp_mtu = link->path_mtu;
262+
hton24(aclc.psn, link->psn_initial);
237263
memcpy(aclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
238264

239265
memset(&msg, 0, sizeof(msg));

net/smc/smc_clc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,6 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info,
109109
int smc_clc_send_proposal(struct smc_sock *smc, struct smc_ib_device *smcibdev,
110110
u8 ibport);
111111
int smc_clc_send_confirm(struct smc_sock *smc);
112-
int smc_clc_send_accept(struct smc_sock *smc);
112+
int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact);
113113

114114
#endif

0 commit comments

Comments
 (0)