Skip to content

Commit 66c5c5b

Browse files
committed
Merge branch 'smc-fixes-next'
Ursula Braun says: ==================== smc: fixes 2017-12-07 here are some smc-patches. The initial 4 patches are cleanups. Patch 5 gets rid of ib_post_sends in tasklet context to avoid peer drops due to out-of-order receivals. Patch 6 makes sure, the Linux SMC code understands variable sized CLC proposal messages built according to RFC7609. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 2a93c1a + e7b7a64 commit 66c5c5b

File tree

8 files changed

+118
-55
lines changed

8 files changed

+118
-55
lines changed

net/smc/af_smc.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ static int smc_connect_rdma(struct smc_sock *smc)
520520
smc->use_fallback = true;
521521
if (reason_code && (reason_code != SMC_CLC_DECL_REPLY)) {
522522
rc = smc_clc_send_decline(smc, reason_code);
523-
if (rc < sizeof(struct smc_clc_msg_decline))
523+
if (rc < 0)
524524
goto out_err;
525525
}
526526
goto out_connected;
@@ -751,14 +751,16 @@ static void smc_listen_work(struct work_struct *work)
751751
{
752752
struct smc_sock *new_smc = container_of(work, struct smc_sock,
753753
smc_listen_work);
754+
struct smc_clc_msg_proposal_prefix *pclc_prfx;
754755
struct socket *newclcsock = new_smc->clcsock;
755756
struct smc_sock *lsmc = new_smc->listen_smc;
756757
struct smc_clc_msg_accept_confirm cclc;
757758
int local_contact = SMC_REUSE_CONTACT;
758759
struct sock *newsmcsk = &new_smc->sk;
759-
struct smc_clc_msg_proposal pclc;
760+
struct smc_clc_msg_proposal *pclc;
760761
struct smc_ib_device *smcibdev;
761762
struct sockaddr_in peeraddr;
763+
u8 buf[SMC_CLC_MAX_LEN];
762764
struct smc_link *link;
763765
int reason_code = 0;
764766
int rc = 0, len;
@@ -775,7 +777,7 @@ static void smc_listen_work(struct work_struct *work)
775777
/* do inband token exchange -
776778
*wait for and receive SMC Proposal CLC message
777779
*/
778-
reason_code = smc_clc_wait_msg(new_smc, &pclc, sizeof(pclc),
780+
reason_code = smc_clc_wait_msg(new_smc, &buf, sizeof(buf),
779781
SMC_CLC_PROPOSAL);
780782
if (reason_code < 0)
781783
goto out_err;
@@ -804,8 +806,11 @@ static void smc_listen_work(struct work_struct *work)
804806
reason_code = SMC_CLC_DECL_CNFERR; /* configuration error */
805807
goto decline_rdma;
806808
}
807-
if ((pclc.outgoing_subnet != subnet) ||
808-
(pclc.prefix_len != prefix_len)) {
809+
810+
pclc = (struct smc_clc_msg_proposal *)&buf;
811+
pclc_prfx = smc_clc_proposal_get_prefix(pclc);
812+
if (pclc_prfx->outgoing_subnet != subnet ||
813+
pclc_prfx->prefix_len != prefix_len) {
809814
reason_code = SMC_CLC_DECL_CNFERR; /* configuration error */
810815
goto decline_rdma;
811816
}
@@ -816,7 +821,7 @@ static void smc_listen_work(struct work_struct *work)
816821
/* allocate connection / link group */
817822
mutex_lock(&smc_create_lgr_pending);
818823
local_contact = smc_conn_create(new_smc, peeraddr.sin_addr.s_addr,
819-
smcibdev, ibport, &pclc.lcl, 0);
824+
smcibdev, ibport, &pclc->lcl, 0);
820825
if (local_contact < 0) {
821826
rc = local_contact;
822827
if (rc == -ENOMEM)
@@ -879,11 +884,9 @@ static void smc_listen_work(struct work_struct *work)
879884
}
880885
/* QP confirmation over RoCE fabric */
881886
reason_code = smc_serv_conf_first_link(new_smc);
882-
if (reason_code < 0) {
887+
if (reason_code < 0)
883888
/* peer is not aware of a problem */
884-
rc = reason_code;
885889
goto out_err_unlock;
886-
}
887890
if (reason_code > 0)
888891
goto decline_rdma_unlock;
889892
}
@@ -916,8 +919,7 @@ static void smc_listen_work(struct work_struct *work)
916919
smc_conn_free(&new_smc->conn);
917920
new_smc->use_fallback = true;
918921
if (reason_code && (reason_code != SMC_CLC_DECL_REPLY)) {
919-
rc = smc_clc_send_decline(new_smc, reason_code);
920-
if (rc < sizeof(struct smc_clc_msg_decline))
922+
if (smc_clc_send_decline(new_smc, reason_code) < 0)
921923
goto out_err;
922924
}
923925
goto out_connected;

