Skip to content

Commit de8474e

Browse files
Stefan Raspldavem330
authored andcommitted
net/smc: urgent data support
Add support for out of band data send and receive. Signed-off-by: Stefan Raspl <[email protected]> Signed-off-by: Ursula Braun <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b9f227c commit de8474e

File tree

8 files changed

+238
-36
lines changed

8 files changed

+238
-36
lines changed

net/smc/af_smc.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
*
99
* Initial restrictions:
1010
* - support for alternate links postponed
11-
* - partial support for non-blocking sockets only
12-
* - support for urgent data postponed
1311
*
1412
* Copyright IBM Corp. 2016, 2018
1513
*
@@ -1338,6 +1336,8 @@ static __poll_t smc_poll(struct file *file, struct socket *sock,
13381336
if (sk->sk_state == SMC_APPCLOSEWAIT1)
13391337
mask |= EPOLLIN;
13401338
}
1339+
if (smc->conn.urg_state == SMC_URG_VALID)
1340+
mask |= EPOLLPRI;
13411341

13421342
}
13431343
release_sock(sk);
@@ -1477,10 +1477,13 @@ static int smc_getsockopt(struct socket *sock, int level, int optname,
14771477
static int smc_ioctl(struct socket *sock, unsigned int cmd,
14781478
unsigned long arg)
14791479
{
1480+
union smc_host_cursor cons, urg;
1481+
struct smc_connection *conn;
14801482
struct smc_sock *smc;
14811483
int answ;
14821484

14831485
smc = smc_sk(sock->sk);
1486+
conn = &smc->conn;
14841487
if (smc->use_fallback) {
14851488
if (!smc->clcsock)
14861489
return -EBADF;
@@ -1517,6 +1520,23 @@ static int smc_ioctl(struct socket *sock, unsigned int cmd,
15171520
else
15181521
answ = smc_tx_prepared_sends(&smc->conn);
15191522
break;
1523+
case SIOCATMARK:
1524+
if (smc->sk.sk_state == SMC_LISTEN)
1525+
return -EINVAL;
1526+
if (smc->sk.sk_state == SMC_INIT ||
1527+
smc->sk.sk_state == SMC_CLOSED) {
1528+
answ = 0;
1529+
} else {
1530+
smc_curs_write(&cons,
1531+
smc_curs_read(&conn->local_tx_ctrl.cons, conn),
1532+
conn);
1533+
smc_curs_write(&urg,
1534+
smc_curs_read(&conn->urg_curs, conn),
1535+
conn);
1536+
answ = smc_curs_diff(conn->rmb_desc->len,
1537+
&cons, &urg) == 1;
1538+
}
1539+
break;
15201540
default:
15211541
return -ENOIOCTLCMD;
15221542
}

net/smc/smc.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ struct smc_host_cdc_msg { /* Connection Data Control message */
114114
u8 reserved[18];
115115
} __aligned(8);
116116

117+
enum smc_urg_state {
118+
SMC_URG_VALID, /* data present */
119+
SMC_URG_NOTYET, /* data pending */
120+
SMC_URG_READ /* data was already read */
121+
};
122+
117123
struct smc_connection {
118124
struct rb_node alert_node;
119125
struct smc_link_group *lgr; /* link group of connection */
@@ -160,6 +166,15 @@ struct smc_connection {
160166
union smc_host_cursor rx_curs_confirmed; /* confirmed to peer
161167
* source of snd_una ?
162168
*/
169+
union smc_host_cursor urg_curs; /* points at urgent byte */
170+
enum smc_urg_state urg_state;
171+
bool urg_tx_pend; /* urgent data staged */
172+
bool urg_rx_skip_pend;
173+
/* indicate urgent oob data
174+
* read, but previous regular
175+
* data still pending
176+
*/
177+
char urg_rx_byte; /* urgent byte */
163178
atomic_t bytes_to_rcv; /* arrived data,
164179
* not yet received
165180
*/

net/smc/smc_cdc.c

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,28 @@ static inline bool smc_cdc_before(u16 seq1, u16 seq2)
164164
return (s16)(seq1 - seq2) < 0;
165165
}
166166

167+
static void smc_cdc_handle_urg_data_arrival(struct smc_sock *smc,
168+
int *diff_prod)
169+
{
170+
struct smc_connection *conn = &smc->conn;
171+
char *base;
172+
173+
/* new data included urgent business */
174+
smc_curs_write(&conn->urg_curs,
175+
smc_curs_read(&conn->local_rx_ctrl.prod, conn),
176+
conn);
177+
conn->urg_state = SMC_URG_VALID;
178+
if (!sock_flag(&smc->sk, SOCK_URGINLINE))
179+
/* we'll skip the urgent byte, so don't account for it */
180+
(*diff_prod)--;
181+
base = (char *)conn->rmb_desc->cpu_addr;
182+
if (conn->urg_curs.count)
183+
conn->urg_rx_byte = *(base + conn->urg_curs.count - 1);
184+
else
185+
conn->urg_rx_byte = *(base + conn->rmb_desc->len - 1);
186+
sk_send_sigurg(&smc->sk);
187+
}
188+
167189
static void smc_cdc_msg_recv_action(struct smc_sock *smc,
168190
struct smc_cdc_msg *cdc)
169191
{
@@ -194,15 +216,25 @@ static void smc_cdc_msg_recv_action(struct smc_sock *smc,
194216
diff_prod = smc_curs_diff(conn->rmb_desc->len, &prod_old,
195217
&conn->local_rx_ctrl.prod);
196218
if (diff_prod) {
219+
if (conn->local_rx_ctrl.prod_flags.urg_data_present)
220+
smc_cdc_handle_urg_data_arrival(smc, &diff_prod);
197221
/* bytes_to_rcv is decreased in smc_recvmsg */
198222
smp_mb__before_atomic();
199223
atomic_add(diff_prod, &conn->bytes_to_rcv);
200224
/* guarantee 0 <= bytes_to_rcv <= rmb_desc->len */
201225
smp_mb__after_atomic();
202226
smc->sk.sk_data_ready(&smc->sk);
203-
} else if ((conn->local_rx_ctrl.prod_flags.write_blocked) ||
204-
(conn->local_rx_ctrl.prod_flags.cons_curs_upd_req)) {
205-
smc->sk.sk_data_ready(&smc->sk);
227+
} else {
228+
if (conn->local_rx_ctrl.prod_flags.write_blocked ||
229+
conn->local_rx_ctrl.prod_flags.cons_curs_upd_req ||
230+
conn->local_rx_ctrl.prod_flags.urg_data_pending) {
231+
if (conn->local_rx_ctrl.prod_flags.urg_data_pending)
232+
conn->urg_state = SMC_URG_NOTYET;
233+
/* force immediate tx of current consumer cursor, but
234+
* under send_lock to guarantee arrival in seqno-order
235+
*/
236+
smc_tx_sndbuf_nonempty(conn);
237+
}
206238
}
207239

208240
/* piggy backed tx info */
@@ -212,6 +244,12 @@ static void smc_cdc_msg_recv_action(struct smc_sock *smc,
212244
/* trigger socket release if connection closed */
213245
smc_close_wake_tx_prepared(smc);
214246
}
247+
if (diff_cons && conn->urg_tx_pend &&
248+
atomic_read(&conn->peer_rmbe_space) == conn->peer_rmbe_size) {
249+
/* urg data confirmed by peer, indicate we're ready for more */
250+
conn->urg_tx_pend = false;
251+
smc->sk.sk_write_space(&smc->sk);
252+
}
215253

216254
if (conn->local_rx_ctrl.conn_state_flags.peer_conn_abort) {
217255
smc->sk.sk_err = ECONNRESET;

net/smc/smc_cdc.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,19 @@ static inline int smc_curs_diff(unsigned int size,
146146
return max_t(int, 0, (new->count - old->count));
147147
}
148148

149+
/* calculate cursor difference between old and new - returns negative
150+
* value in case old > new
151+
*/
152+
static inline int smc_curs_comp(unsigned int size,
153+
union smc_host_cursor *old,
154+
union smc_host_cursor *new)
155+
{
156+
if (old->wrap > new->wrap ||
157+
(old->wrap == new->wrap && old->count > new->count))
158+
return -smc_curs_diff(size, new, old);
159+
return smc_curs_diff(size, old, new);
160+
}
161+
149162
static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer,
150163
union smc_host_cursor *local,
151164
struct smc_connection *conn)

net/smc/smc_core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ int smc_conn_create(struct smc_sock *smc,
544544
}
545545
conn->local_tx_ctrl.common.type = SMC_CDC_MSG_TYPE;
546546
conn->local_tx_ctrl.len = SMC_WR_TX_SIZE;
547+
conn->urg_state = SMC_URG_READ;
547548
#ifndef KERNEL_HAS_ATOMIC64
548549
spin_lock_init(&conn->acurs_lock);
549550
#endif

net/smc/smc_rx.c

Lines changed: 107 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,59 @@ static void smc_rx_wake_up(struct sock *sk)
4747
* @conn connection to update
4848
* @cons consumer cursor
4949
* @len number of Bytes consumed
50+
* Returns:
51+
* 1 if we should end our receive, 0 otherwise
5052
*/
51-
static void smc_rx_update_consumer(struct smc_connection *conn,
52-
union smc_host_cursor cons, size_t len)
53+
static int smc_rx_update_consumer(struct smc_sock *smc,
54+
union smc_host_cursor cons, size_t len)
5355
{
56+
struct smc_connection *conn = &smc->conn;
57+
struct sock *sk = &smc->sk;
58+
bool force = false;
59+
int diff, rc = 0;
60+
5461
smc_curs_add(conn->rmb_desc->len, &cons, len);
62+
63+
/* did we process urgent data? */
64+
if (conn->urg_state == SMC_URG_VALID || conn->urg_rx_skip_pend) {
65+
diff = smc_curs_comp(conn->rmb_desc->len, &cons,
66+
&conn->urg_curs);
67+
if (sock_flag(sk, SOCK_URGINLINE)) {
68+
if (diff == 0) {
69+
force = true;
70+
rc = 1;
71+
conn->urg_state = SMC_URG_READ;
72+
}
73+
} else {
74+
if (diff == 1) {
75+
/* skip urgent byte */
76+
force = true;
77+
smc_curs_add(conn->rmb_desc->len, &cons, 1);
78+
conn->urg_rx_skip_pend = false;
79+
} else if (diff < -1)
80+
/* we read past urgent byte */
81+
conn->urg_state = SMC_URG_READ;
82+
}
83+
}
84+
5585
smc_curs_write(&conn->local_tx_ctrl.cons, smc_curs_read(&cons, conn),
5686
conn);
87+
5788
/* send consumer cursor update if required */
5889
/* similar to advertising new TCP rcv_wnd if required */
59-
smc_tx_consumer_update(conn);
90+
smc_tx_consumer_update(conn, force);
91+
92+
return rc;
93+
}
94+
95+
static void smc_rx_update_cons(struct smc_sock *smc, size_t len)
96+
{
97+
struct smc_connection *conn = &smc->conn;
98+
union smc_host_cursor cons;
99+
100+
smc_curs_write(&cons, smc_curs_read(&conn->local_tx_ctrl.cons, conn),
101+
conn);
102+
smc_rx_update_consumer(smc, cons, len);
60103
}
61104

62105
struct smc_spd_priv {
@@ -70,7 +113,6 @@ static void smc_rx_pipe_buf_release(struct pipe_inode_info *pipe,
70113
struct smc_spd_priv *priv = (struct smc_spd_priv *)buf->private;
71114
struct smc_sock *smc = priv->smc;
72115
struct smc_connection *conn;
73-
union smc_host_cursor cons;
74116
struct sock *sk = &smc->sk;
75117

76118
if (sk->sk_state == SMC_CLOSED ||
@@ -79,9 +121,7 @@ static void smc_rx_pipe_buf_release(struct pipe_inode_info *pipe,
79121
goto out;
80122
conn = &smc->conn;
81123
lock_sock(sk);
82-
smc_curs_write(&cons, smc_curs_read(&conn->local_tx_ctrl.cons, conn),
83-
conn);
84-
smc_rx_update_consumer(conn, cons, priv->len);
124+
smc_rx_update_cons(smc, priv->len);
85125
release_sock(sk);
86126
if (atomic_sub_and_test(priv->len, &conn->splice_pending))
87127
smc_rx_wake_up(sk);
@@ -184,6 +224,52 @@ int smc_rx_wait(struct smc_sock *smc, long *timeo,
184224
return rc;
185225
}
186226

227+
static int smc_rx_recv_urg(struct smc_sock *smc, struct msghdr *msg, int len,
228+
int flags)
229+
{
230+
struct smc_connection *conn = &smc->conn;
231+
union smc_host_cursor cons;
232+
struct sock *sk = &smc->sk;
233+
int rc = 0;
234+
235+
if (sock_flag(sk, SOCK_URGINLINE) ||
236+
!(conn->urg_state == SMC_URG_VALID) ||
237+
conn->urg_state == SMC_URG_READ)
238+
return -EINVAL;
239+
240+
if (conn->urg_state == SMC_URG_VALID) {
241+
if (!(flags & MSG_PEEK))
242+
smc->conn.urg_state = SMC_URG_READ;
243+
msg->msg_flags |= MSG_OOB;
244+
if (len > 0) {
245+
if (!(flags & MSG_TRUNC))
246+
rc = memcpy_to_msg(msg, &conn->urg_rx_byte, 1);
247+
len = 1;
248+
smc_curs_write(&cons,
249+
smc_curs_read(&conn->local_tx_ctrl.cons,
250+
conn),
251+
conn);
252+
if (smc_curs_diff(conn->rmb_desc->len, &cons,
253+
&conn->urg_curs) > 1)
254+
conn->urg_rx_skip_pend = true;
255+
/* Urgent Byte was already accounted for, but trigger
256+
* skipping the urgent byte in non-inline case
257+
*/
258+
if (!(flags & MSG_PEEK))
259+
smc_rx_update_consumer(smc, cons, 0);
260+
} else {
261+
msg->msg_flags |= MSG_TRUNC;
262+
}
263+
264+
return rc ? -EFAULT : len;
265+
}
266+
267+
if (sk->sk_state == SMC_CLOSED || sk->sk_shutdown & RCV_SHUTDOWN)
268+
return 0;
269+
270+
return -EAGAIN;
271+
}
272+
187273
/* smc_rx_recvmsg - receive data from RMBE
188274
* @msg: copy data to receive buffer
189275
* @pipe: copy data to pipe if set - indicates splice() call
@@ -209,12 +295,12 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
209295

210296
if (unlikely(flags & MSG_ERRQUEUE))
211297
return -EINVAL; /* future work for sk.sk_family == AF_SMC */
212-
if (flags & MSG_OOB)
213-
return -EINVAL; /* future work */
214298

215299
sk = &smc->sk;
216300
if (sk->sk_state == SMC_LISTEN)
217301
return -ENOTCONN;
302+
if (flags & MSG_OOB)
303+
return smc_rx_recv_urg(smc, msg, len, flags);
218304
timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
219305
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
220306

@@ -227,6 +313,9 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
227313

228314
if (atomic_read(&conn->bytes_to_rcv))
229315
goto copy;
316+
else if (conn->urg_state == SMC_URG_VALID)
317+
/* we received a single urgent Byte - skip */
318+
smc_rx_update_cons(smc, 0);
230319

231320
if (sk->sk_shutdown & RCV_SHUTDOWN ||
232321
smc_cdc_rxed_any_close_or_senddone(conn) ||
@@ -281,14 +370,18 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
281370
continue;
282371
}
283372

284-
/* not more than what user space asked for */
285-
copylen = min_t(size_t, read_remaining, readable);
286373
smc_curs_write(&cons,
287374
smc_curs_read(&conn->local_tx_ctrl.cons, conn),
288375
conn);
289376
/* subsequent splice() calls pick up where previous left */
290377
if (splbytes)
291378
smc_curs_add(conn->rmb_desc->len, &cons, splbytes);
379+
if (conn->urg_state == SMC_URG_VALID &&
380+
sock_flag(&smc->sk, SOCK_URGINLINE) &&
381+
readable > 1)
382+
readable--; /* always stop at urgent Byte */
383+
/* not more than what user space asked for */
384+
copylen = min_t(size_t, read_remaining, readable);
292385
/* determine chunks where to read from rcvbuf */
293386
/* either unwrapped case, or 1st chunk of wrapped case */
294387
chunk_len = min_t(size_t, copylen, conn->rmb_desc->len -
@@ -333,8 +426,8 @@ int smc_rx_recvmsg(struct smc_sock *smc, struct msghdr *msg,
333426
atomic_sub(copylen, &conn->bytes_to_rcv);
334427
/* guarantee 0 <= bytes_to_rcv <= rmb_desc->len */
335428
smp_mb__after_atomic();
336-
if (msg)
337-
smc_rx_update_consumer(conn, cons, copylen);
429+
if (msg && smc_rx_update_consumer(smc, cons, copylen))
430+
goto out;
338431
}
339432
} while (read_remaining);
340433
out:
@@ -346,4 +439,5 @@ void smc_rx_init(struct smc_sock *smc)
346439
{
347440
smc->sk.sk_data_ready = smc_rx_wake_up;
348441
atomic_set(&smc->conn.splice_pending, 0);
442+
smc->conn.urg_state = SMC_URG_READ;
349443
}

0 commit comments

Comments
 (0)