Blame view
net/smc/af_smc.c
52.9 KB
09c434b8a treewide: Add SPD... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
ac7138746 smc: establish ne... |
2 3 4 5 6 7 8 9 |
/* * Shared Memory Communications over RDMA (SMC-R) and RoCE * * AF_SMC protocol family socket handler keeping the AF_INET sock address type * applies to SOCK_STREAM sockets only * offers an alternative communication option for TCP-protocol sockets * applicable with RoCE-cards only * |
a046d57da smc: CLC handshak... |
10 |
* Initial restrictions: |
a046d57da smc: CLC handshak... |
11 |
* - support for alternate links postponed |
a046d57da smc: CLC handshak... |
12 |
* |
aaa4d33f6 net/smc: enable i... |
13 |
* Copyright IBM Corp. 2016, 2018 |
ac7138746 smc: establish ne... |
14 15 16 17 18 19 20 21 22 23 |
* * Author(s): Ursula Braun <ubraun@linux.vnet.ibm.com> * based on prototype from Frank Blaschka */ #define KMSG_COMPONENT "smc" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/module.h> #include <linux/socket.h> |
a046d57da smc: CLC handshak... |
24 |
#include <linux/workqueue.h> |
5f08318f6 smc: connection d... |
25 |
#include <linux/in.h> |
c3edc4010 sched/headers: Mo... |
26 |
#include <linux/sched/signal.h> |
413498440 net/smc: add SMC-... |
27 |
#include <linux/if_vlan.h> |
4ead9c96d net/smc: use rcu_... |
28 |
#include <linux/rcupdate_wait.h> |
c3edc4010 sched/headers: Mo... |
29 |
|
ac7138746 smc: establish ne... |
30 |
#include <net/sock.h> |
a046d57da smc: CLC handshak... |
31 |
#include <net/tcp.h> |
f16a7dd5c smc: netlink inte... |
32 |
#include <net/smc.h> |
9b67e26f9 net/smc: handle i... |
33 |
#include <asm/ioctls.h> |
ac7138746 smc: establish ne... |
34 |
|
64e28b52c net/smc: add pnet... |
35 36 37 |
#include <net/net_namespace.h> #include <net/netns/generic.h> #include "smc_netns.h" |
ac7138746 smc: establish ne... |
38 |
#include "smc.h" |
a046d57da smc: CLC handshak... |
39 |
#include "smc_clc.h" |
9bf9abead smc: link layer c... |
40 |
#include "smc_llc.h" |
5f08318f6 smc: connection d... |
41 |
#include "smc_cdc.h" |
0cfdd8f92 smc: connection a... |
42 |
#include "smc_core.h" |
a4cf0443c smc: introduce SM... |
43 |
#include "smc_ib.h" |
413498440 net/smc: add SMC-... |
44 |
#include "smc_ism.h" |
6812baabf smc: establish pn... |
45 |
#include "smc_pnet.h" |
e6727f390 smc: send data (t... |
46 |
#include "smc_tx.h" |
952310ccf smc: receive data... |
47 |
#include "smc_rx.h" |
b38d73247 smc: socket closi... |
48 |
#include "smc_close.h" |
ac7138746 smc: establish ne... |
49 |
|
72a36a8ae net/smc: use clie... |
50 51 52 53 54 |
static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group * creation on server */ static DEFINE_MUTEX(smc_client_lgr_pending); /* serialize link group * creation on client |
0cfdd8f92 smc: connection a... |
55 |
*/ |
a046d57da smc: CLC handshak... |
56 |
static void smc_tcp_listen_work(struct work_struct *); |
24ac3a08e net/smc: rebuild ... |
57 |
static void smc_connect_work(struct work_struct *); |
a046d57da smc: CLC handshak... |
58 |
|
ac7138746 smc: establish ne... |
59 60 61 62 63 64 |
static void smc_set_keepalive(struct sock *sk, int val) { struct smc_sock *smc = smc_sk(sk); smc->clcsock->sk->sk_prot->keepalive(smc->clcsock->sk, val); } |
f16a7dd5c smc: netlink inte... |
65 66 67 |
static struct smc_hashinfo smc_v4_hashinfo = { .lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock), }; |
aaa4d33f6 net/smc: enable i... |
68 69 70 |
static struct smc_hashinfo smc_v6_hashinfo = { .lock = __RW_LOCK_UNLOCKED(smc_v6_hashinfo.lock), }; |
f16a7dd5c smc: netlink inte... |
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
int smc_hash_sk(struct sock *sk) { struct smc_hashinfo *h = sk->sk_prot->h.smc_hash; struct hlist_head *head; head = &h->ht; write_lock_bh(&h->lock); sk_add_node(sk, head); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); write_unlock_bh(&h->lock); return 0; } EXPORT_SYMBOL_GPL(smc_hash_sk); void smc_unhash_sk(struct sock *sk) { struct smc_hashinfo *h = sk->sk_prot->h.smc_hash; write_lock_bh(&h->lock); if (sk_del_node_init(sk)) sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); write_unlock_bh(&h->lock); } EXPORT_SYMBOL_GPL(smc_unhash_sk); struct proto smc_proto = { |
ac7138746 smc: establish ne... |
99 100 101 |
.name = "SMC", .owner = THIS_MODULE, .keepalive = smc_set_keepalive, |
f16a7dd5c smc: netlink inte... |
102 103 |
.hash = smc_hash_sk, .unhash = smc_unhash_sk, |
ac7138746 smc: establish ne... |
104 |
.obj_size = sizeof(struct smc_sock), |
f16a7dd5c smc: netlink inte... |
105 |
.h.smc_hash = &smc_v4_hashinfo, |
5f0d5a3ae mm: Rename SLAB_D... |
106 |
.slab_flags = SLAB_TYPESAFE_BY_RCU, |
ac7138746 smc: establish ne... |
107 |
}; |
f16a7dd5c smc: netlink inte... |
108 |
EXPORT_SYMBOL_GPL(smc_proto); |
ac7138746 smc: establish ne... |
109 |
|
aaa4d33f6 net/smc: enable i... |
110 111 112 113 114 115 116 117 118 119 120 |
struct proto smc_proto6 = { .name = "SMC6", .owner = THIS_MODULE, .keepalive = smc_set_keepalive, .hash = smc_hash_sk, .unhash = smc_unhash_sk, .obj_size = sizeof(struct smc_sock), .h.smc_hash = &smc_v6_hashinfo, .slab_flags = SLAB_TYPESAFE_BY_RCU, }; EXPORT_SYMBOL_GPL(smc_proto6); |
f536dffc0 net/smc: fix clos... |
121 122 123 124 125 |
static void smc_restore_fallback_changes(struct smc_sock *smc) { smc->clcsock->file->private_data = smc->sk.sk_socket; smc->clcsock->file = NULL; } |
39f41f367 net/smc: common r... |
126 |
static int __smc_release(struct smc_sock *smc) |
ac7138746 smc: establish ne... |
127 |
{ |
39f41f367 net/smc: common r... |
128 |
struct sock *sk = &smc->sk; |
b38d73247 smc: socket closi... |
129 |
int rc = 0; |
ac7138746 smc: establish ne... |
130 |
|
51f1de79a net/smc: replace ... |
131 |
if (!smc->use_fallback) { |
b38d73247 smc: socket closi... |
132 133 134 |
rc = smc_close_active(smc); sock_set_flag(sk, SOCK_DEAD); sk->sk_shutdown |= SHUTDOWN_MASK; |
b03faa1fa net/smc: postpone... |
135 136 137 138 |
} else { if (sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_INIT) sock_put(sk); /* passive closing */ if (sk->sk_state == SMC_LISTEN) { |
78abe3d0d net/smc: fix TCP ... |
139 140 141 |
/* wake up clcsock accept */ rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); } |
51f1de79a net/smc: replace ... |
142 143 |
sk->sk_state = SMC_CLOSED; sk->sk_state_change(sk); |
f536dffc0 net/smc: fix clos... |
144 |
smc_restore_fallback_changes(smc); |
51f1de79a net/smc: replace ... |
145 |
} |
ac7138746 smc: establish ne... |
146 |
|
b03faa1fa net/smc: postpone... |
147 148 149 150 |
sk->sk_prot->unhash(sk); if (sk->sk_state == SMC_CLOSED) { if (smc->clcsock) { |
fd57770dd net/smc: wait for... |
151 152 153 |
release_sock(sk); smc_clcsock_release(smc); lock_sock(sk); |
b03faa1fa net/smc: postpone... |
154 155 156 157 |
} if (!smc->use_fallback) smc_conn_free(&smc->conn); } |
39f41f367 net/smc: common r... |
158 159 160 161 162 163 164 165 166 167 168 |
return rc; } static int smc_release(struct socket *sock) { struct sock *sk = sock->sk; struct smc_sock *smc; int rc = 0; if (!sk) goto out; |
81cf4f470 net/smc: remove c... |
169 |
sock_hold(sk); /* sock_put below */ |
39f41f367 net/smc: common r... |
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
smc = smc_sk(sk); /* cleanup for a dangling non-blocking connect */ if (smc->connect_nonblock && sk->sk_state == SMC_INIT) tcp_abort(smc->clcsock->sk, ECONNABORTED); flush_work(&smc->connect_work); if (sk->sk_state == SMC_LISTEN) /* smc_close_non_accepted() is called and acquires * sock lock for child sockets again */ lock_sock_nested(sk, SINGLE_DEPTH_NESTING); else lock_sock(sk); rc = __smc_release(smc); |
ac7138746 smc: establish ne... |
186 187 188 189 |
/* detach socket */ sock_orphan(sk); sock->sk = NULL; release_sock(sk); |
81cf4f470 net/smc: remove c... |
190 |
sock_put(sk); /* sock_hold above */ |
51f1de79a net/smc: replace ... |
191 |
sock_put(sk); /* final sock_put */ |
ac7138746 smc: establish ne... |
192 |
out: |
b38d73247 smc: socket closi... |
193 |
return rc; |
ac7138746 smc: establish ne... |
194 195 196 197 198 199 200 201 202 203 204 |
} static void smc_destruct(struct sock *sk) { if (sk->sk_state != SMC_CLOSED) return; if (!sock_flag(sk, SOCK_DEAD)) return; sk_refcnt_debug_dec(sk); } |
aaa4d33f6 net/smc: enable i... |
205 206 |
static struct sock *smc_sock_alloc(struct net *net, struct socket *sock, int protocol) |
ac7138746 smc: establish ne... |
207 208 |
{ struct smc_sock *smc; |
aaa4d33f6 net/smc: enable i... |
209 |
struct proto *prot; |
ac7138746 smc: establish ne... |
210 |
struct sock *sk; |
aaa4d33f6 net/smc: enable i... |
211 212 |
prot = (protocol == SMCPROTO_SMC6) ? &smc_proto6 : &smc_proto; sk = sk_alloc(net, PF_SMC, GFP_KERNEL, prot, 0); |
ac7138746 smc: establish ne... |
213 214 215 216 217 218 |
if (!sk) return NULL; sock_init_data(sock, sk); /* sets sk_refcnt to 1 */ sk->sk_state = SMC_INIT; sk->sk_destruct = smc_destruct; |
aaa4d33f6 net/smc: enable i... |
219 |
sk->sk_protocol = protocol; |
ac7138746 smc: establish ne... |
220 |
smc = smc_sk(sk); |
a046d57da smc: CLC handshak... |
221 |
INIT_WORK(&smc->tcp_listen_work, smc_tcp_listen_work); |
24ac3a08e net/smc: rebuild ... |
222 |
INIT_WORK(&smc->connect_work, smc_connect_work); |
be7f3e599 net/smc: init con... |
223 |
INIT_DELAYED_WORK(&smc->conn.tx_work, smc_tx_work); |
a046d57da smc: CLC handshak... |
224 225 |
INIT_LIST_HEAD(&smc->accept_q); spin_lock_init(&smc->accept_q_lock); |
be7f3e599 net/smc: init con... |
226 |
spin_lock_init(&smc->conn.send_lock); |
f16a7dd5c smc: netlink inte... |
227 |
sk->sk_prot->hash(sk); |
a046d57da smc: CLC handshak... |
228 |
sk_refcnt_debug_inc(sk); |
78abe3d0d net/smc: fix TCP ... |
229 |
mutex_init(&smc->clcsock_release_lock); |
ac7138746 smc: establish ne... |
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
return sk; } static int smc_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; struct sock *sk = sock->sk; struct smc_sock *smc; int rc; smc = smc_sk(sk); /* replicate tests from inet_bind(), to be safe wrt. future changes */ rc = -EINVAL; if (addr_len < sizeof(struct sockaddr_in)) goto out; rc = -EAFNOSUPPORT; |
aaa4d33f6 net/smc: enable i... |
250 251 252 253 |
if (addr->sin_family != AF_INET && addr->sin_family != AF_INET6 && addr->sin_family != AF_UNSPEC) goto out; |
ac7138746 smc: establish ne... |
254 |
/* accept AF_UNSPEC (mapped to AF_INET) only if s_addr is INADDR_ANY */ |
aaa4d33f6 net/smc: enable i... |
255 256 |
if (addr->sin_family == AF_UNSPEC && addr->sin_addr.s_addr != htonl(INADDR_ANY)) |
ac7138746 smc: establish ne... |
257 258 259 260 261 262 |
goto out; lock_sock(sk); /* Check if socket is already active */ rc = -EINVAL; |
cd2063604 net/smc: avoid fa... |
263 |
if (sk->sk_state != SMC_INIT || smc->connect_nonblock) |
ac7138746 smc: establish ne... |
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
goto out_rel; smc->clcsock->sk->sk_reuse = sk->sk_reuse; rc = kernel_bind(smc->clcsock, uaddr, addr_len); out_rel: release_sock(sk); out: return rc; } static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk, unsigned long mask) { /* options we don't get control via setsockopt for */ nsk->sk_type = osk->sk_type; nsk->sk_sndbuf = osk->sk_sndbuf; nsk->sk_rcvbuf = osk->sk_rcvbuf; nsk->sk_sndtimeo = osk->sk_sndtimeo; nsk->sk_rcvtimeo = osk->sk_rcvtimeo; nsk->sk_mark = osk->sk_mark; nsk->sk_priority = osk->sk_priority; nsk->sk_rcvlowat = osk->sk_rcvlowat; nsk->sk_bound_dev_if = osk->sk_bound_dev_if; nsk->sk_err = osk->sk_err; nsk->sk_flags &= ~mask; nsk->sk_flags |= osk->sk_flags & mask; } #define SK_FLAGS_SMC_TO_CLC ((1UL << SOCK_URGINLINE) | \ (1UL << SOCK_KEEPOPEN) | \ (1UL << SOCK_LINGER) | \ (1UL << SOCK_BROADCAST) | \ (1UL << SOCK_TIMESTAMP) | \ (1UL << SOCK_DBG) | \ (1UL << SOCK_RCVTSTAMP) | \ (1UL << SOCK_RCVTSTAMPNS) | \ (1UL << SOCK_LOCALROUTE) | \ (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) | \ (1UL << SOCK_RXQ_OVFL) | \ (1UL << SOCK_WIFI_STATUS) | \ (1UL << SOCK_NOFCS) | \ |
9718475e6 socket: Add SO_TI... |
307 308 |
(1UL << SOCK_FILTER_LOCKED) | \ (1UL << SOCK_TSTAMP_NEW)) |
ac7138746 smc: establish ne... |
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
/* copy only relevant settings and flags of SOL_SOCKET level from smc to * clc socket (since smc is not called for these options from net/core) */ static void smc_copy_sock_settings_to_clc(struct smc_sock *smc) { smc_copy_sock_settings(smc->clcsock->sk, &smc->sk, SK_FLAGS_SMC_TO_CLC); } #define SK_FLAGS_CLC_TO_SMC ((1UL << SOCK_URGINLINE) | \ (1UL << SOCK_KEEPOPEN) | \ (1UL << SOCK_LINGER) | \ (1UL << SOCK_DBG)) /* copy only settings and flags relevant for smc from clc to smc socket */ static void smc_copy_sock_settings_to_smc(struct smc_sock *smc) { smc_copy_sock_settings(&smc->sk, smc->clcsock->sk, SK_FLAGS_CLC_TO_SMC); } |
c7674c001 net/smc: unregist... |
326 |
/* register a new rmb, send confirm_rkey msg to register with peer */ |
44aa81ce9 net/smc: register... |
327 328 |
static int smc_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc, bool conf_rkey) |
e63a5f8c1 net/smc: call con... |
329 |
{ |
c7674c001 net/smc: unregist... |
330 331 332 333 334 335 336 |
if (!rmb_desc->wr_reg) { /* register memory region for new rmb */ if (smc_wr_reg_send(link, rmb_desc->mr_rx[SMC_SINGLE_LINK])) { rmb_desc->regerr = 1; return -EFAULT; } rmb_desc->wr_reg = 1; |
a6920d1d1 net/smc: handle u... |
337 |
} |
44aa81ce9 net/smc: register... |
338 339 340 341 342 343 344 |
if (!conf_rkey) return 0; /* exchange confirm_rkey msg with peer */ if (smc_llc_do_confirm_rkey(link, rmb_desc)) { rmb_desc->regerr = 1; return -EFAULT; } |
e63a5f8c1 net/smc: call con... |
345 346 |
return 0; } |
0f6271264 net/smc: cleanup ... |
347 |
static int smc_clnt_conf_first_link(struct smc_sock *smc) |
9bf9abead smc: link layer c... |
348 |
{ |
877ae5be4 net/smc: periodic... |
349 |
struct net *net = sock_net(smc->clcsock->sk); |
9bf9abead smc: link layer c... |
350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
struct smc_link_group *lgr = smc->conn.lgr; struct smc_link *link; int rest; int rc; link = &lgr->lnk[SMC_SINGLE_LINK]; /* receive CONFIRM LINK request from server over RoCE fabric */ rest = wait_for_completion_interruptible_timeout( &link->llc_confirm, SMC_LLC_WAIT_FIRST_TIME); if (rest <= 0) { struct smc_clc_msg_decline dclc; rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), |
2b59f58e3 net/smc: short wa... |
364 |
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT); |
9ed28556a net/smc: allow fa... |
365 |
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc; |
9bf9abead smc: link layer c... |
366 |
} |
75d320d61 net/smc: do not a... |
367 368 |
if (link->llc_confirm_rc) return SMC_CLC_DECL_RMBE_EC; |
9bf9abead smc: link layer c... |
369 370 |
rc = smc_ib_modify_qp_rts(link); if (rc) |
603cc1498 net/smc: provide ... |
371 |
return SMC_CLC_DECL_ERR_RDYLNK; |
9bf9abead smc: link layer c... |
372 373 |
smc_wr_remember_qp_attr(link); |
652a1e41e net/smc: register... |
374 |
|
44aa81ce9 net/smc: register... |
375 |
if (smc_reg_rmb(link, smc->conn.rmb_desc, false)) |
603cc1498 net/smc: provide ... |
376 |
return SMC_CLC_DECL_ERR_REGRMB; |
652a1e41e net/smc: register... |
377 |
|
9bf9abead smc: link layer c... |
378 |
/* send CONFIRM LINK response over RoCE fabric */ |
947541f36 net/smc: fewer pa... |
379 |
rc = smc_llc_send_confirm_link(link, SMC_LLC_RESP); |
9bf9abead smc: link layer c... |
380 |
if (rc < 0) |
603cc1498 net/smc: provide ... |
381 |
return SMC_CLC_DECL_TIMEOUT_CL; |
9bf9abead smc: link layer c... |
382 |
|
52bedf37b net/smc: process ... |
383 384 385 386 387 388 389 |
/* receive ADD LINK request from server over RoCE fabric */ rest = wait_for_completion_interruptible_timeout(&link->llc_add, SMC_LLC_WAIT_TIME); if (rest <= 0) { struct smc_clc_msg_decline dclc; rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), |
2b59f58e3 net/smc: short wa... |
390 |
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT); |
9ed28556a net/smc: allow fa... |
391 |
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc; |
52bedf37b net/smc: process ... |
392 393 394 395 396 |
} /* send add link reject message, only one link supported for now */ rc = smc_llc_send_add_link(link, link->smcibdev->mac[link->ibport - 1], |
7005ada68 net/smc: use corr... |
397 |
link->gid, SMC_LLC_RESP); |
52bedf37b net/smc: process ... |
398 |
if (rc < 0) |
603cc1498 net/smc: provide ... |
399 |
return SMC_CLC_DECL_TIMEOUT_AL; |
52bedf37b net/smc: process ... |
400 |
|
877ae5be4 net/smc: periodic... |
401 |
smc_llc_link_active(link, net->ipv4.sysctl_tcp_keepalive_time); |
52bedf37b net/smc: process ... |
402 |
|
75d320d61 net/smc: do not a... |
403 |
return 0; |
9bf9abead smc: link layer c... |
404 |
} |
413498440 net/smc: add SMC-... |
405 406 |
static void smcr_conn_save_peer_info(struct smc_sock *smc, struct smc_clc_msg_accept_confirm *clc) |
0cfdd8f92 smc: connection a... |
407 |
{ |
95d8d2630 net/smc: calculat... |
408 |
int bufsize = smc_uncompress_bufsize(clc->rmbe_size); |
92a138e33 net/smc: rename c... |
409 |
smc->conn.peer_rmbe_idx = clc->rmbe_idx; |
5f08318f6 smc: connection d... |
410 |
smc->conn.local_tx_ctrl.token = ntohl(clc->rmbe_alert_token); |
95d8d2630 net/smc: calculat... |
411 |
smc->conn.peer_rmbe_size = bufsize; |
cd6851f30 smc: remote memor... |
412 |
atomic_set(&smc->conn.peer_rmbe_space, smc->conn.peer_rmbe_size); |
95d8d2630 net/smc: calculat... |
413 |
smc->conn.tx_off = bufsize * (smc->conn.peer_rmbe_idx - 1); |
0cfdd8f92 smc: connection a... |
414 |
} |
413498440 net/smc: add SMC-... |
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
static void smcd_conn_save_peer_info(struct smc_sock *smc, struct smc_clc_msg_accept_confirm *clc) { int bufsize = smc_uncompress_bufsize(clc->dmbe_size); smc->conn.peer_rmbe_idx = clc->dmbe_idx; smc->conn.peer_token = clc->token; /* msg header takes up space in the buffer */ smc->conn.peer_rmbe_size = bufsize - sizeof(struct smcd_cdc_msg); atomic_set(&smc->conn.peer_rmbe_space, smc->conn.peer_rmbe_size); smc->conn.tx_off = bufsize * smc->conn.peer_rmbe_idx; } static void smc_conn_save_peer_info(struct smc_sock *smc, struct smc_clc_msg_accept_confirm *clc) { if (smc->conn.lgr->is_smcd) smcd_conn_save_peer_info(smc, clc); else smcr_conn_save_peer_info(smc, clc); } |
0cfdd8f92 smc: connection a... |
436 437 438 439 440 441 442 443 444 |
static void smc_link_save_peer_info(struct smc_link *link, struct smc_clc_msg_accept_confirm *clc) { link->peer_qpn = ntoh24(clc->qpn); memcpy(link->peer_gid, clc->lcl.gid, SMC_GID_SIZE); memcpy(link->peer_mac, clc->lcl.mac, sizeof(link->peer_mac)); link->peer_psn = ntoh24(clc->psn); link->peer_mtu = clc->qp_mtu; } |
07603b230 net/smc: propagat... |
445 446 447 448 449 450 |
static void smc_switch_to_fallback(struct smc_sock *smc) { smc->use_fallback = true; if (smc->sk.sk_socket && smc->sk.sk_socket->file) { smc->clcsock->file = smc->sk.sk_socket->file; smc->clcsock->file->private_data = smc->clcsock; |
67f562e3e net/smc: transfer... |
451 452 |
smc->clcsock->wq.fasync_list = smc->sk.sk_socket->wq.fasync_list; |
07603b230 net/smc: propagat... |
453 454 |
} } |
3b2dec260 net/smc: restruct... |
455 |
/* fall back during connect */ |
603cc1498 net/smc: provide ... |
456 |
static int smc_connect_fallback(struct smc_sock *smc, int reason_code) |
a046d57da smc: CLC handshak... |
457 |
{ |
07603b230 net/smc: propagat... |
458 |
smc_switch_to_fallback(smc); |
603cc1498 net/smc: provide ... |
459 |
smc->fallback_rsn = reason_code; |
3b2dec260 net/smc: restruct... |
460 |
smc_copy_sock_settings_to_clc(smc); |
50717a37d net/smc: nonblock... |
461 |
smc->connect_nonblock = 0; |
3b2dec260 net/smc: restruct... |
462 463 464 465 |
if (smc->sk.sk_state == SMC_INIT) smc->sk.sk_state = SMC_ACTIVE; return 0; } |
51f1de79a net/smc: replace ... |
466 |
|
3b2dec260 net/smc: restruct... |
467 468 469 470 |
/* decline and fall back during connect */ static int smc_connect_decline_fallback(struct smc_sock *smc, int reason_code) { int rc; |
ee9dfbef0 net/smc: handle s... |
471 |
|
e1bbdd570 net/smc: reduce s... |
472 473 474 |
if (reason_code < 0) { /* error, fallback is not possible */ if (smc->sk.sk_state == SMC_INIT) sock_put(&smc->sk); /* passive closing */ |
3b2dec260 net/smc: restruct... |
475 |
return reason_code; |
e1bbdd570 net/smc: reduce s... |
476 |
} |
603cc1498 net/smc: provide ... |
477 |
if (reason_code != SMC_CLC_DECL_PEERDECL) { |
3b2dec260 net/smc: restruct... |
478 |
rc = smc_clc_send_decline(smc, reason_code); |
e1bbdd570 net/smc: reduce s... |
479 480 481 |
if (rc < 0) { if (smc->sk.sk_state == SMC_INIT) sock_put(&smc->sk); /* passive closing */ |
3b2dec260 net/smc: restruct... |
482 |
return rc; |
e1bbdd570 net/smc: reduce s... |
483 |
} |
c5c1cc9c5 smc: add SMC rend... |
484 |
} |
603cc1498 net/smc: provide ... |
485 |
return smc_connect_fallback(smc, reason_code); |
3b2dec260 net/smc: restruct... |
486 |
} |
c5c1cc9c5 smc: add SMC rend... |
487 |
|
3b2dec260 net/smc: restruct... |
488 489 490 491 |
/* abort connecting */ static int smc_connect_abort(struct smc_sock *smc, int reason_code, int local_contact) { |
51e3dfa89 net/smc: fix clea... |
492 |
bool is_smcd = smc->conn.lgr->is_smcd; |
3b2dec260 net/smc: restruct... |
493 |
if (local_contact == SMC_FIRST_CONTACT) |
51e3dfa89 net/smc: fix clea... |
494 495 496 497 |
smc_lgr_cleanup_early(&smc->conn); else smc_conn_free(&smc->conn); if (is_smcd) |
72a36a8ae net/smc: use clie... |
498 499 500 501 |
/* there is only one lgr role for SMC-D; use server lock */ mutex_unlock(&smc_server_lgr_pending); else mutex_unlock(&smc_client_lgr_pending); |
50717a37d net/smc: nonblock... |
502 |
smc->connect_nonblock = 0; |
3b2dec260 net/smc: restruct... |
503 504 505 506 507 |
return reason_code; } /* check if there is a rdma device available for this connection. */ /* called for connect and listen */ |
228bae05b net/smc: code cle... |
508 |
static int smc_find_rdma_device(struct smc_sock *smc, struct smc_init_info *ini) |
3b2dec260 net/smc: restruct... |
509 |
{ |
a046d57da smc: CLC handshak... |
510 511 512 513 |
/* PNET table look up: search active ib_device and port * within same PNETID that also contains the ethernet device * used for the internal TCP socket */ |
bc36d2fc9 net/smc: consolid... |
514 |
smc_pnet_find_roce_resource(smc->clcsock->sk, ini); |
9aa68d298 net/smc: improve ... |
515 516 |
if (!ini->ib_dev) return SMC_CLC_DECL_NOSMCRDEV; |
bc36d2fc9 net/smc: consolid... |
517 |
return 0; |
3b2dec260 net/smc: restruct... |
518 |
} |
413498440 net/smc: add SMC-... |
519 520 |
/* check if there is an ISM device available for this connection. */ /* called for connect and listen */ |
228bae05b net/smc: code cle... |
521 |
static int smc_find_ism_device(struct smc_sock *smc, struct smc_init_info *ini) |
413498440 net/smc: add SMC-... |
522 523 |
{ /* Find ISM device with same PNETID as connecting interface */ |
bc36d2fc9 net/smc: consolid... |
524 525 |
smc_pnet_find_ism_resource(smc->clcsock->sk, ini); if (!ini->ism_dev) |
9aa68d298 net/smc: improve ... |
526 |
return SMC_CLC_DECL_NOSMCDDEV; |
413498440 net/smc: add SMC-... |
527 528 529 530 531 |
return 0; } /* Check for VLAN ID and register it on ISM device just for CLC handshake */ static int smc_connect_ism_vlan_setup(struct smc_sock *smc, |
bc36d2fc9 net/smc: consolid... |
532 |
struct smc_init_info *ini) |
413498440 net/smc: add SMC-... |
533 |
{ |
bc36d2fc9 net/smc: consolid... |
534 |
if (ini->vlan_id && smc_ism_get_vlan(ini->ism_dev, ini->vlan_id)) |
7a62725a5 net/smc: improve ... |
535 |
return SMC_CLC_DECL_ISMVLANERR; |
413498440 net/smc: add SMC-... |
536 537 538 539 540 541 542 |
return 0; } /* cleanup temporary VLAN ID registration used for CLC handshake. If ISM is * used, the VLAN ID will be registered again during the connection setup. */ static int smc_connect_ism_vlan_cleanup(struct smc_sock *smc, bool is_smcd, |
bc36d2fc9 net/smc: consolid... |
543 |
struct smc_init_info *ini) |
413498440 net/smc: add SMC-... |
544 545 546 |
{ if (!is_smcd) return 0; |
bc36d2fc9 net/smc: consolid... |
547 |
if (ini->vlan_id && smc_ism_put_vlan(ini->ism_dev, ini->vlan_id)) |
413498440 net/smc: add SMC-... |
548 549 550 |
return SMC_CLC_DECL_CNFERR; return 0; } |
3b2dec260 net/smc: restruct... |
551 |
/* CLC handshake during connect */ |
c758dfddc net/smc: add SMC-... |
552 |
static int smc_connect_clc(struct smc_sock *smc, int smc_type, |
3b2dec260 net/smc: restruct... |
553 |
struct smc_clc_msg_accept_confirm *aclc, |
bc36d2fc9 net/smc: consolid... |
554 |
struct smc_init_info *ini) |
3b2dec260 net/smc: restruct... |
555 556 |
{ int rc = 0; |
a046d57da smc: CLC handshak... |
557 558 |
/* do inband token exchange */ |
bc36d2fc9 net/smc: consolid... |
559 |
rc = smc_clc_send_proposal(smc, smc_type, ini); |
3b2dec260 net/smc: restruct... |
560 561 |
if (rc) return rc; |
a046d57da smc: CLC handshak... |
562 |
/* receive SMC Accept CLC message */ |
2b59f58e3 net/smc: short wa... |
563 564 |
return smc_clc_wait_msg(smc, aclc, sizeof(*aclc), SMC_CLC_ACCEPT, CLC_WAIT_TIME); |
3b2dec260 net/smc: restruct... |
565 566 567 568 569 |
} /* setup for RDMA connection of client */ static int smc_connect_rdma(struct smc_sock *smc, struct smc_clc_msg_accept_confirm *aclc, |
bc36d2fc9 net/smc: consolid... |
570 |
struct smc_init_info *ini) |
3b2dec260 net/smc: restruct... |
571 |
{ |
3b2dec260 net/smc: restruct... |
572 573 |
struct smc_link *link; int reason_code = 0; |
a046d57da smc: CLC handshak... |
574 |
|
bc36d2fc9 net/smc: consolid... |
575 576 577 578 |
ini->is_smcd = false; ini->ib_lcl = &aclc->lcl; ini->ib_clcqpn = ntoh24(aclc->qpn); ini->srv_first_contact = aclc->hdr.flag; |
72a36a8ae net/smc: use clie... |
579 |
mutex_lock(&smc_client_lgr_pending); |
7a62725a5 net/smc: improve ... |
580 581 |
reason_code = smc_conn_create(smc, ini); if (reason_code) { |
72a36a8ae net/smc: use clie... |
582 583 |
mutex_unlock(&smc_client_lgr_pending); return reason_code; |
0cfdd8f92 smc: connection a... |
584 585 |
} link = &smc->conn.lgr->lnk[SMC_SINGLE_LINK]; |
a046d57da smc: CLC handshak... |
586 |
|
3b2dec260 net/smc: restruct... |
587 |
smc_conn_save_peer_info(smc, aclc); |
cd6851f30 smc: remote memor... |
588 |
|
3e034725c net/smc: common f... |
589 |
/* create send buffer and rmb */ |
c6ba7c9ba net/smc: add base... |
590 |
if (smc_buf_create(smc, false)) |
7a62725a5 net/smc: improve ... |
591 592 |
return smc_connect_abort(smc, SMC_CLC_DECL_MEM, ini->cln_first_contact); |
cd6851f30 smc: remote memor... |
593 |
|
7a62725a5 net/smc: improve ... |
594 |
if (ini->cln_first_contact == SMC_FIRST_CONTACT) |
3b2dec260 net/smc: restruct... |
595 |
smc_link_save_peer_info(link, aclc); |
bd4ad5771 smc: initialize I... |
596 |
|
3b2dec260 net/smc: restruct... |
597 |
if (smc_rmb_rtoken_handling(&smc->conn, aclc)) |
603cc1498 net/smc: provide ... |
598 |
return smc_connect_abort(smc, SMC_CLC_DECL_ERR_RTOK, |
7a62725a5 net/smc: improve ... |
599 |
ini->cln_first_contact); |
bd4ad5771 smc: initialize I... |
600 |
|
46c28dbd4 net/smc: no socke... |
601 602 |
smc_close_init(smc); smc_rx_init(smc); |
7a62725a5 net/smc: improve ... |
603 |
if (ini->cln_first_contact == SMC_FIRST_CONTACT) { |
3b2dec260 net/smc: restruct... |
604 |
if (smc_ib_ready_link(link)) |
603cc1498 net/smc: provide ... |
605 |
return smc_connect_abort(smc, SMC_CLC_DECL_ERR_RDYLNK, |
7a62725a5 net/smc: improve ... |
606 |
ini->cln_first_contact); |
652a1e41e net/smc: register... |
607 |
} else { |
c7674c001 net/smc: unregist... |
608 |
if (smc_reg_rmb(link, smc->conn.rmb_desc, true)) |
603cc1498 net/smc: provide ... |
609 |
return smc_connect_abort(smc, SMC_CLC_DECL_ERR_REGRMB, |
7a62725a5 net/smc: improve ... |
610 |
ini->cln_first_contact); |
bd4ad5771 smc: initialize I... |
611 |
} |
10428dd83 net/smc: synchron... |
612 |
smc_rmb_sync_sg_for_device(&smc->conn); |
a046d57da smc: CLC handshak... |
613 |
|
3b2dec260 net/smc: restruct... |
614 615 |
reason_code = smc_clc_send_confirm(smc); if (reason_code) |
7a62725a5 net/smc: improve ... |
616 617 |
return smc_connect_abort(smc, reason_code, ini->cln_first_contact); |
3b2dec260 net/smc: restruct... |
618 619 |
smc_tx_init(smc); |
a046d57da smc: CLC handshak... |
620 |
|
7a62725a5 net/smc: improve ... |
621 |
if (ini->cln_first_contact == SMC_FIRST_CONTACT) { |
9bf9abead smc: link layer c... |
622 |
/* QP confirmation over RoCE fabric */ |
0f6271264 net/smc: cleanup ... |
623 |
reason_code = smc_clnt_conf_first_link(smc); |
3b2dec260 net/smc: restruct... |
624 625 |
if (reason_code) return smc_connect_abort(smc, reason_code, |
7a62725a5 net/smc: improve ... |
626 |
ini->cln_first_contact); |
9bf9abead smc: link layer c... |
627 |
} |
72a36a8ae net/smc: use clie... |
628 |
mutex_unlock(&smc_client_lgr_pending); |
e6727f390 smc: send data (t... |
629 |
|
a046d57da smc: CLC handshak... |
630 |
smc_copy_sock_settings_to_clc(smc); |
50717a37d net/smc: nonblock... |
631 |
smc->connect_nonblock = 0; |
b38d73247 smc: socket closi... |
632 633 |
if (smc->sk.sk_state == SMC_INIT) smc->sk.sk_state = SMC_ACTIVE; |
a046d57da smc: CLC handshak... |
634 |
|
3b2dec260 net/smc: restruct... |
635 636 |
return 0; } |
a046d57da smc: CLC handshak... |
637 |
|
413498440 net/smc: add SMC-... |
638 639 640 |
/* setup for ISM connection of client */ static int smc_connect_ism(struct smc_sock *smc, struct smc_clc_msg_accept_confirm *aclc, |
bc36d2fc9 net/smc: consolid... |
641 |
struct smc_init_info *ini) |
413498440 net/smc: add SMC-... |
642 |
{ |
413498440 net/smc: add SMC-... |
643 |
int rc = 0; |
bc36d2fc9 net/smc: consolid... |
644 645 646 |
ini->is_smcd = true; ini->ism_gid = aclc->gid; ini->srv_first_contact = aclc->hdr.flag; |
72a36a8ae net/smc: use clie... |
647 648 |
/* there is only one lgr role for SMC-D; use server lock */ mutex_lock(&smc_server_lgr_pending); |
7a62725a5 net/smc: improve ... |
649 650 |
rc = smc_conn_create(smc, ini); if (rc) { |
72a36a8ae net/smc: use clie... |
651 |
mutex_unlock(&smc_server_lgr_pending); |
7a62725a5 net/smc: improve ... |
652 |
return rc; |
72a36a8ae net/smc: use clie... |
653 |
} |
413498440 net/smc: add SMC-... |
654 655 656 |
/* Create send and receive buffers */ if (smc_buf_create(smc, true)) |
7a62725a5 net/smc: improve ... |
657 658 |
return smc_connect_abort(smc, SMC_CLC_DECL_MEM, ini->cln_first_contact); |
413498440 net/smc: add SMC-... |
659 660 661 662 663 664 665 666 |
smc_conn_save_peer_info(smc, aclc); smc_close_init(smc); smc_rx_init(smc); smc_tx_init(smc); rc = smc_clc_send_confirm(smc); if (rc) |
7a62725a5 net/smc: improve ... |
667 |
return smc_connect_abort(smc, rc, ini->cln_first_contact); |
72a36a8ae net/smc: use clie... |
668 |
mutex_unlock(&smc_server_lgr_pending); |
413498440 net/smc: add SMC-... |
669 670 |
smc_copy_sock_settings_to_clc(smc); |
50717a37d net/smc: nonblock... |
671 |
smc->connect_nonblock = 0; |
413498440 net/smc: add SMC-... |
672 673 674 675 676 |
if (smc->sk.sk_state == SMC_INIT) smc->sk.sk_state = SMC_ACTIVE; return 0; } |
3b2dec260 net/smc: restruct... |
677 678 679 |
/* perform steps before actually connecting */ static int __smc_connect(struct smc_sock *smc) { |
413498440 net/smc: add SMC-... |
680 |
bool ism_supported = false, rdma_supported = false; |
3b2dec260 net/smc: restruct... |
681 |
struct smc_clc_msg_accept_confirm aclc; |
bc36d2fc9 net/smc: consolid... |
682 |
struct smc_init_info ini = {0}; |
413498440 net/smc: add SMC-... |
683 |
int smc_type; |
3b2dec260 net/smc: restruct... |
684 |
int rc = 0; |
a046d57da smc: CLC handshak... |
685 |
|
3b2dec260 net/smc: restruct... |
686 |
if (smc->use_fallback) |
603cc1498 net/smc: provide ... |
687 |
return smc_connect_fallback(smc, smc->fallback_rsn); |
3b2dec260 net/smc: restruct... |
688 689 690 |
/* if peer has not signalled SMC-capability, fall back */ if (!tcp_sk(smc->clcsock->sk)->syn_smc) |
603cc1498 net/smc: provide ... |
691 |
return smc_connect_fallback(smc, SMC_CLC_DECL_PEERNOSMC); |
3b2dec260 net/smc: restruct... |
692 693 694 695 |
/* IPSec connections opt out of SMC-R optimizations */ if (using_ipsec(smc)) return smc_connect_decline_fallback(smc, SMC_CLC_DECL_IPSEC); |
fba7e8ef5 net/smc: cleanup ... |
696 |
/* get vlan id from IP device */ |
bc36d2fc9 net/smc: consolid... |
697 |
if (smc_vlan_by_tcpsk(smc->clcsock, &ini)) |
fba7e8ef5 net/smc: cleanup ... |
698 699 |
return smc_connect_decline_fallback(smc, SMC_CLC_DECL_GETVLANERR); |
413498440 net/smc: add SMC-... |
700 701 |
/* check if there is an ism device available */ |
228bae05b net/smc: code cle... |
702 |
if (!smc_find_ism_device(smc, &ini) && |
bc36d2fc9 net/smc: consolid... |
703 |
!smc_connect_ism_vlan_setup(smc, &ini)) { |
413498440 net/smc: add SMC-... |
704 705 706 707 708 709 |
/* ISM is supported for this connection */ ism_supported = true; smc_type = SMC_TYPE_D; } /* check if there is a rdma device available */ |
228bae05b net/smc: code cle... |
710 |
if (!smc_find_rdma_device(smc, &ini)) { |
413498440 net/smc: add SMC-... |
711 712 713 714 715 716 717 718 719 720 |
/* RDMA is supported for this connection */ rdma_supported = true; if (ism_supported) smc_type = SMC_TYPE_B; /* both */ else smc_type = SMC_TYPE_R; /* only RDMA */ } /* if neither ISM nor RDMA are supported, fallback */ if (!rdma_supported && !ism_supported) |
603cc1498 net/smc: provide ... |
721 |
return smc_connect_decline_fallback(smc, SMC_CLC_DECL_NOSMCDEV); |
3b2dec260 net/smc: restruct... |
722 723 |
/* perform CLC handshake */ |
bc36d2fc9 net/smc: consolid... |
724 |
rc = smc_connect_clc(smc, smc_type, &aclc, &ini); |
413498440 net/smc: add SMC-... |
725 |
if (rc) { |
bc36d2fc9 net/smc: consolid... |
726 |
smc_connect_ism_vlan_cleanup(smc, ism_supported, &ini); |
3b2dec260 net/smc: restruct... |
727 |
return smc_connect_decline_fallback(smc, rc); |
413498440 net/smc: add SMC-... |
728 |
} |
3b2dec260 net/smc: restruct... |
729 |
|
413498440 net/smc: add SMC-... |
730 731 |
/* depending on previous steps, connect using rdma or ism */ if (rdma_supported && aclc.hdr.path == SMC_TYPE_R) |
bc36d2fc9 net/smc: consolid... |
732 |
rc = smc_connect_rdma(smc, &aclc, &ini); |
413498440 net/smc: add SMC-... |
733 |
else if (ism_supported && aclc.hdr.path == SMC_TYPE_D) |
bc36d2fc9 net/smc: consolid... |
734 |
rc = smc_connect_ism(smc, &aclc, &ini); |
413498440 net/smc: add SMC-... |
735 |
else |
603cc1498 net/smc: provide ... |
736 |
rc = SMC_CLC_DECL_MODEUNSUPP; |
413498440 net/smc: add SMC-... |
737 |
if (rc) { |
bc36d2fc9 net/smc: consolid... |
738 |
smc_connect_ism_vlan_cleanup(smc, ism_supported, &ini); |
3b2dec260 net/smc: restruct... |
739 |
return smc_connect_decline_fallback(smc, rc); |
413498440 net/smc: add SMC-... |
740 |
} |
3b2dec260 net/smc: restruct... |
741 |
|
bc36d2fc9 net/smc: consolid... |
742 |
smc_connect_ism_vlan_cleanup(smc, ism_supported, &ini); |
3b2dec260 net/smc: restruct... |
743 |
return 0; |
a046d57da smc: CLC handshak... |
744 |
} |
24ac3a08e net/smc: rebuild ... |
745 746 747 748 |
static void smc_connect_work(struct work_struct *work) { struct smc_sock *smc = container_of(work, struct smc_sock, connect_work); |
50717a37d net/smc: nonblock... |
749 750 |
long timeo = smc->sk.sk_sndtimeo; int rc = 0; |
24ac3a08e net/smc: rebuild ... |
751 |
|
50717a37d net/smc: nonblock... |
752 753 754 |
if (!timeo) timeo = MAX_SCHEDULE_TIMEOUT; lock_sock(smc->clcsock->sk); |
24ac3a08e net/smc: rebuild ... |
755 756 |
if (smc->clcsock->sk->sk_err) { smc->sk.sk_err = smc->clcsock->sk->sk_err; |
50717a37d net/smc: nonblock... |
757 758 759 760 761 762 763 |
} else if ((1 << smc->clcsock->sk->sk_state) & (TCPF_SYN_SENT | TCP_SYN_RECV)) { rc = sk_stream_wait_connect(smc->clcsock->sk, &timeo); if ((rc == -EPIPE) && ((1 << smc->clcsock->sk->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))) rc = 0; |
24ac3a08e net/smc: rebuild ... |
764 |
} |
50717a37d net/smc: nonblock... |
765 766 767 768 769 770 771 772 |
release_sock(smc->clcsock->sk); lock_sock(&smc->sk); if (rc != 0 || smc->sk.sk_err) { smc->sk.sk_state = SMC_CLOSED; if (rc == -EPIPE || rc == -EAGAIN) smc->sk.sk_err = EPIPE; else if (signal_pending(current)) smc->sk.sk_err = -sock_intr_errno(timeo); |
6d6dd528d net/smc: fix refc... |
773 |
sock_put(&smc->sk); /* passive closing */ |
24ac3a08e net/smc: rebuild ... |
774 775 776 777 778 779 780 781 |
goto out; } rc = __smc_connect(smc); if (rc < 0) smc->sk.sk_err = -rc; out: |
07603b230 net/smc: propagat... |
782 783 784 785 786 787 788 789 |
if (!sock_flag(&smc->sk, SOCK_DEAD)) { if (smc->sk.sk_err) { smc->sk.sk_state_change(&smc->sk); } else { /* allow polling before and after fallback decision */ smc->clcsock->sk->sk_write_space(smc->clcsock->sk); smc->sk.sk_write_space(&smc->sk); } } |
24ac3a08e net/smc: rebuild ... |
790 791 |
release_sock(&smc->sk); } |
ac7138746 smc: establish ne... |
792 793 794 795 796 797 798 799 800 801 802 803 |
static int smc_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) { struct sock *sk = sock->sk; struct smc_sock *smc; int rc = -EINVAL; smc = smc_sk(sk); /* separate smc parameter checking to be safe */ if (alen < sizeof(addr->sa_family)) goto out_err; |
aaa4d33f6 net/smc: enable i... |
804 |
if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6) |
ac7138746 smc: establish ne... |
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 |
goto out_err; lock_sock(sk); switch (sk->sk_state) { default: goto out; case SMC_ACTIVE: rc = -EISCONN; goto out; case SMC_INIT: rc = 0; break; } smc_copy_sock_settings_to_clc(smc); |
c5c1cc9c5 smc: add SMC rend... |
820 |
tcp_sk(smc->clcsock->sk)->syn_smc = 1; |
50717a37d net/smc: nonblock... |
821 822 823 824 825 826 827 |
if (smc->connect_nonblock) { rc = -EALREADY; goto out; } rc = kernel_connect(smc->clcsock, addr, alen, flags); if (rc && rc != -EINPROGRESS) goto out; |
301428ea3 net/smc: fix refc... |
828 829 |
sock_hold(&smc->sk); /* sock put in passive closing */ |
86434744f net/smc: add fall... |
830 831 |
if (smc->use_fallback) goto out; |
24ac3a08e net/smc: rebuild ... |
832 |
if (flags & O_NONBLOCK) { |
50717a37d net/smc: nonblock... |
833 834 |
if (schedule_work(&smc->connect_work)) smc->connect_nonblock = 1; |
24ac3a08e net/smc: rebuild ... |
835 836 |
rc = -EINPROGRESS; } else { |
24ac3a08e net/smc: rebuild ... |
837 838 839 840 841 842 |
rc = __smc_connect(smc); if (rc < 0) goto out; else rc = 0; /* success cases including fallback */ } |
ac7138746 smc: establish ne... |
843 844 845 846 847 848 849 850 851 |
out: release_sock(sk); out_err: return rc; } static int smc_clcsock_accept(struct smc_sock *lsmc, struct smc_sock **new_smc) { |
3163c5071 net/smc: use loca... |
852 853 |
struct socket *new_clcsock = NULL; struct sock *lsk = &lsmc->sk; |
ac7138746 smc: establish ne... |
854 |
struct sock *new_sk; |
78abe3d0d net/smc: fix TCP ... |
855 |
int rc = -EINVAL; |
ac7138746 smc: establish ne... |
856 |
|
3163c5071 net/smc: use loca... |
857 |
release_sock(lsk); |
aaa4d33f6 net/smc: enable i... |
858 |
new_sk = smc_sock_alloc(sock_net(lsk), NULL, lsk->sk_protocol); |
ac7138746 smc: establish ne... |
859 860 |
if (!new_sk) { rc = -ENOMEM; |
3163c5071 net/smc: use loca... |
861 |
lsk->sk_err = ENOMEM; |
ac7138746 smc: establish ne... |
862 |
*new_smc = NULL; |
3163c5071 net/smc: use loca... |
863 |
lock_sock(lsk); |
ac7138746 smc: establish ne... |
864 865 866 |
goto out; } *new_smc = smc_sk(new_sk); |
78abe3d0d net/smc: fix TCP ... |
867 868 869 870 |
mutex_lock(&lsmc->clcsock_release_lock); if (lsmc->clcsock) rc = kernel_accept(lsmc->clcsock, &new_clcsock, 0); mutex_unlock(&lsmc->clcsock_release_lock); |
3163c5071 net/smc: use loca... |
871 |
lock_sock(lsk); |
35a6b1784 net/smc: simplify... |
872 |
if (rc < 0) |
3163c5071 net/smc: use loca... |
873 |
lsk->sk_err = -rc; |
35a6b1784 net/smc: simplify... |
874 |
if (rc < 0 || lsk->sk_state == SMC_CLOSED) { |
f61bca58f net/smc: move unh... |
875 |
new_sk->sk_prot->unhash(new_sk); |
a046d57da smc: CLC handshak... |
876 877 878 879 |
if (new_clcsock) sock_release(new_clcsock); new_sk->sk_state = SMC_CLOSED; sock_set_flag(new_sk, SOCK_DEAD); |
51f1de79a net/smc: replace ... |
880 |
sock_put(new_sk); /* final */ |
ac7138746 smc: establish ne... |
881 882 883 884 885 886 887 888 |
*new_smc = NULL; goto out; } (*new_smc)->clcsock = new_clcsock; out: return rc; } |
a046d57da smc: CLC handshak... |
889 890 891 892 893 894 |
/* add a just created sock to the accept queue of the listen sock as * candidate for a following socket accept call from user space */ static void smc_accept_enqueue(struct sock *parent, struct sock *sk) { struct smc_sock *par = smc_sk(parent); |
51f1de79a net/smc: replace ... |
895 |
sock_hold(sk); /* sock_put in smc_accept_unlink () */ |
a046d57da smc: CLC handshak... |
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 |
spin_lock(&par->accept_q_lock); list_add_tail(&smc_sk(sk)->accept_q, &par->accept_q); spin_unlock(&par->accept_q_lock); sk_acceptq_added(parent); } /* remove a socket from the accept queue of its parental listening socket */ static void smc_accept_unlink(struct sock *sk) { struct smc_sock *par = smc_sk(sk)->listen_smc; spin_lock(&par->accept_q_lock); list_del_init(&smc_sk(sk)->accept_q); spin_unlock(&par->accept_q_lock); sk_acceptq_removed(&smc_sk(sk)->listen_smc->sk); |
51f1de79a net/smc: replace ... |
911 |
sock_put(sk); /* sock_hold in smc_accept_enqueue */ |
a046d57da smc: CLC handshak... |
912 913 914 915 916 |
} /* remove a sock from the accept queue to bind it to a new socket created * for a socket accept call from user space */ |
b38d73247 smc: socket closi... |
917 918 |
struct sock *smc_accept_dequeue(struct sock *parent, struct socket *new_sock) |
a046d57da smc: CLC handshak... |
919 920 921 922 923 924 925 926 927 |
{ struct smc_sock *isk, *n; struct sock *new_sk; list_for_each_entry_safe(isk, n, &smc_sk(parent)->accept_q, accept_q) { new_sk = (struct sock *)isk; smc_accept_unlink(new_sk); if (new_sk->sk_state == SMC_CLOSED) { |
f61bca58f net/smc: move unh... |
928 |
new_sk->sk_prot->unhash(new_sk); |
127f49705 net/smc: release ... |
929 930 931 932 |
if (isk->clcsock) { sock_release(isk->clcsock); isk->clcsock = NULL; } |
51f1de79a net/smc: replace ... |
933 |
sock_put(new_sk); /* final */ |
a046d57da smc: CLC handshak... |
934 935 |
continue; } |
07603b230 net/smc: propagat... |
936 |
if (new_sock) { |
a046d57da smc: CLC handshak... |
937 |
sock_graft(new_sk, new_sock); |
07603b230 net/smc: propagat... |
938 939 940 941 942 |
if (isk->use_fallback) { smc_sk(new_sk)->clcsock->file = new_sock->file; isk->clcsock->file->private_data = isk->clcsock; } } |
a046d57da smc: CLC handshak... |
943 944 945 946 947 948 |
return new_sk; } return NULL; } /* clean up for a created but never accepted sock */ |
b38d73247 smc: socket closi... |
949 |
void smc_close_non_accepted(struct sock *sk) |
a046d57da smc: CLC handshak... |
950 951 |
{ struct smc_sock *smc = smc_sk(sk); |
81cf4f470 net/smc: remove c... |
952 |
sock_hold(sk); /* sock_put below */ |
b38d73247 smc: socket closi... |
953 954 955 956 |
lock_sock(sk); if (!sk->sk_lingertime) /* wait for peer closing */ sk->sk_lingertime = SMC_MAX_STREAM_WAIT_TIMEOUT; |
39f41f367 net/smc: common r... |
957 |
__smc_release(smc); |
b38d73247 smc: socket closi... |
958 |
release_sock(sk); |
81cf4f470 net/smc: remove c... |
959 |
sock_put(sk); /* sock_hold above */ |
51f1de79a net/smc: replace ... |
960 |
sock_put(sk); /* final sock_put */ |
a046d57da smc: CLC handshak... |
961 |
} |
9bf9abead smc: link layer c... |
962 963 |
static int smc_serv_conf_first_link(struct smc_sock *smc) { |
877ae5be4 net/smc: periodic... |
964 |
struct net *net = sock_net(smc->clcsock->sk); |
9bf9abead smc: link layer c... |
965 966 967 968 969 970 |
struct smc_link_group *lgr = smc->conn.lgr; struct smc_link *link; int rest; int rc; link = &lgr->lnk[SMC_SINGLE_LINK]; |
652a1e41e net/smc: register... |
971 |
|
44aa81ce9 net/smc: register... |
972 |
if (smc_reg_rmb(link, smc->conn.rmb_desc, false)) |
603cc1498 net/smc: provide ... |
973 |
return SMC_CLC_DECL_ERR_REGRMB; |
652a1e41e net/smc: register... |
974 |
|
9bf9abead smc: link layer c... |
975 |
/* send CONFIRM LINK request to client over the RoCE fabric */ |
947541f36 net/smc: fewer pa... |
976 |
rc = smc_llc_send_confirm_link(link, SMC_LLC_REQ); |
9bf9abead smc: link layer c... |
977 |
if (rc < 0) |
603cc1498 net/smc: provide ... |
978 |
return SMC_CLC_DECL_TIMEOUT_CL; |
9bf9abead smc: link layer c... |
979 980 981 982 983 984 985 986 987 |
/* receive CONFIRM LINK response from client over the RoCE fabric */ rest = wait_for_completion_interruptible_timeout( &link->llc_confirm_resp, SMC_LLC_WAIT_FIRST_TIME); if (rest <= 0) { struct smc_clc_msg_decline dclc; rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), |
2b59f58e3 net/smc: short wa... |
988 |
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT); |
9ed28556a net/smc: allow fa... |
989 |
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_CL : rc; |
9bf9abead smc: link layer c... |
990 |
} |
75d320d61 net/smc: do not a... |
991 992 |
if (link->llc_confirm_resp_rc) return SMC_CLC_DECL_RMBE_EC; |
52bedf37b net/smc: process ... |
993 994 995 |
/* send ADD LINK request to client over the RoCE fabric */ rc = smc_llc_send_add_link(link, link->smcibdev->mac[link->ibport - 1], |
7005ada68 net/smc: use corr... |
996 |
link->gid, SMC_LLC_REQ); |
52bedf37b net/smc: process ... |
997 |
if (rc < 0) |
603cc1498 net/smc: provide ... |
998 |
return SMC_CLC_DECL_TIMEOUT_AL; |
52bedf37b net/smc: process ... |
999 1000 1001 1002 1003 1004 1005 1006 |
/* receive ADD LINK response from client over the RoCE fabric */ rest = wait_for_completion_interruptible_timeout(&link->llc_add_resp, SMC_LLC_WAIT_TIME); if (rest <= 0) { struct smc_clc_msg_decline dclc; rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc), |
2b59f58e3 net/smc: short wa... |
1007 |
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT); |
9ed28556a net/smc: allow fa... |
1008 |
return rc == -EAGAIN ? SMC_CLC_DECL_TIMEOUT_AL : rc; |
52bedf37b net/smc: process ... |
1009 |
} |
877ae5be4 net/smc: periodic... |
1010 |
smc_llc_link_active(link, net->ipv4.sysctl_tcp_keepalive_time); |
52bedf37b net/smc: process ... |
1011 |
|
75d320d61 net/smc: do not a... |
1012 |
return 0; |
9bf9abead smc: link layer c... |
1013 |
} |
3b2dec260 net/smc: restruct... |
1014 1015 |
/* listen worker: finish */ static void smc_listen_out(struct smc_sock *new_smc) |
a046d57da smc: CLC handshak... |
1016 |
{ |
a046d57da smc: CLC handshak... |
1017 |
struct smc_sock *lsmc = new_smc->listen_smc; |
a046d57da smc: CLC handshak... |
1018 |
struct sock *newsmcsk = &new_smc->sk; |
a046d57da smc: CLC handshak... |
1019 |
|
3b2dec260 net/smc: restruct... |
1020 |
if (lsmc->sk.sk_state == SMC_LISTEN) { |
fd57770dd net/smc: wait for... |
1021 |
lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING); |
3b2dec260 net/smc: restruct... |
1022 |
smc_accept_enqueue(&lsmc->sk, newsmcsk); |
fd57770dd net/smc: wait for... |
1023 |
release_sock(&lsmc->sk); |
3b2dec260 net/smc: restruct... |
1024 1025 |
} else { /* no longer listening */ smc_close_non_accepted(newsmcsk); |
c5c1cc9c5 smc: add SMC rend... |
1026 |
} |
3b2dec260 net/smc: restruct... |
1027 1028 1029 1030 |
/* Wake up accept */ lsmc->sk.sk_data_ready(&lsmc->sk); sock_put(&lsmc->sk); /* sock_hold in smc_tcp_listen_work */ } |
a046d57da smc: CLC handshak... |
1031 |
|
3b2dec260 net/smc: restruct... |
1032 1033 1034 1035 |
/* listen worker: finish in state connected */ static void smc_listen_out_connected(struct smc_sock *new_smc) { struct sock *newsmcsk = &new_smc->sk; |
a046d57da smc: CLC handshak... |
1036 |
|
3b2dec260 net/smc: restruct... |
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 |
sk_refcnt_debug_inc(newsmcsk); if (newsmcsk->sk_state == SMC_INIT) newsmcsk->sk_state = SMC_ACTIVE; smc_listen_out(new_smc); } /* listen worker: finish in error state */ static void smc_listen_out_err(struct smc_sock *new_smc) { struct sock *newsmcsk = &new_smc->sk; if (newsmcsk->sk_state == SMC_INIT) sock_put(&new_smc->sk); /* passive closing */ newsmcsk->sk_state = SMC_CLOSED; |
3b2dec260 net/smc: restruct... |
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 |
smc_listen_out(new_smc); } /* listen worker: decline and fall back if possible */ static void smc_listen_decline(struct smc_sock *new_smc, int reason_code, int local_contact) { /* RDMA setup failed, switch back to TCP */ if (local_contact == SMC_FIRST_CONTACT) |
51e3dfa89 net/smc: fix clea... |
1062 1063 1064 |
smc_lgr_cleanup_early(&new_smc->conn); else smc_conn_free(&new_smc->conn); |
3b2dec260 net/smc: restruct... |
1065 1066 1067 1068 |
if (reason_code < 0) { /* error, no fallback possible */ smc_listen_out_err(new_smc); return; } |
07603b230 net/smc: propagat... |
1069 |
smc_switch_to_fallback(new_smc); |
603cc1498 net/smc: provide ... |
1070 1071 |
new_smc->fallback_rsn = reason_code; if (reason_code && reason_code != SMC_CLC_DECL_PEERDECL) { |
3b2dec260 net/smc: restruct... |
1072 1073 1074 1075 |
if (smc_clc_send_decline(new_smc, reason_code) < 0) { smc_listen_out_err(new_smc); return; } |
a046d57da smc: CLC handshak... |
1076 |
} |
3b2dec260 net/smc: restruct... |
1077 1078 1079 1080 |
smc_listen_out_connected(new_smc); } /* listen worker: check prefixes */ |
598866974 net/smc: check fo... |
1081 |
static int smc_listen_prfx_check(struct smc_sock *new_smc, |
3b2dec260 net/smc: restruct... |
1082 1083 1084 1085 |
struct smc_clc_msg_proposal *pclc) { struct smc_clc_msg_proposal_prefix *pclc_prfx; struct socket *newclcsock = new_smc->clcsock; |
a046d57da smc: CLC handshak... |
1086 |
|
e7b7a64a8 smc: support vari... |
1087 |
pclc_prfx = smc_clc_proposal_get_prefix(pclc); |
3b2dec260 net/smc: restruct... |
1088 |
if (smc_clc_prfx_match(newclcsock, pclc_prfx)) |
598866974 net/smc: check fo... |
1089 |
return SMC_CLC_DECL_DIFFPREFIX; |
c246d942e net/smc: restruct... |
1090 |
|
3b2dec260 net/smc: restruct... |
1091 1092 |
return 0; } |
a046d57da smc: CLC handshak... |
1093 |
|
3b2dec260 net/smc: restruct... |
1094 1095 |
/* listen worker: initialize connection and buffers */ static int smc_listen_rdma_init(struct smc_sock *new_smc, |
7a62725a5 net/smc: improve ... |
1096 |
struct smc_init_info *ini) |
3b2dec260 net/smc: restruct... |
1097 |
{ |
7a62725a5 net/smc: improve ... |
1098 |
int rc; |
0cfdd8f92 smc: connection a... |
1099 |
/* allocate connection / link group */ |
7a62725a5 net/smc: improve ... |
1100 1101 1102 |
rc = smc_conn_create(new_smc, ini); if (rc) return rc; |
a046d57da smc: CLC handshak... |
1103 |
|
3e034725c net/smc: common f... |
1104 |
/* create send buffer and rmb */ |
c6ba7c9ba net/smc: add base... |
1105 |
if (smc_buf_create(new_smc, false)) |
3b2dec260 net/smc: restruct... |
1106 |
return SMC_CLC_DECL_MEM; |
a046d57da smc: CLC handshak... |
1107 |
|
3b2dec260 net/smc: restruct... |
1108 1109 |
return 0; } |
413498440 net/smc: add SMC-... |
1110 1111 1112 |
/* listen worker: initialize connection and buffers for SMC-D */ static int smc_listen_ism_init(struct smc_sock *new_smc, struct smc_clc_msg_proposal *pclc, |
7a62725a5 net/smc: improve ... |
1113 |
struct smc_init_info *ini) |
413498440 net/smc: add SMC-... |
1114 1115 |
{ struct smc_clc_msg_smcd *pclc_smcd; |
7a62725a5 net/smc: improve ... |
1116 |
int rc; |
413498440 net/smc: add SMC-... |
1117 1118 |
pclc_smcd = smc_get_clc_msg_smcd(pclc); |
bc36d2fc9 net/smc: consolid... |
1119 |
ini->ism_gid = pclc_smcd->gid; |
7a62725a5 net/smc: improve ... |
1120 1121 1122 |
rc = smc_conn_create(new_smc, ini); if (rc) return rc; |
413498440 net/smc: add SMC-... |
1123 1124 1125 1126 1127 |
/* Check if peer can be reached via ISM device */ if (smc_ism_cantalk(new_smc->conn.lgr->peer_gid, new_smc->conn.lgr->vlan_id, new_smc->conn.lgr->smcd)) { |
7a62725a5 net/smc: improve ... |
1128 |
if (ini->cln_first_contact == SMC_FIRST_CONTACT) |
51e3dfa89 net/smc: fix clea... |
1129 1130 1131 |
smc_lgr_cleanup_early(&new_smc->conn); else smc_conn_free(&new_smc->conn); |
9aa68d298 net/smc: improve ... |
1132 |
return SMC_CLC_DECL_SMCDNOTALK; |
413498440 net/smc: add SMC-... |
1133 1134 1135 1136 |
} /* Create send and receive buffers */ if (smc_buf_create(new_smc, true)) { |
7a62725a5 net/smc: improve ... |
1137 |
if (ini->cln_first_contact == SMC_FIRST_CONTACT) |
51e3dfa89 net/smc: fix clea... |
1138 1139 1140 |
smc_lgr_cleanup_early(&new_smc->conn); else smc_conn_free(&new_smc->conn); |
413498440 net/smc: add SMC-... |
1141 1142 1143 1144 1145 |
return SMC_CLC_DECL_MEM; } return 0; } |
3b2dec260 net/smc: restruct... |
1146 1147 1148 1149 |
/* listen worker: register buffers */ static int smc_listen_rdma_reg(struct smc_sock *new_smc, int local_contact) { struct smc_link *link = &new_smc->conn.lgr->lnk[SMC_SINGLE_LINK]; |
46c28dbd4 net/smc: no socke... |
1150 |
|
652a1e41e net/smc: register... |
1151 |
if (local_contact != SMC_FIRST_CONTACT) { |
c7674c001 net/smc: unregist... |
1152 1153 |
if (smc_reg_rmb(link, new_smc->conn.rmb_desc, true)) return SMC_CLC_DECL_ERR_REGRMB; |
652a1e41e net/smc: register... |
1154 |
} |
10428dd83 net/smc: synchron... |
1155 |
smc_rmb_sync_sg_for_device(&new_smc->conn); |
652a1e41e net/smc: register... |
1156 |
|
3b2dec260 net/smc: restruct... |
1157 1158 1159 1160 |
return 0; } /* listen worker: finish RDMA setup */ |
1ca52fcfa net/smc: remove d... |
1161 1162 1163 |
static int smc_listen_rdma_finish(struct smc_sock *new_smc, struct smc_clc_msg_accept_confirm *cclc, int local_contact) |
3b2dec260 net/smc: restruct... |
1164 1165 1166 |
{ struct smc_link *link = &new_smc->conn.lgr->lnk[SMC_SINGLE_LINK]; int reason_code = 0; |
a046d57da smc: CLC handshak... |
1167 |
|
0cfdd8f92 smc: connection a... |
1168 |
if (local_contact == SMC_FIRST_CONTACT) |
3b2dec260 net/smc: restruct... |
1169 |
smc_link_save_peer_info(link, cclc); |
a046d57da smc: CLC handshak... |
1170 |
|
3b2dec260 net/smc: restruct... |
1171 |
if (smc_rmb_rtoken_handling(&new_smc->conn, cclc)) { |
603cc1498 net/smc: provide ... |
1172 |
reason_code = SMC_CLC_DECL_ERR_RTOK; |
3b2dec260 net/smc: restruct... |
1173 |
goto decline; |
bd4ad5771 smc: initialize I... |
1174 |
} |
bd4ad5771 smc: initialize I... |
1175 |
if (local_contact == SMC_FIRST_CONTACT) { |
3b2dec260 net/smc: restruct... |
1176 |
if (smc_ib_ready_link(link)) { |
603cc1498 net/smc: provide ... |
1177 |
reason_code = SMC_CLC_DECL_ERR_RDYLNK; |
3b2dec260 net/smc: restruct... |
1178 |
goto decline; |
bd4ad5771 smc: initialize I... |
1179 |
} |
9bf9abead smc: link layer c... |
1180 1181 |
/* QP confirmation over RoCE fabric */ reason_code = smc_serv_conf_first_link(new_smc); |
3b2dec260 net/smc: restruct... |
1182 1183 |
if (reason_code) goto decline; |
bd4ad5771 smc: initialize I... |
1184 |
} |
1ca52fcfa net/smc: remove d... |
1185 |
return 0; |
a046d57da smc: CLC handshak... |
1186 |
|
3b2dec260 net/smc: restruct... |
1187 |
decline: |
3b2dec260 net/smc: restruct... |
1188 |
smc_listen_decline(new_smc, reason_code, local_contact); |
1ca52fcfa net/smc: remove d... |
1189 |
return reason_code; |
3b2dec260 net/smc: restruct... |
1190 |
} |
e6727f390 smc: send data (t... |
1191 |
|
3b2dec260 net/smc: restruct... |
1192 1193 1194 1195 1196 1197 1198 1199 |
/* setup for RDMA connection of server */ static void smc_listen_work(struct work_struct *work) { struct smc_sock *new_smc = container_of(work, struct smc_sock, smc_listen_work); struct socket *newclcsock = new_smc->clcsock; struct smc_clc_msg_accept_confirm cclc; struct smc_clc_msg_proposal *pclc; |
bc36d2fc9 net/smc: consolid... |
1200 |
struct smc_init_info ini = {0}; |
413498440 net/smc: add SMC-... |
1201 |
bool ism_supported = false; |
3b2dec260 net/smc: restruct... |
1202 |
u8 buf[SMC_CLC_MAX_LEN]; |
3b2dec260 net/smc: restruct... |
1203 |
int rc = 0; |
3b2dec260 net/smc: restruct... |
1204 |
|
fd57770dd net/smc: wait for... |
1205 1206 |
if (new_smc->listen_smc->sk.sk_state != SMC_LISTEN) return smc_listen_out_err(new_smc); |
3b2dec260 net/smc: restruct... |
1207 1208 1209 |
if (new_smc->use_fallback) { smc_listen_out_connected(new_smc); return; |
a046d57da smc: CLC handshak... |
1210 |
} |
a046d57da smc: CLC handshak... |
1211 |
|
3b2dec260 net/smc: restruct... |
1212 1213 |
/* check if peer is smc capable */ if (!tcp_sk(newclcsock->sk)->syn_smc) { |
07603b230 net/smc: propagat... |
1214 |
smc_switch_to_fallback(new_smc); |
603cc1498 net/smc: provide ... |
1215 |
new_smc->fallback_rsn = SMC_CLC_DECL_PEERNOSMC; |
3b2dec260 net/smc: restruct... |
1216 1217 1218 |
smc_listen_out_connected(new_smc); return; } |
a046d57da smc: CLC handshak... |
1219 |
|
3b2dec260 net/smc: restruct... |
1220 1221 1222 1223 |
/* do inband token exchange - * wait for and receive SMC Proposal CLC message */ pclc = (struct smc_clc_msg_proposal *)&buf; |
228bae05b net/smc: code cle... |
1224 1225 |
rc = smc_clc_wait_msg(new_smc, pclc, SMC_CLC_MAX_LEN, SMC_CLC_PROPOSAL, CLC_WAIT_TIME); |
9aa68d298 net/smc: improve ... |
1226 1227 |
if (rc) goto out_decl; |
a046d57da smc: CLC handshak... |
1228 |
|
3b2dec260 net/smc: restruct... |
1229 1230 |
/* IPSec connections opt out of SMC-R optimizations */ if (using_ipsec(new_smc)) { |
9aa68d298 net/smc: improve ... |
1231 1232 |
rc = SMC_CLC_DECL_IPSEC; goto out_decl; |
3b2dec260 net/smc: restruct... |
1233 |
} |
598866974 net/smc: check fo... |
1234 1235 |
/* check for matching IP prefix and subnet length */ rc = smc_listen_prfx_check(new_smc, pclc); |
9aa68d298 net/smc: improve ... |
1236 1237 |
if (rc) goto out_decl; |
598866974 net/smc: check fo... |
1238 |
|
fba7e8ef5 net/smc: cleanup ... |
1239 1240 |
/* get vlan id from IP device */ if (smc_vlan_by_tcpsk(new_smc->clcsock, &ini)) { |
9aa68d298 net/smc: improve ... |
1241 1242 |
rc = SMC_CLC_DECL_GETVLANERR; goto out_decl; |
fba7e8ef5 net/smc: cleanup ... |
1243 |
} |
72a36a8ae net/smc: use clie... |
1244 |
mutex_lock(&smc_server_lgr_pending); |
3b2dec260 net/smc: restruct... |
1245 1246 1247 |
smc_close_init(new_smc); smc_rx_init(new_smc); smc_tx_init(new_smc); |
413498440 net/smc: add SMC-... |
1248 |
/* check if ISM is available */ |
9aa68d298 net/smc: improve ... |
1249 1250 1251 1252 |
if (pclc->hdr.path == SMC_TYPE_D || pclc->hdr.path == SMC_TYPE_B) { ini.is_smcd = true; /* prepare ISM check */ rc = smc_find_ism_device(new_smc, &ini); if (!rc) |
7a62725a5 net/smc: improve ... |
1253 |
rc = smc_listen_ism_init(new_smc, pclc, &ini); |
9aa68d298 net/smc: improve ... |
1254 1255 1256 1257 1258 1259 1260 1261 |
if (!rc) ism_supported = true; else if (pclc->hdr.path == SMC_TYPE_D) goto out_unlock; /* skip RDMA and decline */ } /* check if RDMA is available */ if (!ism_supported) { /* SMC_TYPE_R or SMC_TYPE_B */ |
bc36d2fc9 net/smc: consolid... |
1262 |
/* prepare RDMA check */ |
bc36d2fc9 net/smc: consolid... |
1263 |
ini.is_smcd = false; |
ca5f8d2dd net/smc: keep vla... |
1264 |
ini.ism_dev = NULL; |
bc36d2fc9 net/smc: consolid... |
1265 |
ini.ib_lcl = &pclc->lcl; |
9aa68d298 net/smc: improve ... |
1266 1267 1268 1269 1270 1271 1272 1273 |
rc = smc_find_rdma_device(new_smc, &ini); if (rc) { /* no RDMA device found */ if (pclc->hdr.path == SMC_TYPE_B) /* neither ISM nor RDMA device found */ rc = SMC_CLC_DECL_NOSMCDEV; goto out_unlock; } |
7a62725a5 net/smc: improve ... |
1274 |
rc = smc_listen_rdma_init(new_smc, &ini); |
9aa68d298 net/smc: improve ... |
1275 1276 |
if (rc) goto out_unlock; |
7a62725a5 net/smc: improve ... |
1277 |
rc = smc_listen_rdma_reg(new_smc, ini.cln_first_contact); |
9aa68d298 net/smc: improve ... |
1278 1279 |
if (rc) goto out_unlock; |
3b2dec260 net/smc: restruct... |
1280 1281 1282 |
} /* send SMC Accept CLC message */ |
7a62725a5 net/smc: improve ... |
1283 |
rc = smc_clc_send_accept(new_smc, ini.cln_first_contact); |
9aa68d298 net/smc: improve ... |
1284 1285 |
if (rc) goto out_unlock; |
3b2dec260 net/smc: restruct... |
1286 |
|
62c7139f3 net/smc: unlock L... |
1287 1288 |
/* SMC-D does not need this lock any more */ if (ism_supported) |
72a36a8ae net/smc: use clie... |
1289 |
mutex_unlock(&smc_server_lgr_pending); |
62c7139f3 net/smc: unlock L... |
1290 |
|
3b2dec260 net/smc: restruct... |
1291 |
/* receive SMC Confirm CLC message */ |
228bae05b net/smc: code cle... |
1292 1293 1294 |
rc = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc), SMC_CLC_CONFIRM, CLC_WAIT_TIME); if (rc) { |
62c7139f3 net/smc: unlock L... |
1295 |
if (!ism_supported) |
9aa68d298 net/smc: improve ... |
1296 1297 |
goto out_unlock; goto out_decl; |
3b2dec260 net/smc: restruct... |
1298 1299 1300 |
} /* finish worker */ |
1ca52fcfa net/smc: remove d... |
1301 |
if (!ism_supported) { |
7a62725a5 net/smc: improve ... |
1302 1303 |
rc = smc_listen_rdma_finish(new_smc, &cclc, ini.cln_first_contact); |
72a36a8ae net/smc: use clie... |
1304 |
mutex_unlock(&smc_server_lgr_pending); |
62c7139f3 net/smc: unlock L... |
1305 |
if (rc) |
1ca52fcfa net/smc: remove d... |
1306 1307 |
return; } |
3b2dec260 net/smc: restruct... |
1308 |
smc_conn_save_peer_info(new_smc, &cclc); |
3b2dec260 net/smc: restruct... |
1309 |
smc_listen_out_connected(new_smc); |
9aa68d298 net/smc: improve ... |
1310 1311 1312 1313 1314 |
return; out_unlock: mutex_unlock(&smc_server_lgr_pending); out_decl: |
7a62725a5 net/smc: improve ... |
1315 |
smc_listen_decline(new_smc, rc, ini.cln_first_contact); |
a046d57da smc: CLC handshak... |
1316 1317 1318 1319 1320 1321 |
} static void smc_tcp_listen_work(struct work_struct *work) { struct smc_sock *lsmc = container_of(work, struct smc_sock, tcp_listen_work); |
3163c5071 net/smc: use loca... |
1322 |
struct sock *lsk = &lsmc->sk; |
a046d57da smc: CLC handshak... |
1323 1324 |
struct smc_sock *new_smc; int rc = 0; |
3163c5071 net/smc: use loca... |
1325 1326 |
lock_sock(lsk); while (lsk->sk_state == SMC_LISTEN) { |
a046d57da smc: CLC handshak... |
1327 1328 1329 1330 1331 1332 1333 |
rc = smc_clcsock_accept(lsmc, &new_smc); if (rc) goto out; if (!new_smc) continue; new_smc->listen_smc = lsmc; |
ee9dfbef0 net/smc: handle s... |
1334 |
new_smc->use_fallback = lsmc->use_fallback; |
603cc1498 net/smc: provide ... |
1335 |
new_smc->fallback_rsn = lsmc->fallback_rsn; |
3163c5071 net/smc: use loca... |
1336 |
sock_hold(lsk); /* sock_put in smc_listen_work */ |
a046d57da smc: CLC handshak... |
1337 1338 |
INIT_WORK(&new_smc->smc_listen_work, smc_listen_work); smc_copy_sock_settings_to_smc(new_smc); |
bd58c7e08 net/smc: allow sy... |
1339 1340 |
new_smc->sk.sk_sndbuf = lsmc->sk.sk_sndbuf; new_smc->sk.sk_rcvbuf = lsmc->sk.sk_rcvbuf; |
51f1de79a net/smc: replace ... |
1341 1342 1343 |
sock_hold(&new_smc->sk); /* sock_put in passive closing */ if (!schedule_work(&new_smc->smc_listen_work)) sock_put(&new_smc->sk); |
a046d57da smc: CLC handshak... |
1344 1345 1346 |
} out: |
3163c5071 net/smc: use loca... |
1347 |
release_sock(lsk); |
51f1de79a net/smc: replace ... |
1348 |
sock_put(&lsmc->sk); /* sock_hold in smc_listen */ |
a046d57da smc: CLC handshak... |
1349 |
} |
ac7138746 smc: establish ne... |
1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 |
static int smc_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; struct smc_sock *smc; int rc; smc = smc_sk(sk); lock_sock(sk); rc = -EINVAL; |
cd2063604 net/smc: avoid fa... |
1360 1361 |
if ((sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) || smc->connect_nonblock) |
ac7138746 smc: establish ne... |
1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 |
goto out; rc = 0; if (sk->sk_state == SMC_LISTEN) { sk->sk_max_ack_backlog = backlog; goto out; } /* some socket options are handled in core, so we could not apply * them to the clc socket -- copy smc socket options to clc socket */ smc_copy_sock_settings_to_clc(smc); |
ee9dfbef0 net/smc: handle s... |
1373 1374 |
if (!smc->use_fallback) tcp_sk(smc->clcsock->sk)->syn_smc = 1; |
ac7138746 smc: establish ne... |
1375 1376 1377 1378 1379 1380 1381 |
rc = kernel_listen(smc->clcsock, backlog); if (rc) goto out; sk->sk_max_ack_backlog = backlog; sk->sk_ack_backlog = 0; sk->sk_state = SMC_LISTEN; |
51f1de79a net/smc: replace ... |
1382 1383 1384 |
sock_hold(sk); /* sock_hold in tcp_listen_worker */ if (!schedule_work(&smc->tcp_listen_work)) sock_put(sk); |
ac7138746 smc: establish ne... |
1385 1386 1387 1388 1389 1390 1391 |
out: release_sock(sk); return rc; } static int smc_accept(struct socket *sock, struct socket *new_sock, |
cdfbabfb2 net: Work around ... |
1392 |
int flags, bool kern) |
ac7138746 smc: establish ne... |
1393 |
{ |
a046d57da smc: CLC handshak... |
1394 1395 |
struct sock *sk = sock->sk, *nsk; DECLARE_WAITQUEUE(wait, current); |
ac7138746 smc: establish ne... |
1396 |
struct smc_sock *lsmc; |
a046d57da smc: CLC handshak... |
1397 1398 |
long timeo; int rc = 0; |
ac7138746 smc: establish ne... |
1399 1400 |
lsmc = smc_sk(sk); |
51f1de79a net/smc: replace ... |
1401 |
sock_hold(sk); /* sock_put below */ |
ac7138746 smc: establish ne... |
1402 1403 1404 1405 |
lock_sock(sk); if (lsmc->sk.sk_state != SMC_LISTEN) { rc = -EINVAL; |
abb190f19 net/smc: handle s... |
1406 |
release_sock(sk); |
ac7138746 smc: establish ne... |
1407 1408 |
goto out; } |
a046d57da smc: CLC handshak... |
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 |
/* Wait for an incoming connection */ timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); add_wait_queue_exclusive(sk_sleep(sk), &wait); while (!(nsk = smc_accept_dequeue(sk, new_sock))) { set_current_state(TASK_INTERRUPTIBLE); if (!timeo) { rc = -EAGAIN; break; } release_sock(sk); timeo = schedule_timeout(timeo); /* wakeup by sk_data_ready in smc_listen_work() */ sched_annotate_sleep(); lock_sock(sk); if (signal_pending(current)) { rc = sock_intr_errno(timeo); break; } } set_current_state(TASK_RUNNING); remove_wait_queue(sk_sleep(sk), &wait); |
ac7138746 smc: establish ne... |
1430 |
|
a046d57da smc: CLC handshak... |
1431 1432 |
if (!rc) rc = sock_error(nsk); |
abb190f19 net/smc: handle s... |
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 |
release_sock(sk); if (rc) goto out; if (lsmc->sockopt_defer_accept && !(flags & O_NONBLOCK)) { /* wait till data arrives on the socket */ timeo = msecs_to_jiffies(lsmc->sockopt_defer_accept * MSEC_PER_SEC); if (smc_sk(nsk)->use_fallback) { struct sock *clcsk = smc_sk(nsk)->clcsock->sk; lock_sock(clcsk); if (skb_queue_empty(&clcsk->sk_receive_queue)) sk_wait_data(clcsk, &timeo, NULL); release_sock(clcsk); } else if (!atomic_read(&smc_sk(nsk)->conn.bytes_to_rcv)) { lock_sock(nsk); |
b51fa1b13 smc: make smc_rx_... |
1450 |
smc_rx_wait(smc_sk(nsk), &timeo, smc_rx_data_available); |
abb190f19 net/smc: handle s... |
1451 1452 1453 |
release_sock(nsk); } } |
ac7138746 smc: establish ne... |
1454 1455 |
out: |
51f1de79a net/smc: replace ... |
1456 |
sock_put(sk); /* sock_hold above */ |
ac7138746 smc: establish ne... |
1457 1458 1459 1460 |
return rc; } static int smc_getname(struct socket *sock, struct sockaddr *addr, |
9b2c45d47 net: make getname... |
1461 |
int peer) |
ac7138746 smc: establish ne... |
1462 1463 |
{ struct smc_sock *smc; |
b38d73247 smc: socket closi... |
1464 1465 |
if (peer && (sock->sk->sk_state != SMC_ACTIVE) && (sock->sk->sk_state != SMC_APPCLOSEWAIT1)) |
ac7138746 smc: establish ne... |
1466 1467 1468 |
return -ENOTCONN; smc = smc_sk(sock->sk); |
9b2c45d47 net: make getname... |
1469 |
return smc->clcsock->ops->getname(smc->clcsock, addr, peer); |
ac7138746 smc: establish ne... |
1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 |
} static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; struct smc_sock *smc; int rc = -EPIPE; smc = smc_sk(sk); lock_sock(sk); |
b38d73247 smc: socket closi... |
1480 1481 1482 |
if ((sk->sk_state != SMC_ACTIVE) && (sk->sk_state != SMC_APPCLOSEWAIT1) && (sk->sk_state != SMC_INIT)) |
ac7138746 smc: establish ne... |
1483 |
goto out; |
ee9dfbef0 net/smc: handle s... |
1484 1485 |
if (msg->msg_flags & MSG_FASTOPEN) { |
cd2063604 net/smc: avoid fa... |
1486 |
if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) { |
07603b230 net/smc: propagat... |
1487 |
smc_switch_to_fallback(smc); |
603cc1498 net/smc: provide ... |
1488 |
smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP; |
ee9dfbef0 net/smc: handle s... |
1489 1490 1491 1492 1493 |
} else { rc = -EINVAL; goto out; } } |
ac7138746 smc: establish ne... |
1494 1495 1496 |
if (smc->use_fallback) rc = smc->clcsock->ops->sendmsg(smc->clcsock, msg, len); else |
e6727f390 smc: send data (t... |
1497 |
rc = smc_tx_sendmsg(smc, msg, len); |
ac7138746 smc: establish ne... |
1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 |
out: release_sock(sk); return rc; } static int smc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int flags) { struct sock *sk = sock->sk; struct smc_sock *smc; int rc = -ENOTCONN; smc = smc_sk(sk); lock_sock(sk); |
51c5aba3b net/smc: recvmsg ... |
1512 1513 1514 1515 1516 |
if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) { /* socket was connected before, no more data to read */ rc = 0; goto out; } |
b38d73247 smc: socket closi... |
1517 1518 1519 |
if ((sk->sk_state == SMC_INIT) || (sk->sk_state == SMC_LISTEN) || (sk->sk_state == SMC_CLOSED)) |
ac7138746 smc: establish ne... |
1520 |
goto out; |
b38d73247 smc: socket closi... |
1521 1522 1523 1524 |
if (sk->sk_state == SMC_PEERFINCLOSEWAIT) { rc = 0; goto out; } |
9014db202 smc: add support ... |
1525 |
if (smc->use_fallback) { |
ac7138746 smc: establish ne... |
1526 |
rc = smc->clcsock->ops->recvmsg(smc->clcsock, msg, len, flags); |
9014db202 smc: add support ... |
1527 1528 1529 1530 |
} else { msg->msg_namelen = 0; rc = smc_rx_recvmsg(smc, msg, NULL, len, flags); } |
b38d73247 smc: socket closi... |
1531 |
|
ac7138746 smc: establish ne... |
1532 1533 1534 1535 |
out: release_sock(sk); return rc; } |
ade994f4f net: annotate ->p... |
1536 |
static __poll_t smc_accept_poll(struct sock *parent) |
a046d57da smc: CLC handshak... |
1537 |
{ |
8dce2786a net/smc: smc_poll... |
1538 |
struct smc_sock *isk = smc_sk(parent); |
63e2480c8 smc: missing poll... |
1539 |
__poll_t mask = 0; |
a046d57da smc: CLC handshak... |
1540 |
|
8dce2786a net/smc: smc_poll... |
1541 1542 |
spin_lock(&isk->accept_q_lock); if (!list_empty(&isk->accept_q)) |
a9a08845e vfs: do bulk POLL... |
1543 |
mask = EPOLLIN | EPOLLRDNORM; |
8dce2786a net/smc: smc_poll... |
1544 |
spin_unlock(&isk->accept_q_lock); |
a046d57da smc: CLC handshak... |
1545 |
|
8dce2786a net/smc: smc_poll... |
1546 |
return mask; |
a046d57da smc: CLC handshak... |
1547 |
} |
a11e1d432 Revert changes to... |
1548 1549 |
static __poll_t smc_poll(struct file *file, struct socket *sock, poll_table *wait) |
ac7138746 smc: establish ne... |
1550 1551 |
{ struct sock *sk = sock->sk; |
ac7138746 smc: establish ne... |
1552 |
struct smc_sock *smc; |
50717a37d net/smc: nonblock... |
1553 |
__poll_t mask = 0; |
ac7138746 smc: establish ne... |
1554 |
|
8dce2786a net/smc: smc_poll... |
1555 |
if (!sk) |
a9a08845e vfs: do bulk POLL... |
1556 |
return EPOLLNVAL; |
8dce2786a net/smc: smc_poll... |
1557 |
|
ac7138746 smc: establish ne... |
1558 |
smc = smc_sk(sock->sk); |
648a5a7ae net/smc: fix non-... |
1559 |
if (smc->use_fallback) { |
a046d57da smc: CLC handshak... |
1560 |
/* delegate to CLC child sock */ |
a11e1d432 Revert changes to... |
1561 |
mask = smc->clcsock->ops->poll(file, smc->clcsock, wait); |
784813aed net/smc: restrict... |
1562 |
sk->sk_err = smc->clcsock->sk->sk_err; |
ac7138746 smc: establish ne... |
1563 |
} else { |
410da1e12 net/smc: fix up m... |
1564 |
if (sk->sk_state != SMC_CLOSED) |
89ab066d4 Revert "net: simp... |
1565 |
sock_poll_wait(file, sock, wait); |
a046d57da smc: CLC handshak... |
1566 |
if (sk->sk_err) |
a9a08845e vfs: do bulk POLL... |
1567 |
mask |= EPOLLERR; |
b38d73247 smc: socket closi... |
1568 1569 |
if ((sk->sk_shutdown == SHUTDOWN_MASK) || (sk->sk_state == SMC_CLOSED)) |
a9a08845e vfs: do bulk POLL... |
1570 |
mask |= EPOLLHUP; |
8dce2786a net/smc: smc_poll... |
1571 1572 |
if (sk->sk_state == SMC_LISTEN) { /* woken up by sk_data_ready in smc_listen_work() */ |
50717a37d net/smc: nonblock... |
1573 1574 1575 1576 1577 |
mask |= smc_accept_poll(sk); } else if (smc->use_fallback) { /* as result of connect_work()*/ mask |= smc->clcsock->ops->poll(file, smc->clcsock, wait); sk->sk_err = smc->clcsock->sk->sk_err; |
8dce2786a net/smc: smc_poll... |
1578 |
} else { |
50717a37d net/smc: nonblock... |
1579 1580 |
if ((sk->sk_state != SMC_INIT && atomic_read(&smc->conn.sndbuf_space)) || |
8dce2786a net/smc: smc_poll... |
1581 |
sk->sk_shutdown & SEND_SHUTDOWN) { |
a9a08845e vfs: do bulk POLL... |
1582 |
mask |= EPOLLOUT | EPOLLWRNORM; |
8dce2786a net/smc: smc_poll... |
1583 1584 1585 1586 1587 |
} else { sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); } if (atomic_read(&smc->conn.bytes_to_rcv)) |
a9a08845e vfs: do bulk POLL... |
1588 |
mask |= EPOLLIN | EPOLLRDNORM; |
8dce2786a net/smc: smc_poll... |
1589 |
if (sk->sk_shutdown & RCV_SHUTDOWN) |
a9a08845e vfs: do bulk POLL... |
1590 |
mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; |
8dce2786a net/smc: smc_poll... |
1591 |
if (sk->sk_state == SMC_APPCLOSEWAIT1) |
a9a08845e vfs: do bulk POLL... |
1592 |
mask |= EPOLLIN; |
71d117f52 net/smc: no urgen... |
1593 1594 |
if (smc->conn.urg_state == SMC_URG_VALID) mask |= EPOLLPRI; |
8dce2786a net/smc: smc_poll... |
1595 |
} |
ac7138746 smc: establish ne... |
1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 |
} return mask; } static int smc_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; struct smc_sock *smc; int rc = -EINVAL; |
b38d73247 smc: socket closi... |
1606 |
int rc1 = 0; |
ac7138746 smc: establish ne... |
1607 1608 1609 1610 |
smc = smc_sk(sk); if ((how < SHUT_RD) || (how > SHUT_RDWR)) |
b38d73247 smc: socket closi... |
1611 |
return rc; |
ac7138746 smc: establish ne... |
1612 1613 1614 1615 |
lock_sock(sk); rc = -ENOTCONN; |
caa21e19e net/smc: no shutd... |
1616 |
if ((sk->sk_state != SMC_ACTIVE) && |
b38d73247 smc: socket closi... |
1617 1618 1619 1620 1621 |
(sk->sk_state != SMC_PEERCLOSEWAIT1) && (sk->sk_state != SMC_PEERCLOSEWAIT2) && (sk->sk_state != SMC_APPCLOSEWAIT1) && (sk->sk_state != SMC_APPCLOSEWAIT2) && (sk->sk_state != SMC_APPFINCLOSEWAIT)) |
ac7138746 smc: establish ne... |
1622 1623 1624 1625 1626 1627 |
goto out; if (smc->use_fallback) { rc = kernel_sock_shutdown(smc->clcsock, how); sk->sk_shutdown = smc->clcsock->sk->sk_shutdown; if (sk->sk_shutdown == SHUTDOWN_MASK) sk->sk_state = SMC_CLOSED; |
b38d73247 smc: socket closi... |
1628 |
goto out; |
ac7138746 smc: establish ne... |
1629 |
} |
b38d73247 smc: socket closi... |
1630 1631 1632 1633 1634 1635 1636 1637 |
switch (how) { case SHUT_RDWR: /* shutdown in both directions */ rc = smc_close_active(smc); break; case SHUT_WR: rc = smc_close_shutdown_write(smc); break; case SHUT_RD: |
1255fcb2a net/smc: fix shut... |
1638 1639 |
rc = 0; /* nothing more to do because peer is not involved */ |
b38d73247 smc: socket closi... |
1640 1641 |
break; } |
1255fcb2a net/smc: fix shut... |
1642 1643 |
if (smc->clcsock) rc1 = kernel_sock_shutdown(smc->clcsock, how); |
b38d73247 smc: socket closi... |
1644 1645 |
/* map sock_shutdown_cmd constants to sk_shutdown value range */ sk->sk_shutdown |= how + 1; |
ac7138746 smc: establish ne... |
1646 1647 1648 |
out: release_sock(sk); |
b38d73247 smc: socket closi... |
1649 |
return rc ? rc : rc1; |
ac7138746 smc: establish ne... |
1650 1651 1652 1653 1654 1655 1656 |
} static int smc_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; struct smc_sock *smc; |
01d2f7e2c net/smc: sockopts... |
1657 |
int val, rc; |
ac7138746 smc: establish ne... |
1658 1659 1660 1661 1662 1663 |
smc = smc_sk(sk); /* generic setsockopts reaching us here always apply to the * CLC socket */ |
ee9dfbef0 net/smc: handle s... |
1664 1665 1666 1667 1668 1669 |
rc = smc->clcsock->ops->setsockopt(smc->clcsock, level, optname, optval, optlen); if (smc->clcsock->sk->sk_err) { sk->sk_err = smc->clcsock->sk->sk_err; sk->sk_error_report(sk); } |
ee9dfbef0 net/smc: handle s... |
1670 |
|
01d2f7e2c net/smc: sockopts... |
1671 |
if (optlen < sizeof(int)) |
3dc9f558c net/smc: fix erro... |
1672 |
return -EINVAL; |
ac0107edb net/smc: add erro... |
1673 1674 |
if (get_user(val, (int __user *)optval)) return -EFAULT; |
01d2f7e2c net/smc: sockopts... |
1675 |
|
ee9dfbef0 net/smc: handle s... |
1676 |
lock_sock(sk); |
86434744f net/smc: add fall... |
1677 1678 |
if (rc || smc->use_fallback) goto out; |
ee9dfbef0 net/smc: handle s... |
1679 1680 1681 1682 1683 1684 1685 |
switch (optname) { case TCP_ULP: case TCP_FASTOPEN: case TCP_FASTOPEN_CONNECT: case TCP_FASTOPEN_KEY: case TCP_FASTOPEN_NO_COOKIE: /* option not supported by SMC */ |
8204df72b net/smc: fix fast... |
1686 |
if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) { |
07603b230 net/smc: propagat... |
1687 |
smc_switch_to_fallback(smc); |
603cc1498 net/smc: provide ... |
1688 |
smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP; |
ee9dfbef0 net/smc: handle s... |
1689 |
} else { |
86434744f net/smc: add fall... |
1690 |
rc = -EINVAL; |
ee9dfbef0 net/smc: handle s... |
1691 1692 |
} break; |
01d2f7e2c net/smc: sockopts... |
1693 |
case TCP_NODELAY: |
f9cedf1a9 net/smc: do not s... |
1694 1695 1696 |
if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_CLOSED) { |
86434744f net/smc: add fall... |
1697 |
if (val) |
01d2f7e2c net/smc: sockopts... |
1698 1699 1700 1701 1702 |
mod_delayed_work(system_wq, &smc->conn.tx_work, 0); } break; case TCP_CORK: |
f9cedf1a9 net/smc: do not s... |
1703 1704 1705 |
if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN && sk->sk_state != SMC_CLOSED) { |
86434744f net/smc: add fall... |
1706 |
if (!val) |
01d2f7e2c net/smc: sockopts... |
1707 1708 1709 1710 |
mod_delayed_work(system_wq, &smc->conn.tx_work, 0); } break; |
abb190f19 net/smc: handle s... |
1711 1712 1713 |
case TCP_DEFER_ACCEPT: smc->sockopt_defer_accept = val; break; |
ee9dfbef0 net/smc: handle s... |
1714 1715 1716 |
default: break; } |
86434744f net/smc: add fall... |
1717 |
out: |
ee9dfbef0 net/smc: handle s... |
1718 1719 1720 |
release_sock(sk); return rc; |
ac7138746 smc: establish ne... |
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 |
} static int smc_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct smc_sock *smc; smc = smc_sk(sock->sk); /* socket options apply to the CLC socket */ return smc->clcsock->ops->getsockopt(smc->clcsock, level, optname, optval, optlen); } static int smc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { |
de8474eb9 net/smc: urgent d... |
1737 1738 |
union smc_host_cursor cons, urg; struct smc_connection *conn; |
ac7138746 smc: establish ne... |
1739 |
struct smc_sock *smc; |
9b67e26f9 net/smc: handle i... |
1740 |
int answ; |
ac7138746 smc: establish ne... |
1741 1742 |
smc = smc_sk(sock->sk); |
de8474eb9 net/smc: urgent d... |
1743 |
conn = &smc->conn; |
7311d665c net/smc: move soc... |
1744 |
lock_sock(&smc->sk); |
9b67e26f9 net/smc: handle i... |
1745 |
if (smc->use_fallback) { |
7311d665c net/smc: move soc... |
1746 1747 |
if (!smc->clcsock) { release_sock(&smc->sk); |
9b67e26f9 net/smc: handle i... |
1748 |
return -EBADF; |
7311d665c net/smc: move soc... |
1749 1750 1751 1752 |
} answ = smc->clcsock->ops->ioctl(smc->clcsock, cmd, arg); release_sock(&smc->sk); return answ; |
9b67e26f9 net/smc: handle i... |
1753 1754 1755 |
} switch (cmd) { case SIOCINQ: /* same as FIONREAD */ |
1992d9988 net/smc: take soc... |
1756 1757 |
if (smc->sk.sk_state == SMC_LISTEN) { release_sock(&smc->sk); |
9b67e26f9 net/smc: handle i... |
1758 |
return -EINVAL; |
1992d9988 net/smc: take soc... |
1759 |
} |
2351abe6f net/smc: return 0... |
1760 1761 1762 1763 1764 |
if (smc->sk.sk_state == SMC_INIT || smc->sk.sk_state == SMC_CLOSED) answ = 0; else answ = atomic_read(&smc->conn.bytes_to_rcv); |
9b67e26f9 net/smc: handle i... |
1765 1766 1767 |
break; case SIOCOUTQ: /* output queue size (not send + not acked) */ |
1992d9988 net/smc: take soc... |
1768 1769 |
if (smc->sk.sk_state == SMC_LISTEN) { release_sock(&smc->sk); |
9b67e26f9 net/smc: handle i... |
1770 |
return -EINVAL; |
1992d9988 net/smc: take soc... |
1771 |
} |
2351abe6f net/smc: return 0... |
1772 1773 1774 1775 1776 |
if (smc->sk.sk_state == SMC_INIT || smc->sk.sk_state == SMC_CLOSED) answ = 0; else answ = smc->conn.sndbuf_desc->len - |
9b67e26f9 net/smc: handle i... |
1777 1778 1779 1780 |
atomic_read(&smc->conn.sndbuf_space); break; case SIOCOUTQNSD: /* output queue size (not send only) */ |
1992d9988 net/smc: take soc... |
1781 1782 |
if (smc->sk.sk_state == SMC_LISTEN) { release_sock(&smc->sk); |
9b67e26f9 net/smc: handle i... |
1783 |
return -EINVAL; |
1992d9988 net/smc: take soc... |
1784 |
} |
2351abe6f net/smc: return 0... |
1785 1786 1787 1788 1789 |
if (smc->sk.sk_state == SMC_INIT || smc->sk.sk_state == SMC_CLOSED) answ = 0; else answ = smc_tx_prepared_sends(&smc->conn); |
9b67e26f9 net/smc: handle i... |
1790 |
break; |
de8474eb9 net/smc: urgent d... |
1791 |
case SIOCATMARK: |
1992d9988 net/smc: take soc... |
1792 1793 |
if (smc->sk.sk_state == SMC_LISTEN) { release_sock(&smc->sk); |
de8474eb9 net/smc: urgent d... |
1794 |
return -EINVAL; |
1992d9988 net/smc: take soc... |
1795 |
} |
de8474eb9 net/smc: urgent d... |
1796 1797 1798 1799 |
if (smc->sk.sk_state == SMC_INIT || smc->sk.sk_state == SMC_CLOSED) { answ = 0; } else { |
bac6de7b6 net/smc: eliminat... |
1800 1801 |
smc_curs_copy(&cons, &conn->local_tx_ctrl.cons, conn); smc_curs_copy(&urg, &conn->urg_curs, conn); |
de8474eb9 net/smc: urgent d... |
1802 1803 1804 1805 |
answ = smc_curs_diff(conn->rmb_desc->len, &cons, &urg) == 1; } break; |
9b67e26f9 net/smc: handle i... |
1806 |
default: |
1992d9988 net/smc: take soc... |
1807 |
release_sock(&smc->sk); |
9b67e26f9 net/smc: handle i... |
1808 1809 |
return -ENOIOCTLCMD; } |
1992d9988 net/smc: take soc... |
1810 |
release_sock(&smc->sk); |
9b67e26f9 net/smc: handle i... |
1811 1812 |
return put_user(answ, (int __user *)arg); |
ac7138746 smc: establish ne... |
1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 |
} static ssize_t smc_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags) { struct sock *sk = sock->sk; struct smc_sock *smc; int rc = -EPIPE; smc = smc_sk(sk); lock_sock(sk); |
bda27ff5c smc: fix sendpage... |
1824 1825 |
if (sk->sk_state != SMC_ACTIVE) { release_sock(sk); |
ac7138746 smc: establish ne... |
1826 |
goto out; |
bda27ff5c smc: fix sendpage... |
1827 1828 |
} release_sock(sk); |
ac7138746 smc: establish ne... |
1829 1830 1831 1832 1833 1834 1835 |
if (smc->use_fallback) rc = kernel_sendpage(smc->clcsock, page, offset, size, flags); else rc = sock_no_sendpage(sock, page, offset, size, flags); out: |
ac7138746 smc: establish ne... |
1836 1837 |
return rc; } |
9014db202 smc: add support ... |
1838 1839 1840 1841 1842 1843 |
/* Map the affected portions of the rmbe into an spd, note the number of bytes * to splice in conn->splice_pending, and press 'go'. Delays consumer cursor * updates till whenever a respective page has been fully processed. * Note that subsequent recv() calls have to wait till all splice() processing * completed. */ |
ac7138746 smc: establish ne... |
1844 1845 |
static ssize_t smc_splice_read(struct socket *sock, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, |
9014db202 smc: add support ... |
1846 |
unsigned int flags) |
ac7138746 smc: establish ne... |
1847 1848 1849 1850 1851 1852 1853 |
{ struct sock *sk = sock->sk; struct smc_sock *smc; int rc = -ENOTCONN; smc = smc_sk(sk); lock_sock(sk); |
51c5aba3b net/smc: recvmsg ... |
1854 1855 1856 1857 1858 |
if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) { /* socket was connected before, no more data to read */ rc = 0; goto out; } |
9014db202 smc: add support ... |
1859 1860 1861 1862 1863 1864 1865 |
if (sk->sk_state == SMC_INIT || sk->sk_state == SMC_LISTEN || sk->sk_state == SMC_CLOSED) goto out; if (sk->sk_state == SMC_PEERFINCLOSEWAIT) { rc = 0; |
ac7138746 smc: establish ne... |
1866 |
goto out; |
9014db202 smc: add support ... |
1867 |
} |
ac7138746 smc: establish ne... |
1868 1869 1870 1871 |
if (smc->use_fallback) { rc = smc->clcsock->ops->splice_read(smc->clcsock, ppos, pipe, len, flags); } else { |
9014db202 smc: add support ... |
1872 1873 1874 1875 1876 1877 1878 1879 1880 |
if (*ppos) { rc = -ESPIPE; goto out; } if (flags & SPLICE_F_NONBLOCK) flags = MSG_DONTWAIT; else flags = 0; rc = smc_rx_recvmsg(smc, NULL, pipe, len, flags); |
ac7138746 smc: establish ne... |
1881 1882 1883 |
} out: release_sock(sk); |
9014db202 smc: add support ... |
1884 |
|
ac7138746 smc: establish ne... |
1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 |
return rc; } /* must look like tcp */ static const struct proto_ops smc_sock_ops = { .family = PF_SMC, .owner = THIS_MODULE, .release = smc_release, .bind = smc_bind, .connect = smc_connect, .socketpair = sock_no_socketpair, .accept = smc_accept, .getname = smc_getname, |
a11e1d432 Revert changes to... |
1898 |
.poll = smc_poll, |
ac7138746 smc: establish ne... |
1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 |
.ioctl = smc_ioctl, .listen = smc_listen, .shutdown = smc_shutdown, .setsockopt = smc_setsockopt, .getsockopt = smc_getsockopt, .sendmsg = smc_sendmsg, .recvmsg = smc_recvmsg, .mmap = sock_no_mmap, .sendpage = smc_sendpage, .splice_read = smc_splice_read, }; static int smc_create(struct net *net, struct socket *sock, int protocol, int kern) { |
aaa4d33f6 net/smc: enable i... |
1914 |
int family = (protocol == SMCPROTO_SMC6) ? PF_INET6 : PF_INET; |
ac7138746 smc: establish ne... |
1915 1916 1917 1918 1919 1920 1921 1922 1923 |
struct smc_sock *smc; struct sock *sk; int rc; rc = -ESOCKTNOSUPPORT; if (sock->type != SOCK_STREAM) goto out; rc = -EPROTONOSUPPORT; |
aaa4d33f6 net/smc: enable i... |
1924 |
if (protocol != SMCPROTO_SMC && protocol != SMCPROTO_SMC6) |
ac7138746 smc: establish ne... |
1925 1926 1927 1928 |
goto out; rc = -ENOBUFS; sock->ops = &smc_sock_ops; |
aaa4d33f6 net/smc: enable i... |
1929 |
sk = smc_sock_alloc(net, sock, protocol); |
ac7138746 smc: establish ne... |
1930 1931 1932 1933 1934 |
if (!sk) goto out; /* create internal TCP socket for CLC handshake and fallback */ smc = smc_sk(sk); |
a046d57da smc: CLC handshak... |
1935 |
smc->use_fallback = false; /* assume rdma capability first */ |
603cc1498 net/smc: provide ... |
1936 |
smc->fallback_rsn = 0; |
aaa4d33f6 net/smc: enable i... |
1937 1938 |
rc = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP, &smc->clcsock); |
a5dcb73b9 net/smc: fix NULL... |
1939 |
if (rc) { |
ac7138746 smc: establish ne... |
1940 |
sk_common_release(sk); |
a5dcb73b9 net/smc: fix NULL... |
1941 1942 |
goto out; } |
cd6851f30 smc: remote memor... |
1943 1944 |
smc->sk.sk_sndbuf = max(smc->clcsock->sk->sk_sndbuf, SMC_BUF_MIN_SIZE); smc->sk.sk_rcvbuf = max(smc->clcsock->sk->sk_rcvbuf, SMC_BUF_MIN_SIZE); |
ac7138746 smc: establish ne... |
1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 |
out: return rc; } static const struct net_proto_family smc_sock_family_ops = { .family = PF_SMC, .owner = THIS_MODULE, .create = smc_create, }; |
64e28b52c net/smc: add pnet... |
1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 |
unsigned int smc_net_id; static __net_init int smc_net_init(struct net *net) { return smc_pnet_net_init(net); } static void __net_exit smc_net_exit(struct net *net) { smc_pnet_net_exit(net); } static struct pernet_operations smc_net_ops = { .init = smc_net_init, .exit = smc_net_exit, .id = &smc_net_id, .size = sizeof(struct smc_net), }; |
ac7138746 smc: establish ne... |
1973 1974 1975 |
static int __init smc_init(void) { int rc; |
64e28b52c net/smc: add pnet... |
1976 1977 1978 |
rc = register_pernet_subsys(&smc_net_ops); if (rc) return rc; |
6812baabf smc: establish pn... |
1979 1980 |
rc = smc_pnet_init(); if (rc) |
8c33bf1b0 net/smc: Fix erro... |
1981 |
goto out_pernet_subsys; |
6812baabf smc: establish pn... |
1982 |
|
6dabd4054 net/smc: introduc... |
1983 1984 1985 1986 1987 1988 |
rc = smc_core_init(); if (rc) { pr_err("%s: smc_core_init fails with %d ", __func__, rc); goto out_pnet; } |
9bf9abead smc: link layer c... |
1989 1990 1991 1992 |
rc = smc_llc_init(); if (rc) { pr_err("%s: smc_llc_init fails with %d ", __func__, rc); |
6dabd4054 net/smc: introduc... |
1993 |
goto out_core; |
9bf9abead smc: link layer c... |
1994 |
} |
5f08318f6 smc: connection d... |
1995 1996 1997 1998 |
rc = smc_cdc_init(); if (rc) { pr_err("%s: smc_cdc_init fails with %d ", __func__, rc); |
6dabd4054 net/smc: introduc... |
1999 |
goto out_core; |
5f08318f6 smc: connection d... |
2000 |
} |
ac7138746 smc: establish ne... |
2001 2002 |
rc = proto_register(&smc_proto, 1); if (rc) { |
aaa4d33f6 net/smc: enable i... |
2003 2004 |
pr_err("%s: proto_register(v4) fails with %d ", __func__, rc); |
6dabd4054 net/smc: introduc... |
2005 |
goto out_core; |
ac7138746 smc: establish ne... |
2006 |
} |
aaa4d33f6 net/smc: enable i... |
2007 2008 2009 2010 2011 2012 |
rc = proto_register(&smc_proto6, 1); if (rc) { pr_err("%s: proto_register(v6) fails with %d ", __func__, rc); goto out_proto; } |
ac7138746 smc: establish ne... |
2013 2014 2015 2016 |
rc = sock_register(&smc_sock_family_ops); if (rc) { pr_err("%s: sock_register fails with %d ", __func__, rc); |
aaa4d33f6 net/smc: enable i... |
2017 |
goto out_proto6; |
ac7138746 smc: establish ne... |
2018 |
} |
f16a7dd5c smc: netlink inte... |
2019 |
INIT_HLIST_HEAD(&smc_v4_hashinfo.ht); |
aaa4d33f6 net/smc: enable i... |
2020 |
INIT_HLIST_HEAD(&smc_v6_hashinfo.ht); |
ac7138746 smc: establish ne... |
2021 |
|
a4cf0443c smc: introduce SM... |
2022 2023 2024 2025 2026 2027 |
rc = smc_ib_register_client(); if (rc) { pr_err("%s: ib_register fails with %d ", __func__, rc); goto out_sock; } |
c5c1cc9c5 smc: add SMC rend... |
2028 |
static_branch_enable(&tcp_have_smc); |
ac7138746 smc: establish ne... |
2029 |
return 0; |
a4cf0443c smc: introduce SM... |
2030 2031 |
out_sock: sock_unregister(PF_SMC); |
aaa4d33f6 net/smc: enable i... |
2032 2033 |
out_proto6: proto_unregister(&smc_proto6); |
ac7138746 smc: establish ne... |
2034 2035 |
out_proto: proto_unregister(&smc_proto); |
6dabd4054 net/smc: introduc... |
2036 2037 |
out_core: smc_core_exit(); |
6812baabf smc: establish pn... |
2038 2039 |
out_pnet: smc_pnet_exit(); |
8c33bf1b0 net/smc: Fix erro... |
2040 2041 |
out_pernet_subsys: unregister_pernet_subsys(&smc_net_ops); |
ac7138746 smc: establish ne... |
2042 2043 2044 2045 2046 |
return rc; } static void __exit smc_exit(void) { |
c5c1cc9c5 smc: add SMC rend... |
2047 |
static_branch_disable(&tcp_have_smc); |
ac7138746 smc: establish ne... |
2048 |
sock_unregister(PF_SMC); |
6dabd4054 net/smc: introduc... |
2049 2050 |
smc_core_exit(); smc_ib_unregister_client(); |
aaa4d33f6 net/smc: enable i... |
2051 |
proto_unregister(&smc_proto6); |
ac7138746 smc: establish ne... |
2052 |
proto_unregister(&smc_proto); |
6812baabf smc: establish pn... |
2053 |
smc_pnet_exit(); |
64e28b52c net/smc: add pnet... |
2054 |
unregister_pernet_subsys(&smc_net_ops); |
4ead9c96d net/smc: use rcu_... |
2055 |
rcu_barrier(); |
ac7138746 smc: establish ne... |
2056 2057 2058 2059 2060 2061 2062 2063 2064 |
} module_init(smc_init); module_exit(smc_exit); MODULE_AUTHOR("Ursula Braun <ubraun@linux.vnet.ibm.com>"); MODULE_DESCRIPTION("smc socket address family"); MODULE_LICENSE("GPL"); MODULE_ALIAS_NETPROTO(PF_SMC); |