net/smc/smc_cdc.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ static void smc_cdc_msg_recv_action(struct smc_sock *smc,
213213
/* guarantee 0 <= bytes_to_rcv <= rmbe_size */
214214
smp_mb__after_atomic();
215215
smc->sk.sk_data_ready(&smc->sk);
216+
} else if ((conn->local_rx_ctrl.prod_flags.write_blocked) ||
217+
(conn->local_rx_ctrl.prod_flags.cons_curs_upd_req)) {
218+
smc->sk.sk_data_ready(&smc->sk);
216219
}
217220

218221
if (conn->local_rx_ctrl.conn_state_flags.peer_conn_abort) {
@@ -234,15 +237,6 @@ static void smc_cdc_msg_recv_action(struct smc_sock *smc,
234237
/* trigger socket release if connection closed */
235238
smc_close_wake_tx_prepared(smc);
236239
}
237-
238-
/* socket connected but not accepted */
239-
if (!smc->sk.sk_socket)
240-
return;
241-
242-
/* data available */
243-
if ((conn->local_rx_ctrl.prod_flags.write_blocked) ||
244-
(conn->local_rx_ctrl.prod_flags.cons_curs_upd_req))
245-
smc_tx_consumer_update(conn);
246240
}
247241

248242
/* called under tasklet context */

net/smc/smc_clc.c

Lines changed: 70 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,54 @@
2222
#include "smc_clc.h"
2323
#include "smc_ib.h"
2424

