Skip to content

Commit

Permalink
udp: preserve skb->dst if required for IP options processing
Browse files Browse the repository at this point in the history
Eric noticed that in udp_recvmsg() we still need to access
skb->dst while processing the IP options.
Since commit 0a463c7 ("udp: avoid a cache miss on dequeue")
skb->dst is no more available at recvmsg() time and bad things
will happen if we enter the relevant code path.

This commit address the issue, avoid clearing skb->dst if
any IP options are present into the relevant skb.
Since the IP CB is contained in the first skb cacheline, we can
test it to decide to leverage the consume_stateless_skb()
optimization, without measurable additional cost in the faster
path.

v1 -> v2: updated commit message tags

Fixes: 0a463c7 ("udp: avoid a cache miss on dequeue")
Reported-by: Andrey Konovalov <andreyknvl@google.com>
Reported-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Paolo Abeni authored and David S. Miller committed Jul 18, 2017
1 parent 799f917 commit 0ddf3fb
Showing 1 changed file with 11 additions and 2 deletions.
13 changes: 11 additions & 2 deletions net/ipv4/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1388,6 +1388,11 @@ void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len)
unlock_sock_fast(sk, slow);
}

/* we cleared the head states previously only if the skb lacks any IP
* options, see __udp_queue_rcv_skb().
*/
if (unlikely(IPCB(skb)->opt.optlen > 0))
skb_release_head_state(skb);
consume_stateless_skb(skb);
}
EXPORT_SYMBOL_GPL(skb_consume_udp);
Expand Down Expand Up @@ -1779,8 +1784,12 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
sk_mark_napi_id_once(sk, skb);
}

/* clear all pending head states while they are hot in the cache */
skb_release_head_state(skb);
/* At recvmsg() time we need skb->dst to process IP options-related
* cmsg, elsewhere can we clear all pending head states while they are
* hot in the cache
*/
if (likely(IPCB(skb)->opt.optlen == 0))
skb_release_head_state(skb);

rc = __udp_enqueue_schedule_skb(sk, skb);
if (rc < 0) {
Expand Down

0 comments on commit 0ddf3fb

Please sign in to comment.