From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Ahern Subject: Re: The SO_BINDTODEVICE was set to the desired interface, but packets are received from all interfaces. Date: Tue, 8 May 2018 16:48:43 -0600 Message-ID: References: <5a61e34b-75c2-0452-d6e2-6e4ea77d5ac2@oktetlabs.ru> <1525696890.2587.24.camel@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Cc: Konstantin Ushakov , "Alexandra N. Kossovsky" , Andrey Dmitrov To: Paolo Abeni , Damir Mansurov , netdev@vger.kernel.org Return-path: Received: from mail-pl0-f44.google.com ([209.85.160.44]:42706 "EHLO mail-pl0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932133AbeEHWsq (ORCPT ); Tue, 8 May 2018 18:48:46 -0400 Received: by mail-pl0-f44.google.com with SMTP id u6-v6so3077418pls.9 for ; Tue, 08 May 2018 15:48:46 -0700 (PDT) In-Reply-To: <1525696890.2587.24.camel@redhat.com> Content-Language: en-US Sender: netdev-owner@vger.kernel.org List-ID: On 5/7/18 6:41 AM, Paolo Abeni wrote: > Hi, > On Mon, 2018-05-07 at 13:19 +0300, Damir Mansurov wrote: >> After successful call of the setsockopt(SO_BINDTODEVICE) function to set >> data reception from only one interface, the data is still received from >> all interfaces. Function setsockopt() returns 0 but then recv() receives >> data from all available network interfaces. >> >> The problem is reproducible on linux kernels 4.14 - 4.16, but it does >> not on linux kernels 4.4, 4.13. > > I think that the cause is commit: > > commit fb74c27735f0a34e76dbf1972084e984ad2ea145 > Author: David Ahern > Date: Mon Aug 7 08:44:16 2017 -0700 > > net: ipv4: add second dif to udp socket lookups > > Something like the following should fix, but I'm unsure it preserves > the intended semathics for 'sdif'. David, can you please have a look? > Thanks! > > Paolo > --- > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c > index dd3102a37ef9..0d593d5c33cf 100644 > --- a/net/ipv4/udp.c > +++ b/net/ipv4/udp.c > @@ -401,9 +401,9 @@ static int compute_score(struct sock *sk, struct net *net, > bool dev_match = (sk->sk_bound_dev_if == dif || > sk->sk_bound_dev_if == sdif); > > - if (exact_dif && !dev_match) > + if (!dev_match) > return -1; > - if (sk->sk_bound_dev_if && dev_match) > + if (sk->sk_bound_dev_if) > score += 4; > } > > The above fixes the reported problem. You should make the same change to ipv6 as well. Fixes tags: Fixes: fb74c27735f0a ("net: ipv4: add second dif to udp socket lookups") Fixes: 1801b570dd2ae ("net: ipv6: add second dif to udp socket lookups") The change does break a VRF use case, but that case works by accident given this bug. The use case is a client or server bound to an enslaved device and trying to communicate locally. In some cases the error is the ICMP 'Connection refused' getting lost; in other cases the packets don't make it from one scope to another (eg., VRF based server talking to device based client). After poking around for a couple of days, I believe the proper fix for this uses case is beyond the scope of anything that should be backported to 4.14. So I am fine with the breakage to what is IMHO a corner case - and there is a reasonable workaround until I find a proper solution.