Skip to content

Commit 46dda29

Browse files
committed
neper: rx zerocopy hybrid reads
Tested: confirmed that we still transfer almost all (99%) bytes via zerocopy.
1 parent 1a70286 commit 46dda29

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

flow.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,20 @@ ssize_t flow_recv_zerocopy(struct flow *f, void *copybuf, size_t copybuf_len) {
337337
socklen_t zc_len = sizeof(zc);
338338
int result;
339339

340+
/* Setup both the mmap address and extra buffer for bytes that aren't
341+
* zerocopy-able.
342+
*/
340343
zc.address = (__u64)f->f_rx_zerocopy_buffer;
341344
zc.length = copybuf_len; /* Same size used as zerocopy buffer. */
342345

346+
/* The kernel will effectively use copybuf_len as a hint as to what the
347+
* cutoff point between zerocopy and recv is. So passing a large copybuf
348+
* causes less zerocopy. Thus we pass just under a page to maximize
349+
* zerocopying.
350+
*/
351+
zc.copybuf_address = (__u64)copybuf;
352+
zc.copybuf_len = copybuf_len < 4096 ? copybuf_len : 4095;
353+
343354
result = getsockopt(f->f_fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, &zc,
344355
&zc_len);
345356
if (result == -1)
@@ -361,5 +372,5 @@ ssize_t flow_recv_zerocopy(struct flow *f, void *copybuf, size_t copybuf_len) {
361372
madvise(f->f_rx_zerocopy_buffer, zc.length, MADV_DONTNEED);
362373
}
363374

364-
return zc.recv_skip_hint + zc.length;
375+
return zc.recv_skip_hint + zc.length + zc.copybuf_len;
365376
}

0 commit comments

Comments
 (0)