25+
/* check if received message has a correct header length and contains valid
26+
* heading and trailing eyecatchers
27+
*/
28+
static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
29+
{
30+
struct smc_clc_msg_proposal_prefix *pclc_prfx;
31+
struct smc_clc_msg_accept_confirm *clc;
32+
struct smc_clc_msg_proposal *pclc;
33+
struct smc_clc_msg_decline *dclc;
34+
struct smc_clc_msg_trail *trl;
35+
36+
if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)))
37+
return false;
38+
switch (clcm->type) {
39+
case SMC_CLC_PROPOSAL:
40+
pclc = (struct smc_clc_msg_proposal *)clcm;
41+
pclc_prfx = smc_clc_proposal_get_prefix(pclc);
42+
if (ntohs(pclc->hdr.length) !=
43+
sizeof(*pclc) + ntohs(pclc->iparea_offset) +
44+
sizeof(*pclc_prfx) +
45+
pclc_prfx->ipv6_prefixes_cnt *
46+
sizeof(struct smc_clc_ipv6_prefix) +
47+
sizeof(*trl))
48+
return false;
49+
trl = (struct smc_clc_msg_trail *)
50+
((u8 *)pclc + ntohs(pclc->hdr.length) - sizeof(*trl));
51+
break;
52+
case SMC_CLC_ACCEPT:
53+
case SMC_CLC_CONFIRM:
54+
clc = (struct smc_clc_msg_accept_confirm *)clcm;
55+
if (ntohs(clc->hdr.length) != sizeof(*clc))
56+
return false;
57+
trl = &clc->trl;
58+
break;
59+
case SMC_CLC_DECLINE:
60+
dclc = (struct smc_clc_msg_decline *)clcm;
61+
if (ntohs(dclc->hdr.length) != sizeof(*dclc))
62+
return false;
63+
trl = &dclc->trl;
64+
break;
65+
default:
66+
return false;
67+
}
68+
if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)))
69+
return false;
70+
return true;
71+
}
72+
2573
/* Wait for data on the tcp-socket, analyze received data
2674
* Returns:
2775
* 0 if success and it was not a decline that we received.
@@ -72,9 +120,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
72120
}
73121
datlen = ntohs(clcm->length);
74122
if ((len < sizeof(struct smc_clc_msg_hdr)) ||
75-
(datlen < sizeof(struct smc_clc_msg_decline)) ||
76-
(datlen > sizeof(struct smc_clc_msg_accept_confirm)) ||
77-
memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) ||
123+
(datlen > buflen) ||
78124
((clcm->type != SMC_CLC_DECLINE) &&
79125
(clcm->type != expected_type))) {
80126
smc->sk.sk_err = EPROTO;
@@ -89,7 +135,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
89135
krflags = MSG_WAITALL;
90136
smc->clcsock->sk->sk_rcvtimeo = CLC_WAIT_TIME;
91137
len = kernel_recvmsg(smc->clcsock, &msg, &vec, 1, datlen, krflags);
92-
if (len < datlen) {
138+
if (len < datlen || !smc_clc_msg_hdr_valid(clcm)) {
93139
smc->sk.sk_err = EPROTO;
94140
reason_code = -EPROTO;
95141
goto out;
@@ -133,41 +179,51 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
133179
smc->sk.sk_err = EPROTO;
134180
if (len < 0)
135181
smc->sk.sk_err = -len;
136-
return len;
182+
return sock_error(&smc->sk);
137183
}
138184

139185
/* send CLC PROPOSAL message across internal TCP socket */
140186
int smc_clc_send_proposal(struct smc_sock *smc,
141187
struct smc_ib_device *smcibdev,
142188
u8 ibport)
143189
{
190+
struct smc_clc_msg_proposal_prefix pclc_prfx;
144191
struct smc_clc_msg_proposal pclc;
192+
struct smc_clc_msg_trail trl;
145193
int reason_code = 0;
194+
struct kvec vec[3];
146195
struct msghdr msg;
147-
struct kvec vec;
148-
int len, rc;
196+
int len, plen, rc;
149197

150198
/* send SMC Proposal CLC message */
199+
plen = sizeof(pclc) + sizeof(pclc_prfx) + sizeof(trl);
151200
memset(&pclc, 0, sizeof(pclc));
152201
memcpy(pclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
153202
pclc.hdr.type = SMC_CLC_PROPOSAL;
154-
pclc.hdr.length = htons(sizeof(pclc));
203+
pclc.hdr.length = htons(plen);
155204
pclc.hdr.version = SMC_CLC_V1; /* SMC version */
156205
memcpy(pclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid));
157206
memcpy(&pclc.lcl.gid, &smcibdev->gid[ibport - 1], SMC_GID_SIZE);
158207
memcpy(&pclc.lcl.mac, &smcibdev->mac[ibport - 1], ETH_ALEN);
208+
pclc.iparea_offset = htons(0);
159209

210+
memset(&pclc_prfx, 0, sizeof(pclc_prfx));
160211
/* determine subnet and mask from internal TCP socket */
161-
rc = smc_netinfo_by_tcpsk(smc->clcsock, &pclc.outgoing_subnet,
162-
&pclc.prefix_len);
212+
rc = smc_netinfo_by_tcpsk(smc->clcsock, &pclc_prfx.outgoing_subnet,
213+
&pclc_prfx.prefix_len);
163214
if (rc)
164215
return SMC_CLC_DECL_CNFERR; /* configuration error */
165-
memcpy(pclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
216+
pclc_prfx.ipv6_prefixes_cnt = 0;
217+
memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
166218
memset(&msg, 0, sizeof(msg));
167-
vec.iov_base = &pclc;
168-
vec.iov_len = sizeof(pclc);
219+
vec[0].iov_base = &pclc;
220+
vec[0].iov_len = sizeof(pclc);
221+
vec[1].iov_base = &pclc_prfx;
222+
vec[1].iov_len = sizeof(pclc_prfx);
223+
vec[2].iov_base = &trl;
224+
vec[2].iov_len = sizeof(trl);
169225
/* due to the few bytes needed for clc-handshake this cannot block */
170-
len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, sizeof(pclc));
226+
len = kernel_sendmsg(smc->clcsock, &msg, vec, 3, plen);
171227
if (len < sizeof(pclc)) {
172228
if (len >= 0) {
173229
reason_code = -ENETUNREACH;

net/smc/smc_clc.h

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ struct smc_clc_msg_hdr { /* header1 of clc messages */
4444
#if defined(__BIG_ENDIAN_BITFIELD)
4545
u8 version : 4,
4646
flag : 1,
47-
rsvd : 3;
47+
rsvd : 3;
4848
#elif defined(__LITTLE_ENDIAN_BITFIELD)
4949
u8 rsvd : 3,
5050
flag : 1,
@@ -62,17 +62,31 @@ struct smc_clc_msg_local { /* header2 of clc messages */
6262
u8 mac[6]; /* mac of ib_device port */
6363
};
6464

65-
struct smc_clc_msg_proposal { /* clc proposal message */
66-
struct smc_clc_msg_hdr hdr;
67-
struct smc_clc_msg_local lcl;
68-
__be16 iparea_offset; /* offset to IP address information area */
65+
struct smc_clc_ipv6_prefix {
66+
u8 prefix[4];
67+
u8 prefix_len;
68+
} __packed;
69+
70+
struct smc_clc_msg_proposal_prefix { /* prefix part of clc proposal message*/
6971
__be32 outgoing_subnet; /* subnet mask */
7072
u8 prefix_len; /* number of significant bits in mask */
7173
u8 reserved[2];
7274
u8 ipv6_prefixes_cnt; /* number of IPv6 prefixes in prefix array */
73-
struct smc_clc_msg_trail trl; /* eye catcher "SMCR" EBCDIC */
7475
} __aligned(4);
7576

77+
struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */
78+
struct smc_clc_msg_hdr hdr;
79+
struct smc_clc_msg_local lcl;
80+
__be16 iparea_offset; /* offset to IP address information area */
81+
} __aligned(4);
82+
83+
#define SMC_CLC_PROPOSAL_MAX_OFFSET 0x28
84+
#define SMC_CLC_PROPOSAL_MAX_PREFIX (8 * sizeof(struct smc_clc_ipv6_prefix))
85+
#define SMC_CLC_MAX_LEN (sizeof(struct smc_clc_msg_proposal) + \
86+
SMC_CLC_PROPOSAL_MAX_OFFSET + \
87+
SMC_CLC_PROPOSAL_MAX_PREFIX + \
88+
sizeof(struct smc_clc_msg_trail))
89+
7690
struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */
7791
struct smc_clc_msg_hdr hdr;
7892
struct smc_clc_msg_local lcl;
@@ -102,6 +116,14 @@ struct smc_clc_msg_decline { /* clc decline message */
102116
struct smc_clc_msg_trail trl; /* eye catcher "SMCR" EBCDIC */
103117
} __aligned(4);
104118

119+
/* determine start of the prefix area within the proposal message */
120+
static inline struct smc_clc_msg_proposal_prefix *
121+
smc_clc_proposal_get_prefix(struct smc_clc_msg_proposal *pclc)
122+
{
123+
return (struct smc_clc_msg_proposal_prefix *)
124+
((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset));
125+
}
126+
105127
struct smc_sock;
106128
struct smc_ib_device;
107129

net/smc/smc_close.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ static int smc_close_abort(struct smc_connection *conn)
113113
/* terminate smc socket abnormally - active abort
114114
* RDMA communication no longer possible
115115
*/
116-
void smc_close_active_abort(struct smc_sock *smc)
116+
static void smc_close_active_abort(struct smc_sock *smc)
117117
{
118118
struct smc_cdc_conn_state_flags *txflags =
119119
&smc->conn.local_tx_ctrl.conn_state_flags;

net/smc/smc_close.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#define SMC_CLOSE_SOCK_PUT_DELAY HZ
2121

2222
void smc_close_wake_tx_prepared(struct smc_sock *smc);
23-
void smc_close_active_abort(struct smc_sock *smc);
2423
int smc_close_active(struct smc_sock *smc);
2524
void smc_close_sock_put_work(struct work_struct *work);
2625
int smc_close_shutdown_write(struct smc_sock *smc);

net/smc/smc_rx.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ static int smc_rx_wait_data(struct smc_sock *smc, long *timeo)
6565
rc = sk_wait_event(sk, timeo,
6666
sk->sk_err ||
6767
sk->sk_shutdown & RCV_SHUTDOWN ||
68-
sock_flag(sk, SOCK_DONE) ||
6968
atomic_read(&conn->bytes_to_rcv) ||
7069
smc_cdc_rxed_any_close_or_senddone(conn),
7170
&wait);
@@ -116,16 +115,14 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg, size_t len,
116115
if (read_done) {
117116
if (sk->sk_err ||
118117
sk->sk_state == SMC_CLOSED ||
119-
(sk->sk_shutdown & RCV_SHUTDOWN) ||
118+
sk->sk_shutdown & RCV_SHUTDOWN ||
120119
!timeo ||
121120
signal_pending(current) ||
122121
smc_cdc_rxed_any_close_or_senddone(conn) ||
123122
conn->local_tx_ctrl.conn_state_flags.
124123
peer_conn_abort)
125124
break;
126125
} else {
127-
if (sock_flag(sk, SOCK_DONE))
128-
break;
129126
if (sk->sk_err) {
130127
read_done = sock_error(sk);
131128
break;

net/smc/smc_tx.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,12 @@ static int smc_tx_wait_memory(struct smc_sock *smc, int flags)
104104
if (atomic_read(&conn->sndbuf_space))
105105
break; /* at least 1 byte of free space available */
106106
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
107-
sk->sk_write_pending++;
108107
sk_wait_event(sk, &timeo,
109108
sk->sk_err ||
110109
(sk->sk_shutdown & SEND_SHUTDOWN) ||
111110
smc_cdc_rxed_any_close_or_senddone(conn) ||
112111
atomic_read(&conn->sndbuf_space),
113112
&wait);
114-
sk->sk_write_pending--;
115113
}
116114
remove_wait_queue(sk_sleep(sk), &wait);
117115
return rc;
@@ -450,9 +448,7 @@ static void smc_tx_work(struct work_struct *work)
450448
void smc_tx_consumer_update(struct smc_connection *conn)
451449
{
452450
union smc_host_cursor cfed, cons;
453-
struct smc_cdc_tx_pend *pend;
454-
struct smc_wr_buf *wr_buf;
455-
int to_confirm, rc;
451+
int to_confirm;
456452

457453
smc_curs_write(&cons,
458454
smc_curs_read(&conn->local_tx_ctrl.cons, conn),
@@ -466,10 +462,7 @@ void smc_tx_consumer_update(struct smc_connection *conn)
466462
((to_confirm > conn->rmbe_update_limit) &&
467463
((to_confirm > (conn->rmbe_size / 2)) ||
468464
conn->local_rx_ctrl.prod_flags.write_blocked))) {
469-
rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend);
470-
if (!rc)
471-
rc = smc_cdc_msg_send(conn, wr_buf, pend);
472-
if (rc < 0) {
465+
if (smc_cdc_get_slot_and_msg_send(conn) < 0) {
473466
schedule_delayed_work(&conn->tx_work,
474467
SMC_TX_WORK_DELAY);
475468
return;

0 commit comments

Comments
 (0)