Blame view
net/smc/smc_cdc.c
13.6 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
5f08318f6 smc: connection d... |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Shared Memory Communications over RDMA (SMC-R) and RoCE * * Connection Data Control (CDC) * handles flow control * * Copyright IBM Corp. 2016 * * Author(s): Ursula Braun <ubraun@linux.vnet.ibm.com> */ #include <linux/spinlock.h> #include "smc.h" #include "smc_wr.h" #include "smc_cdc.h" |
e6727f390 smc: send data (t... |
18 |
#include "smc_tx.h" |
952310ccf smc: receive data... |
19 |
#include "smc_rx.h" |
b38d73247 smc: socket closi... |
20 |
#include "smc_close.h" |
5f08318f6 smc: connection d... |
21 22 |
/********************************** send *************************************/ |
5f08318f6 smc: connection d... |
23 24 25 26 27 28 |
/* handler for send/transmission completion of a CDC msg */ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd, struct smc_link *link, enum ib_wc_status wc_status) { struct smc_cdc_tx_pend *cdcpend = (struct smc_cdc_tx_pend *)pnd_snd; |
bac6de7b6 net/smc: eliminat... |
29 |
struct smc_connection *conn = cdcpend->conn; |
5f08318f6 smc: connection d... |
30 31 |
struct smc_sock *smc; int diff; |
bac6de7b6 net/smc: eliminat... |
32 |
if (!conn) |
5f08318f6 smc: connection d... |
33 34 |
/* already dismissed */ return; |
bac6de7b6 net/smc: eliminat... |
35 |
smc = container_of(conn, struct smc_sock, conn); |
5f08318f6 smc: connection d... |
36 37 |
bh_lock_sock(&smc->sk); if (!wc_status) { |
69cb7dc02 net/smc: add comm... |
38 |
diff = smc_curs_diff(cdcpend->conn->sndbuf_desc->len, |
5f08318f6 smc: connection d... |
39 40 41 42 43 |
&cdcpend->conn->tx_curs_fin, &cdcpend->cursor); /* sndbuf_space is decreased in smc_sendmsg */ smp_mb__before_atomic(); atomic_add(diff, &cdcpend->conn->sndbuf_space); |
69cb7dc02 net/smc: add comm... |
44 |
/* guarantee 0 <= sndbuf_space <= sndbuf_desc->len */ |
5f08318f6 smc: connection d... |
45 |
smp_mb__after_atomic(); |
bac6de7b6 net/smc: eliminat... |
46 |
smc_curs_copy(&conn->tx_curs_fin, &cdcpend->cursor, conn); |
f0ec4f1d3 net/smc: save sta... |
47 48 49 |
smc_curs_copy(&conn->local_tx_ctrl_fin, &cdcpend->p_cursor, conn); conn->tx_cdc_seq_fin = cdcpend->ctrl_seq; |
5f08318f6 smc: connection d... |
50 |
} |
e6727f390 smc: send data (t... |
51 |
smc_tx_sndbuf_nonfull(smc); |
5f08318f6 smc: connection d... |
52 53 |
bh_unlock_sock(&smc->sk); } |
51957bc53 net/smc: paramete... |
54 |
int smc_cdc_get_free_slot(struct smc_connection *conn, |
c6f02ebee net/smc: switch c... |
55 |
struct smc_link *link, |
5f08318f6 smc: connection d... |
56 |
struct smc_wr_buf **wr_buf, |
ad6f317f7 net/smc: prealloc... |
57 |
struct smc_rdma_wr **wr_rdma_buf, |
5f08318f6 smc: connection d... |
58 59 |
struct smc_cdc_tx_pend **pend) { |
1a0a04c7a net/smc: check fo... |
60 |
int rc; |
51957bc53 net/smc: paramete... |
61 |
|
1a0a04c7a net/smc: check fo... |
62 |
rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf, |
ad6f317f7 net/smc: prealloc... |
63 |
wr_rdma_buf, |
1a0a04c7a net/smc: check fo... |
64 |
(struct smc_wr_tx_pend_priv **)pend); |
2bced6aef net/smc: put slot... |
65 |
if (conn->killed) { |
1a0a04c7a net/smc: check fo... |
66 |
/* abnormal termination */ |
2bced6aef net/smc: put slot... |
67 68 69 |
if (!rc) smc_wr_tx_put_slot(link, (struct smc_wr_tx_pend_priv *)pend); |
1a0a04c7a net/smc: check fo... |
70 |
rc = -EPIPE; |
2bced6aef net/smc: put slot... |
71 |
} |
1a0a04c7a net/smc: check fo... |
72 |
return rc; |
5f08318f6 smc: connection d... |
73 74 75 76 77 78 79 80 81 |
} static inline void smc_cdc_add_pending_send(struct smc_connection *conn, struct smc_cdc_tx_pend *pend) { BUILD_BUG_ON_MSG( sizeof(struct smc_cdc_msg) > SMC_WR_BUF_SIZE, "must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_cdc_msg)"); BUILD_BUG_ON_MSG( |
b9a22dd98 net/smc: atomic S... |
82 |
offsetofend(struct smc_cdc_msg, reserved) > SMC_WR_TX_SIZE, |
5f08318f6 smc: connection d... |
83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
"must adapt SMC_WR_TX_SIZE to sizeof(struct smc_cdc_msg); if not all smc_wr upper layer protocols use the same message size any more, must start to set link->wr_tx_sges[i].length on each individual smc_wr_tx_send()"); BUILD_BUG_ON_MSG( sizeof(struct smc_cdc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE, "must increase SMC_WR_TX_PEND_PRIV_SIZE to at least sizeof(struct smc_cdc_tx_pend)"); pend->conn = conn; pend->cursor = conn->tx_curs_sent; pend->p_cursor = conn->local_tx_ctrl.prod; pend->ctrl_seq = conn->tx_cdc_seq; } int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf, struct smc_cdc_tx_pend *pend) { |
387707fdf net/smc: convert ... |
97 |
struct smc_link *link = conn->lnk; |
b8649efad net/smc: fix send... |
98 |
union smc_host_cursor cfed; |
5f08318f6 smc: connection d... |
99 |
int rc; |
5f08318f6 smc: connection d... |
100 101 102 103 |
smc_cdc_add_pending_send(conn, pend); conn->tx_cdc_seq++; conn->local_tx_ctrl.seqno = conn->tx_cdc_seq; |
ccc8ca9b9 net/smc: fix byte... |
104 |
smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf, conn, &cfed); |
5f08318f6 smc: connection d... |
105 |
rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend); |
4dff63c25 net/smc: reset cu... |
106 |
if (!rc) { |
b8649efad net/smc: fix send... |
107 |
smc_curs_copy(&conn->rx_curs_confirmed, &cfed, conn); |
4dff63c25 net/smc: reset cu... |
108 |
conn->local_rx_ctrl.prod_flags.cons_curs_upd_req = 0; |
f0ec4f1d3 net/smc: save sta... |
109 110 111 |
} else { conn->tx_cdc_seq--; conn->local_tx_ctrl.seqno = conn->tx_cdc_seq; |
4dff63c25 net/smc: reset cu... |
112 |
} |
5f08318f6 smc: connection d... |
113 114 115 |
return rc; } |
29bd73dba net/smc: send fai... |
116 |
/* send a validation msg indicating the move of a conn to an other QP link */ |
b8ded9de8 net/smc: pre-fetc... |
117 118 119 |
int smcr_cdc_msg_send_validation(struct smc_connection *conn, struct smc_cdc_tx_pend *pend, struct smc_wr_buf *wr_buf) |
29bd73dba net/smc: send fai... |
120 121 122 |
{ struct smc_host_cdc_msg *local = &conn->local_tx_ctrl; struct smc_link *link = conn->lnk; |
29bd73dba net/smc: send fai... |
123 124 |
struct smc_cdc_msg *peer; int rc; |
29bd73dba net/smc: send fai... |
125 126 127 128 129 130 131 132 133 134 |
peer = (struct smc_cdc_msg *)wr_buf; peer->common.type = local->common.type; peer->len = local->len; peer->seqno = htons(conn->tx_cdc_seq_fin); /* seqno last compl. tx */ peer->token = htonl(local->token); peer->prod_flags.failover_validation = 1; rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend); return rc; } |
be244f28d net/smc: add SMC-... |
135 |
static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn) |
5f08318f6 smc: connection d... |
136 137 138 |
{ struct smc_cdc_tx_pend *pend; struct smc_wr_buf *wr_buf; |
c6f02ebee net/smc: switch c... |
139 140 |
struct smc_link *link; bool again = false; |
5f08318f6 smc: connection d... |
141 |
int rc; |
c6f02ebee net/smc: switch c... |
142 143 144 |
again: link = conn->lnk; rc = smc_cdc_get_free_slot(conn, link, &wr_buf, NULL, &pend); |
5f08318f6 smc: connection d... |
145 146 |
if (rc) return rc; |
2dee25af4 net/smc: call smc... |
147 |
spin_lock_bh(&conn->send_lock); |
c6f02ebee net/smc: switch c... |
148 149 150 151 152 153 154 155 156 157 |
if (link != conn->lnk) { /* link of connection changed, try again one time*/ spin_unlock_bh(&conn->send_lock); smc_wr_tx_put_slot(link, (struct smc_wr_tx_pend_priv *)pend); if (again) return -ENOLINK; again = true; goto again; } |
2dee25af4 net/smc: call smc... |
158 159 160 |
rc = smc_cdc_msg_send(conn, wr_buf, pend); spin_unlock_bh(&conn->send_lock); return rc; |
5f08318f6 smc: connection d... |
161 |
} |
be244f28d net/smc: add SMC-... |
162 163 164 |
int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn) { int rc; |
50c6b20ef net/smc: fix fina... |
165 166 |
if (!conn->lgr || (conn->lgr->is_smcd && conn->lgr->peer_shutdown)) return -EPIPE; |
be244f28d net/smc: add SMC-... |
167 168 169 170 171 172 173 174 175 176 |
if (conn->lgr->is_smcd) { spin_lock_bh(&conn->send_lock); rc = smcd_cdc_msg_send(conn); spin_unlock_bh(&conn->send_lock); } else { rc = smcr_cdc_get_slot_and_msg_send(conn); } return rc; } |
5f08318f6 smc: connection d... |
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
static bool smc_cdc_tx_filter(struct smc_wr_tx_pend_priv *tx_pend, unsigned long data) { struct smc_connection *conn = (struct smc_connection *)data; struct smc_cdc_tx_pend *cdc_pend = (struct smc_cdc_tx_pend *)tx_pend; return cdc_pend->conn == conn; } static void smc_cdc_tx_dismisser(struct smc_wr_tx_pend_priv *tx_pend) { struct smc_cdc_tx_pend *cdc_pend = (struct smc_cdc_tx_pend *)tx_pend; cdc_pend->conn = NULL; } void smc_cdc_tx_dismiss_slots(struct smc_connection *conn) { |
387707fdf net/smc: convert ... |
197 |
struct smc_link *link = conn->lnk; |
5f08318f6 smc: connection d... |
198 199 200 201 202 |
smc_wr_tx_dismiss_slots(link, SMC_CDC_MSG_TYPE, smc_cdc_tx_filter, smc_cdc_tx_dismisser, (unsigned long)conn); } |
be244f28d net/smc: add SMC-... |
203 204 205 206 207 208 209 |
/* Send a SMC-D CDC header. * This increments the free space available in our send buffer. * Also update the confirmed receive buffer with what was sent to the peer. */ int smcd_cdc_msg_send(struct smc_connection *conn) { struct smc_sock *smc = container_of(conn, struct smc_sock, conn); |
b9a22dd98 net/smc: atomic S... |
210 |
union smc_host_cursor curs; |
be244f28d net/smc: add SMC-... |
211 212 213 214 215 |
struct smcd_cdc_msg cdc; int rc, diff; memset(&cdc, 0, sizeof(cdc)); cdc.common.type = SMC_CDC_MSG_TYPE; |
b9a22dd98 net/smc: atomic S... |
216 217 218 219 220 221 222 223 |
curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.prod.acurs); cdc.prod.wrap = curs.wrap; cdc.prod.count = curs.count; curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.cons.acurs); cdc.cons.wrap = curs.wrap; cdc.cons.count = curs.count; cdc.cons.prod_flags = conn->local_tx_ctrl.prod_flags; cdc.cons.conn_state_flags = conn->local_tx_ctrl.conn_state_flags; |
be244f28d net/smc: add SMC-... |
224 225 226 |
rc = smcd_tx_ism_write(conn, &cdc, sizeof(cdc), 0, 1); if (rc) return rc; |
b9a22dd98 net/smc: atomic S... |
227 |
smc_curs_copy(&conn->rx_curs_confirmed, &curs, conn); |
4dff63c25 net/smc: reset cu... |
228 |
conn->local_rx_ctrl.prod_flags.cons_curs_upd_req = 0; |
be244f28d net/smc: add SMC-... |
229 230 231 232 233 234 235 236 |
/* Calculate transmitted data and increment free send buffer space */ diff = smc_curs_diff(conn->sndbuf_desc->len, &conn->tx_curs_fin, &conn->tx_curs_sent); /* increased by confirmed number of bytes */ smp_mb__before_atomic(); atomic_add(diff, &conn->sndbuf_space); /* guarantee 0 <= sndbuf_space <= sndbuf_desc->len */ smp_mb__after_atomic(); |
bac6de7b6 net/smc: eliminat... |
237 |
smc_curs_copy(&conn->tx_curs_fin, &conn->tx_curs_sent, conn); |
be244f28d net/smc: add SMC-... |
238 239 240 241 |
smc_tx_sndbuf_nonfull(smc); return rc; } |
5f08318f6 smc: connection d... |
242 243 244 245 246 247 |
/********************************* receive ***********************************/ static inline bool smc_cdc_before(u16 seq1, u16 seq2) { return (s16)(seq1 - seq2) < 0; } |
de8474eb9 net/smc: urgent d... |
248 249 250 251 252 253 254 |
static void smc_cdc_handle_urg_data_arrival(struct smc_sock *smc, int *diff_prod) { struct smc_connection *conn = &smc->conn; char *base; /* new data included urgent business */ |
bac6de7b6 net/smc: eliminat... |
255 |
smc_curs_copy(&conn->urg_curs, &conn->local_rx_ctrl.prod, conn); |
de8474eb9 net/smc: urgent d... |
256 257 258 259 |
conn->urg_state = SMC_URG_VALID; if (!sock_flag(&smc->sk, SOCK_URGINLINE)) /* we'll skip the urgent byte, so don't account for it */ (*diff_prod)--; |
be244f28d net/smc: add SMC-... |
260 |
base = (char *)conn->rmb_desc->cpu_addr + conn->rx_off; |
de8474eb9 net/smc: urgent d... |
261 262 263 264 265 266 |
if (conn->urg_curs.count) conn->urg_rx_byte = *(base + conn->urg_curs.count - 1); else conn->urg_rx_byte = *(base + conn->rmb_desc->len - 1); sk_send_sigurg(&smc->sk); } |
b286a0651 net/smc: handle i... |
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
static void smc_cdc_msg_validate(struct smc_sock *smc, struct smc_cdc_msg *cdc, struct smc_link *link) { struct smc_connection *conn = &smc->conn; u16 recv_seq = ntohs(cdc->seqno); s16 diff; /* check that seqnum was seen before */ diff = conn->local_rx_ctrl.seqno - recv_seq; if (diff < 0) { /* diff larger than 0x7fff */ /* drop connection */ conn->out_of_sync = 1; /* prevent any further receives */ spin_lock_bh(&conn->send_lock); conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; conn->lnk = link; spin_unlock_bh(&conn->send_lock); sock_hold(&smc->sk); /* sock_put in abort_work */ |
22ef473db net/smc: use sepa... |
284 |
if (!queue_work(smc_close_wq, &conn->abort_work)) |
b286a0651 net/smc: handle i... |
285 286 287 |
sock_put(&smc->sk); } } |
5f08318f6 smc: connection d... |
288 |
static void smc_cdc_msg_recv_action(struct smc_sock *smc, |
5f08318f6 smc: connection d... |
289 290 291 292 293 |
struct smc_cdc_msg *cdc) { union smc_host_cursor cons_old, prod_old; struct smc_connection *conn = &smc->conn; int diff_cons, diff_prod; |
bac6de7b6 net/smc: eliminat... |
294 295 |
smc_curs_copy(&prod_old, &conn->local_rx_ctrl.prod, conn); smc_curs_copy(&cons_old, &conn->local_rx_ctrl.cons, conn); |
5f08318f6 smc: connection d... |
296 297 298 299 300 301 302 303 304 305 306 307 308 |
smc_cdc_msg_to_host(&conn->local_rx_ctrl, cdc, conn); diff_cons = smc_curs_diff(conn->peer_rmbe_size, &cons_old, &conn->local_rx_ctrl.cons); if (diff_cons) { /* peer_rmbe_space is decreased during data transfer with RDMA * write */ smp_mb__before_atomic(); atomic_add(diff_cons, &conn->peer_rmbe_space); /* guarantee 0 <= peer_rmbe_space <= peer_rmbe_size */ smp_mb__after_atomic(); } |
69cb7dc02 net/smc: add comm... |
309 |
diff_prod = smc_curs_diff(conn->rmb_desc->len, &prod_old, |
5f08318f6 smc: connection d... |
310 311 |
&conn->local_rx_ctrl.prod); if (diff_prod) { |
de8474eb9 net/smc: urgent d... |
312 313 |
if (conn->local_rx_ctrl.prod_flags.urg_data_present) smc_cdc_handle_urg_data_arrival(smc, &diff_prod); |
5f08318f6 smc: connection d... |
314 315 316 |
/* bytes_to_rcv is decreased in smc_recvmsg */ smp_mb__before_atomic(); atomic_add(diff_prod, &conn->bytes_to_rcv); |
69cb7dc02 net/smc: add comm... |
317 |
/* guarantee 0 <= bytes_to_rcv <= rmb_desc->len */ |
5f08318f6 smc: connection d... |
318 |
smp_mb__after_atomic(); |
952310ccf smc: receive data... |
319 |
smc->sk.sk_data_ready(&smc->sk); |
de8474eb9 net/smc: urgent d... |
320 |
} else { |
cf0cfe535 net/smc: reduce a... |
321 322 323 324 |
if (conn->local_rx_ctrl.prod_flags.write_blocked) smc->sk.sk_data_ready(&smc->sk); if (conn->local_rx_ctrl.prod_flags.urg_data_pending) conn->urg_state = SMC_URG_NOTYET; |
5f08318f6 smc: connection d... |
325 |
} |
51f1de79a net/smc: replace ... |
326 |
/* trigger sndbuf consumer: RDMA write into peer RMBE and CDC */ |
cf0cfe535 net/smc: reduce a... |
327 328 329 |
if ((diff_cons && smc_tx_prepared_sends(conn)) || conn->local_rx_ctrl.prod_flags.cons_curs_upd_req || conn->local_rx_ctrl.prod_flags.urg_data_pending) |
51f1de79a net/smc: replace ... |
330 |
smc_tx_sndbuf_nonempty(conn); |
cf0cfe535 net/smc: reduce a... |
331 |
|
de8474eb9 net/smc: urgent d... |
332 333 334 335 336 337 |
if (diff_cons && conn->urg_tx_pend && atomic_read(&conn->peer_rmbe_space) == conn->peer_rmbe_size) { /* urg data confirmed by peer, indicate we're ready for more */ conn->urg_tx_pend = false; smc->sk.sk_write_space(&smc->sk); } |
51f1de79a net/smc: replace ... |
338 |
|
b38d73247 smc: socket closi... |
339 |
if (conn->local_rx_ctrl.conn_state_flags.peer_conn_abort) { |
5f08318f6 smc: connection d... |
340 |
smc->sk.sk_err = ECONNRESET; |
b38d73247 smc: socket closi... |
341 342 |
conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1; } |
46c28dbd4 net/smc: no socke... |
343 344 345 346 347 |
if (smc_cdc_rxed_any_close_or_senddone(conn)) { smc->sk.sk_shutdown |= RCV_SHUTDOWN; if (smc->clcsock && smc->clcsock->sk) smc->clcsock->sk->sk_shutdown |= RCV_SHUTDOWN; sock_set_flag(&smc->sk, SOCK_DONE); |
51f1de79a net/smc: replace ... |
348 |
sock_hold(&smc->sk); /* sock_put in close_work */ |
22ef473db net/smc: use sepa... |
349 |
if (!queue_work(smc_close_wq, &conn->close_work)) |
51f1de79a net/smc: replace ... |
350 |
sock_put(&smc->sk); |
b38d73247 smc: socket closi... |
351 |
} |
5f08318f6 smc: connection d... |
352 353 354 |
} /* called under tasklet context */ |
d7b0e37c1 net/smc: restruct... |
355 |
static void smc_cdc_msg_recv(struct smc_sock *smc, struct smc_cdc_msg *cdc) |
5f08318f6 smc: connection d... |
356 |
{ |
5f08318f6 smc: connection d... |
357 |
sock_hold(&smc->sk); |
5f08318f6 smc: connection d... |
358 |
bh_lock_sock(&smc->sk); |
d7b0e37c1 net/smc: restruct... |
359 |
smc_cdc_msg_recv_action(smc, cdc); |
5f08318f6 smc: connection d... |
360 361 362 |
bh_unlock_sock(&smc->sk); sock_put(&smc->sk); /* no free sk in softirq-context */ } |
be244f28d net/smc: add SMC-... |
363 364 365 366 367 368 369 370 371 |
/* Schedule a tasklet for this connection. Triggered from the ISM device IRQ * handler to indicate update in the DMBE. * * Context: * - tasklet context */ static void smcd_cdc_rx_tsklet(unsigned long data) { struct smc_connection *conn = (struct smc_connection *)data; |
b9a22dd98 net/smc: atomic S... |
372 |
struct smcd_cdc_msg *data_cdc; |
be244f28d net/smc: add SMC-... |
373 374 |
struct smcd_cdc_msg cdc; struct smc_sock *smc; |
b29009809 net/smc: cancel s... |
375 |
if (!conn || conn->killed) |
be244f28d net/smc: add SMC-... |
376 |
return; |
b9a22dd98 net/smc: atomic S... |
377 378 379 |
data_cdc = (struct smcd_cdc_msg *)conn->rmb_desc->cpu_addr; smcd_curs_copy(&cdc.prod, &data_cdc->prod, conn); smcd_curs_copy(&cdc.cons, &data_cdc->cons, conn); |
be244f28d net/smc: add SMC-... |
380 381 382 383 384 385 386 387 388 389 390 |
smc = container_of(conn, struct smc_sock, conn); smc_cdc_msg_recv(smc, (struct smc_cdc_msg *)&cdc); } /* Initialize receive tasklet. Called from ISM device IRQ handler to start * receiver side. */ void smcd_cdc_rx_init(struct smc_connection *conn) { tasklet_init(&conn->rx_tsklet, smcd_cdc_rx_tsklet, (unsigned long)conn); } |
5f08318f6 smc: connection d... |
391 392 393 394 395 396 |
/***************************** init, exit, misc ******************************/ static void smc_cdc_rx_handler(struct ib_wc *wc, void *buf) { struct smc_link *link = (struct smc_link *)wc->qp->qp_context; struct smc_cdc_msg *cdc = buf; |
d7b0e37c1 net/smc: restruct... |
397 398 399 |
struct smc_connection *conn; struct smc_link_group *lgr; struct smc_sock *smc; |
5f08318f6 smc: connection d... |
400 401 402 |
if (wc->byte_len < offsetof(struct smc_cdc_msg, reserved)) return; /* short message */ |
cbba07a72 net/smc: use a co... |
403 |
if (cdc->len != SMC_WR_TX_SIZE) |
5f08318f6 smc: connection d... |
404 |
return; /* invalid message */ |
d7b0e37c1 net/smc: restruct... |
405 406 |
/* lookup connection */ |
00e5fb263 net/smc: add func... |
407 |
lgr = smc_get_lgr(link); |
d7b0e37c1 net/smc: restruct... |
408 409 410 |
read_lock_bh(&lgr->conns_lock); conn = smc_lgr_find_conn(ntohl(cdc->token), lgr); read_unlock_bh(&lgr->conns_lock); |
b286a0651 net/smc: handle i... |
411 |
if (!conn || conn->out_of_sync) |
d7b0e37c1 net/smc: restruct... |
412 413 |
return; smc = container_of(conn, struct smc_sock, conn); |
b286a0651 net/smc: handle i... |
414 415 416 |
if (cdc->prod_flags.failover_validation) { smc_cdc_msg_validate(smc, cdc, link); return; |
d7b0e37c1 net/smc: restruct... |
417 |
} |
b286a0651 net/smc: handle i... |
418 419 420 421 |
if (smc_cdc_before(ntohs(cdc->seqno), conn->local_rx_ctrl.seqno)) /* received seqno is old */ return; |
d7b0e37c1 net/smc: restruct... |
422 |
smc_cdc_msg_recv(smc, cdc); |
5f08318f6 smc: connection d... |
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 |
} static struct smc_wr_rx_handler smc_cdc_rx_handlers[] = { { .handler = smc_cdc_rx_handler, .type = SMC_CDC_MSG_TYPE }, { .handler = NULL, } }; int __init smc_cdc_init(void) { struct smc_wr_rx_handler *handler; int rc = 0; for (handler = smc_cdc_rx_handlers; handler->handler; handler++) { INIT_HLIST_NODE(&handler->list); rc = smc_wr_rx_register_handler(handler); if (rc) break; } return rc; } |