Skip to content

Commit

Permalink
net-zerocopy: Set zerocopy hint when data is copied
Browse files Browse the repository at this point in the history
Set zerocopy hint, event when falling back to copy, so that the
pending data can be efficiently received using zerocopy when
possible.

Signed-off-by: Arjun Roy <arjunroy@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Arjun Roy authored and Jakub Kicinski committed Dec 4, 2020
1 parent f21a3c4 commit 0c3936d
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions net/ipv4/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1800,6 +1800,43 @@ static int find_next_mappable_frag(const skb_frag_t *frag,
return offset;
}

static void tcp_zerocopy_set_hint_for_skb(struct sock *sk,
struct tcp_zerocopy_receive *zc,
struct sk_buff *skb, u32 offset)
{
u32 frag_offset, partial_frag_remainder = 0;
int mappable_offset;
skb_frag_t *frag;

/* worst case: skip to next skb. try to improve on this case below */
zc->recv_skip_hint = skb->len - offset;

/* Find the frag containing this offset (and how far into that frag) */
frag = skb_advance_to_frag(skb, offset, &frag_offset);
if (!frag)
return;

if (frag_offset) {
struct skb_shared_info *info = skb_shinfo(skb);

/* We read part of the last frag, must recvmsg() rest of skb. */
if (frag == &info->frags[info->nr_frags - 1])
return;

/* Else, we must at least read the remainder in this frag. */
partial_frag_remainder = skb_frag_size(frag) - frag_offset;
zc->recv_skip_hint -= partial_frag_remainder;
++frag;
}

/* partial_frag_remainder: If part way through a frag, must read rest.
* mappable_offset: Bytes till next mappable frag, *not* counting bytes
* in partial_frag_remainder.
*/
mappable_offset = find_next_mappable_frag(frag, zc->recv_skip_hint);
zc->recv_skip_hint = mappable_offset + partial_frag_remainder;
}

static int tcp_recvmsg_locked(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags,
struct scm_timestamping_internal *tss,
Expand Down Expand Up @@ -1830,6 +1867,14 @@ static int receive_fallback_to_copy(struct sock *sk,
return err;

zc->copybuf_len = err;
if (likely(zc->copybuf_len)) {
struct sk_buff *skb;
u32 offset;

skb = tcp_recv_skb(sk, tcp_sk(sk)->copied_seq, &offset);
if (skb)
tcp_zerocopy_set_hint_for_skb(sk, zc, skb, offset);
}
return 0;
}

Expand Down

0 comments on commit 0c3936d

Please sign in to comment.