Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752518AbdFAQne (ORCPT ); Thu, 1 Jun 2017 12:43:34 -0400 Received: from mail-it0-f44.google.com ([209.85.214.44]:36665 "EHLO mail-it0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751871AbdFAQnS (ORCPT ); Thu, 1 Jun 2017 12:43:18 -0400 MIME-Version: 1.0 In-Reply-To: <20170601153645.GC10526@rei.suse.de> References: <20170601140048.GA24401@rei.lan> <20170601143141.GB24401@rei.lan> <20170601151003.GB10526@rei.suse.de> <20170601153645.GC10526@rei.suse.de> From: Soheil Hassas Yeganeh Date: Thu, 1 Jun 2017 12:42:18 -0400 Message-ID: Subject: Re: commit f5f99309 (sock: do not set sk_err in sock_dequeue_err_skb) has broken ping To: Cyril Hrubis Cc: "David S. Miller" , Shmulik Ladkani , Marcelo Ricardo Leitner , Pravin B Shelar , Eric Dumazet , WANG Cong , Yaogong Wang , Steffen Klassert , Al Viro , netdev , linux-kernel@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2023 Lines: 53 On Thu, Jun 1, 2017 at 11:36 AM, Cyril Hrubis wrote: > It seems to repeatedly produce (until I plug the cable back): > > ee_errno = 113 ee_origin = 2 ee_type = 3 ee_code = 1 ee_info = 0 ee_data = 0 > > So we get EHOSTUNREACH on SO_EE_ORIGIN_ICMP. Thank you very much! I have a wild guess that, when we have a train of skbs on the error queue starting from a local error, we will see this issue. Ping (without my patch) considers EAGAIN on a normal read as an indication that there is nothing on the error queue, but that's a flawed assumption. Would you mind trying another shot in the darkness please? Thanks! diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5a726161f4e4..097152a03c74 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3742,7 +3742,8 @@ EXPORT_SYMBOL(sock_queue_err_skb); static bool is_icmp_err_skb(const struct sk_buff *skb) { return skb && (SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ICMP || - SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ICMP6); + SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_ICMP6 || + SKB_EXT_ERR(skb)->ee.ee_origin == SO_EE_ORIGIN_LOCAL); } struct sk_buff *sock_dequeue_err_skb(struct sock *sk) @@ -3751,14 +3752,19 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk) struct sk_buff *skb, *skb_next = NULL; bool icmp_next = false; unsigned long flags; + int err = 0; spin_lock_irqsave(&q->lock, flags); skb = __skb_dequeue(q); - if (skb && (skb_next = skb_peek(q))) + if (skb && (skb_next = skb_peek(q))) { icmp_next = is_icmp_err_skb(skb_next); + err = SKB_EXT_ERR(skb_next)->ee.ee_origin; + } spin_unlock_irqrestore(&q->lock, flags); - if (is_icmp_err_skb(skb) && !icmp_next) + if (icmp_next) + sk->sk_err = err; + else if (is_icmp_err_skb(skb) && !icmp_next) sk->sk_err = 0; if (skb_next)