* RE: [PATCH] netfilter: fix stringop-overflow warning with UBSAN
From: David Laight @ 2017-08-01 9:25 UTC (permalink / raw)
To: 'Arnd Bergmann', Pablo Neira Ayuso, Jozsef Kadlecsik,
Florian Westphal, David S. Miller
Cc: Johannes Berg, Alexey Dobriyan, Aaron Conole,
netfilter-devel@vger.kernel.org, coreteam@netfilter.org,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20170731100913.465530-1-arnd@arndb.de>
From: Arnd Bergmann
> Sent: 31 July 2017 11:09
> Using gcc-7 with UBSAN enabled, we get this false-positive warning:
>
> net/netfilter/ipset/ip_set_core.c: In function 'ip_set_sockfn_get':
> net/netfilter/ipset/ip_set_core.c:1998:3: error: 'strncpy' writing 32 bytes into a region of size 2
> overflows the destination [-Werror=stringop-overflow=]
> strncpy(req_get->set.name, set ? set->name : "",
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> sizeof(req_get->set.name));
> ~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> This seems completely bogus, and I could not find a nice workaround.
> To work around it in a less elegant way, I change the ?: operator
> into an if()/else() construct.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> net/netfilter/ipset/ip_set_core.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
> index e495b5e484b1..d7ebb021003b 100644
> --- a/net/netfilter/ipset/ip_set_core.c
> +++ b/net/netfilter/ipset/ip_set_core.c
> @@ -1995,8 +1995,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
> }
> nfnl_lock(NFNL_SUBSYS_IPSET);
> set = ip_set(inst, req_get->set.index);
> - strncpy(req_get->set.name, ,
> - IPSET_MAXNAMELEN);
> + if (set)
> + strncpy(req_get->set.name, set->name,
> + sizeof(req_get->set.name));
> + else
> + memset(req_get->set.name, '\0',
> + sizeof(req_get->set.name));
If you use strncpy() here, the compiler might optimise the code
back to 'how it was before'.
Or, maybe an explicit temporary: 'const char *name = set ? set->name : "";
David
^ permalink raw reply
* Re: [PATCH] Cipso: cipso_v4_optptr enter infinite loop
From: yujuan.qi @ 2017-08-01 8:54 UTC (permalink / raw)
To: Paul Moore
Cc: Ryder Lee, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Casey Schaufler,
David S. Miller
In-Reply-To: <CAGH-KguiiVTyxHp0Z3Z==6b5n2h3Lm4SmU=ruydMpGgctdhYSw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
Hi
On Mon, 2017-07-31 at 16:13 -0400, Paul Moore wrote:
> On Sun, Jul 30, 2017 at 11:23 PM, Yujuan Qi <yujuan.qi-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org> wrote:
> > From: "yujuan.qi" <yujuan.qi-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> >
> > in for(),if((optlen > 0) && (optptr[1] == 0)), enter infinite loop.
> >
> > Test: receive a packet which the ip length > 20 and t he first byte of ip option is 0, produce this issue
> >
> > Signed-off-by: yujuan.qi <yujuan.qi-NuS5LvNUpcJWk0Htik3J/w@public.gmane.org>
> > ---
> > net/ipv4/cipso_ipv4.c | 12 ++++++++++--
> > 1 file changed, 10 insertions(+), 2 deletions(-)
>
> Considering I gave you the code below I should probably ack it, right? ;)
>
> Acked-by: Paul Moore <paul-r2n+y4ga6xFZroRs9YW3xA@public.gmane.org>
Yes! Thanks for your suggestions!
> > diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
> > index ae20616..0d1e07d 100644
> > --- a/net/ipv4/cipso_ipv4.c
> > +++ b/net/ipv4/cipso_ipv4.c
> > @@ -1523,9 +1523,17 @@ unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
> > int taglen;
> >
> > for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 0; ) {
> > - if (optptr[0] == IPOPT_CIPSO)
> > + switch (optptr[0]) {
> > + case IPOPT_CIPSO:
> > return optptr;
> > - taglen = optptr[1];
> > + case IPOPT_END:
> > + return NULL;
> > + case IPOPT_NOOP:
> > + taglen = 1;
> > + break;
> > + default:
> > + taglen = optptr[1];
> > + }
> > optlen -= taglen;
> > optptr += taglen;
> > }
>
^ permalink raw reply
* Re: [PATCH net 3/3] tcp: fix xmit timer to only be reset if data ACKed/SACKed
From: Eric Dumazet @ 2017-08-01 7:25 UTC (permalink / raw)
To: Neal Cardwell; +Cc: David Miller, netdev, Yuchung Cheng, Nandita Dukkipati
In-Reply-To: <20170801025814.31206-4-ncardwell@google.com>
On Mon, 2017-07-31 at 22:58 -0400, Neal Cardwell wrote:
> Fix a TCP loss recovery performance bug raised recently on the netdev
> list, in two threads:
>
> (i) July 26, 2017: netdev thread "TCP fast retransmit issues"
> (ii) July 26, 2017: netdev thread:
> "[PATCH V2 net-next] TLP: Don't reschedule PTO when there's one
> outstanding TLP retransmission"
Acked-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply
* Re: [PATCH net 2/3] tcp: enable xmit timer fix by having TLP use time when RTO should fire
From: Eric Dumazet @ 2017-08-01 7:22 UTC (permalink / raw)
To: Neal Cardwell; +Cc: David Miller, netdev, Yuchung Cheng, Nandita Dukkipati
In-Reply-To: <20170801025814.31206-3-ncardwell@google.com>
On Mon, 2017-07-31 at 22:58 -0400, Neal Cardwell wrote:
> Have tcp_schedule_loss_probe() base the TLP scheduling decision based
> on when the RTO *should* fire. This is to enable the upcoming xmit
> timer fix in this series, where tcp_schedule_loss_probe() cannot
> assume that the last timer installed was an RTO timer (because we are
> no longer doing the "rearm RTO, rearm RTO, rearm TLP" dance on every
> ACK). So tcp_schedule_loss_probe() must independently figure out when
> an RTO would want to fire.
>
> In the new TLP implementation following in this series, we cannot
> assume that icsk_timeout was set based on an RTO; after processing a
> cumulative ACK the icsk_timeout we see can be from a previous TLP or
> RTO. So we need to independently recalculate the RTO time (instead of
> reading it out of icsk_timeout). Removing this dependency on the
> nature of icsk_timeout makes things a little easier to reason about
> anyway.
>
> Note that the old and new code should be equivalent, since they are
> both saying: "if the RTO is in the future, but at an earlier time than
> the normal TLP time, then set the TLP timer to fire when the RTO would
> have fired".
>
> Fixes: 6ba8a3b19e76 ("tcp: Tail loss probe (TLP)")
> Signed-off-by: Neal Cardwell <ncardwell@google.com>
> Signed-off-by: Yuchung Cheng <ycheng@google.com>
> Signed-off-by: Nandita Dukkipati <nanditad@google.com>
> ---
> net/ipv4/tcp_output.c | 12 ++++--------
> 1 file changed, 4 insertions(+), 8 deletions(-)
>
> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> index 2f1588bf73da..0ae6b5d176c0 100644
> --- a/net/ipv4/tcp_output.c
> +++ b/net/ipv4/tcp_output.c
> @@ -2377,8 +2377,8 @@ bool tcp_schedule_loss_probe(struct sock *sk)
> {
> struct inet_connection_sock *icsk = inet_csk(sk);
> struct tcp_sock *tp = tcp_sk(sk);
> - u32 timeout, tlp_time_stamp, rto_time_stamp;
> u32 rtt = usecs_to_jiffies(tp->srtt_us >> 3);
> + u32 timeout, rto_delta_us;
>
> /* No consecutive loss probes. */
> if (WARN_ON(icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)) {
> @@ -2418,13 +2418,9 @@ bool tcp_schedule_loss_probe(struct sock *sk)
> timeout = max_t(u32, timeout, msecs_to_jiffies(10));
>
> /* If RTO is shorter, just schedule TLP in its place. */
I have hard time to read this comment.
We are here trying to arm a timer based on TLP.
If RTO is shorter, we'll arm the timer based on RTO instead of TLP.
Is "If RTO is shorter, just schedule TLP in its place." really correct ?
I suggest we reword the comment or simply get rid of it now the code is
more obvious.
> - tlp_time_stamp = tcp_jiffies32 + timeout;
> - rto_time_stamp = (u32)inet_csk(sk)->icsk_timeout;
> - if ((s32)(tlp_time_stamp - rto_time_stamp) > 0) {
> - s32 delta = rto_time_stamp - tcp_jiffies32;
> - if (delta > 0)
> - timeout = delta;
> - }
> + rto_delta_us = tcp_rto_delta_us(sk); /* How far in future is RTO? */
> + if (rto_delta_us > 0)
> + timeout = min_t(u32, timeout, usecs_to_jiffies(rto_delta_us));
>
> inet_csk_reset_xmit_timer(sk, ICSK_TIME_LOSS_PROBE, timeout,
> TCP_RTO_MAX);
Acked-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply
* Re: [RFC] net: make net.core.{r,w}mem_{default,max} namespaced
From: Eric Dumazet @ 2017-08-01 7:18 UTC (permalink / raw)
To: Hannes Frederic Sowa; +Cc: Matteo Croce, netdev
In-Reply-To: <87wp6nerrj.fsf@stressinduktion.org>
On Tue, 2017-08-01 at 02:17 -0400, Hannes Frederic Sowa wrote:
> We do account rmem as well as wmem allocated memory to the apropriate
> mem_cgs. In theory this should be okay.
Last time I checked, rmem was not memcg ready yet.
Can you describe the details ?
Thanks.
^ permalink raw reply
* Re: [PATCH net 1/3] tcp: introduce tcp_rto_delta_us() helper for xmit timer fix
From: Eric Dumazet @ 2017-08-01 7:16 UTC (permalink / raw)
To: Neal Cardwell; +Cc: David Miller, netdev, Yuchung Cheng, Nandita Dukkipati
In-Reply-To: <20170801025814.31206-2-ncardwell@google.com>
On Mon, 2017-07-31 at 22:58 -0400, Neal Cardwell wrote:
> Pure refactor. This helper will be required in the xmit timer fix
> later in the patch series. (Because the TLP logic will want to make
> this calculation.)
>
> Fixes: 6ba8a3b19e76 ("tcp: Tail loss probe (TLP)")
> Signed-off-by: Neal Cardwell <ncardwell@google.com>
> Signed-off-by: Yuchung Cheng <ycheng@google.com>
> Signed-off-by: Nandita Dukkipati <nanditad@google.com>
> ---
> include/net/tcp.h | 10 ++++++++++
> net/ipv4/tcp_input.c | 5 +----
> 2 files changed, 11 insertions(+), 4 deletions(-)
Acked-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply
* Re: [RFC net-next] net ipv6: convert fib6_table rwlock to a percpu lock
From: Eric Dumazet @ 2017-08-01 7:15 UTC (permalink / raw)
To: Shaohua Li
Cc: Stephen Hemminger, netdev, davem, Kernel-team, Shaohua Li,
Wei Wang
In-Reply-To: <20170801025704.fuhxll23d3eenwrz@kernel.org>
On Mon, 2017-07-31 at 19:57 -0700, Shaohua Li wrote:
> On Mon, Jul 31, 2017 at 04:10:07PM -0700, Stephen Hemminger wrote:
> > On Mon, 31 Jul 2017 10:18:57 -0700
> > Shaohua Li <shli@kernel.org> wrote:
> >
> > > From: Shaohua Li <shli@fb.com>
> > >
> > > In a syn flooding test, the fib6_table rwlock is a significant
> > > bottleneck. While converting the rwlock to rcu sounds straighforward,
> > > but is very challenging if it's possible. A percpu spinlock is quite
> > > trival for this problem since updating the routing table is a rare
> > > event. In my test, the server receives around 1.5 Mpps in syn flooding
> > > test without the patch in a dual sockets and 56-CPU system. With the
> > > patch, the server receives around 3.8Mpps, and perf report doesn't show
> > > the locking issue.
> > >
> > > Cc: Wei Wang <weiwan@google.com>
> >
> > You just reinvented brlock...
>
> you mean lglock? It has been removed from kernel.
>
> > RCU is not that hard, why not do it right?
>
> Maybe. But don't think it's the reason why we shouldn't do the percpu lock now,
> this is a simple change, if some smart guys find a way of RCU, we can easily
> remove this.
Make sure to test this on a 256 cpu host, dealing with ICMP messages a
lot.
percpu locks do not scale. This hack was okay last decade, sure, but it
is no longer a good hack.
I would rather focus on the RCU work, Wei is actively working on it.
^ permalink raw reply
* Re: [PATCH v2 2/4] can: fixed-transceiver: Add documentation for CAN fixed transceiver bindings
From: Kurt Van Dijck @ 2017-08-01 7:12 UTC (permalink / raw)
To: Oliver Hartkopp
Cc: Franklin S Cooper Jr, Andrew Lunn, linux-kernel, devicetree,
netdev, linux-can, wg, mkl, robh+dt, quentin.schulz,
sergei.shtylyov
In-Reply-To: <91879489-87de-21b9-0227-650c0001e6a3@hartkopp.net>
> Hi Kurt,
>
> On 07/28/2017 09:41 PM, Kurt Van Dijck wrote:
>
> >>The transceiver is an analog device that needs to support faster
> >>switching frequency (FETs) including minimizing delay to support CAN-FD
> >>ie higher bitrate. From the transceiver perspective the bits for
> >>"arbitration" and "data" look exactly the same. Since it can't
> >>differentiate between the two (at the physical layer) then the actual
> >>limit isn't specific to which part/type of the CAN message is being
> >>sent. Rather its just a single overall max bitrate limit.
> >
> >I must disagree here.
> >The transceiver is an analog device that performs 2 functions:
> >propagate tx bits to CAN wire, and propagate CAN wire state
> >(dominant/recesive) to rx bits.
> >
> >I'll rephrase the above explanation to fit your argument:
> >During arbitration, both directions are required, and needs to propagate
> >within 1 bit time. The transceiver doesn't know, it just performs to
> >best effort.
> >During data, the round-trip timing requirement of layer2 is relaxed.
> >The transceiver still doesn't know, it still performs to best effort.
> >Due to the relaxed round-trip timing requirement, the same transceiver
> >can suddenly allow higher bitrates. The transceiver didn't change, the
> >requirement did change.
> >This is what I meant earlier with "layer2 has been adapted to circumvent
> >layer1 limitations"
> >
> I talked to our CAN transceiver & CAN physical layer specialist who was
> involved in the ISO activities too.
>
> We just need ONE value: max-bitrate
>
> The CAN transceiver is qualified to provide this bitrate. That's it.
> There's nothing special with the arbitration bitrate - we don't even need to
> outline any CAN FD capability.
>
> The other things like 'loop delay compensation' are done in the CAN
> controller. The better the transceiver get's the bits 'in shape' the higher
> it can be qualified. But from the SoC/Controller/Linux view we only need the
> max-bitrate value to double check with the CAN controllers bitrate
> configuration request (which was Franklins intention).
I bet your physical layer specialist understands the details way better
than I do :-)
1 value it is then.
Kind regards,
Kurt
^ permalink raw reply
* Re: [RFC] net: make net.core.{r,w}mem_{default,max} namespaced
From: Hannes Frederic Sowa @ 2017-08-01 6:17 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Matteo Croce, netdev
In-Reply-To: <1501495652.1876.17.camel@edumazet-glaptop3.roam.corp.google.com>
Eric Dumazet <eric.dumazet@gmail.com> writes:
> On Wed, 2017-07-26 at 19:03 +0200, Matteo Croce wrote:
>> The following sysctl are global and can't be read or set from a netns:
>>
>> net.core.rmem_default
>> net.core.rmem_max
>> net.core.wmem_default
>> net.core.wmem_max
>>
>> Make the following sysctl parameters available from within a network
>> namespace, allowing to set unique values per network namespace.
>>
>> My concern is about the initial value of this sysctl in the newly
>> creates netns: I'm not sure if is better to copy them from the init
>> namespace or set them to the default values.
>>
>> Setting them to the default value has the advantage that a new namespace
>> behaves like a freshly booted system, while copying them from the init
>> netns has the advantage of keeping the current behaviour as the values
>> from the init netns are used.
>>
>> Signed-off-by: Matteo Croce <mcroce@redhat.com>
>> ---
>
> It looks that these sysctls were giving some kind of isolation.
>
> If we make them per namespace, a malicious usage could eat all memory
> and hurt other namespaces.
We do account rmem as well as wmem allocated memory to the apropriate
mem_cgs. In theory this should be okay.
Bye,
Hannes
^ permalink raw reply
* Re: [PATCH 1/2] ipv6: constify inet6_protocol structures
From: Julia Lawall @ 2017-08-01 5:59 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S. Miller, bhumirks, netdev
In-Reply-To: <1501495011.1876.12.camel@edumazet-glaptop3.roam.corp.google.com>
On Mon, 31 Jul 2017, Eric Dumazet wrote:
> On Fri, 2017-07-28 at 22:18 +0200, Julia Lawall wrote:
> > The inet6_protocol structure is only passed as the first argument to
> > inet6_add_protocol or inet6_del_protocol, both of which are declared as
> > const. Thus the inet6_protocol structure itself can be const.
> >
> > Also drop __read_mostly where present on the newly const structures.
> >
> > Done with the help of Coccinelle.
> >
> > Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
> >
> > ---
> > net/ipv6/ip6_gre.c | 2 +-
> > net/ipv6/tcp_ipv6.c | 2 +-
> > net/ipv6/udp.c | 2 +-
> > 3 files changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
> > index 67ff2aa..33865d6 100644
> > --- a/net/ipv6/ip6_gre.c
> > +++ b/net/ipv6/ip6_gre.c
> > @@ -1080,7 +1080,7 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
> > }
> >
> >
> > -static struct inet6_protocol ip6gre_protocol __read_mostly = {
> > +static const struct inet6_protocol ip6gre_protocol = {
> > .handler = gre_rcv,
> > .err_handler = ip6gre_err,
> > .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
> > diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
> > index 90a3257..2968a33 100644
> > --- a/net/ipv6/tcp_ipv6.c
> > +++ b/net/ipv6/tcp_ipv6.c
> > @@ -1945,7 +1945,7 @@ struct proto tcpv6_prot = {
> > .diag_destroy = tcp_abort,
> > };
> >
> > -static struct inet6_protocol tcpv6_protocol = {
> > +static const struct inet6_protocol tcpv6_protocol = {
> > .early_demux = tcp_v6_early_demux,
> > .early_demux_handler = tcp_v6_early_demux,
> > .handler = tcp_v6_rcv,
> > diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
> > index 4a3e656..5f8b8d7 100644
> > --- a/net/ipv6/udp.c
> > +++ b/net/ipv6/udp.c
> > @@ -1448,7 +1448,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
> > }
> > #endif
> >
> > -static struct inet6_protocol udpv6_protocol = {
> > +static const struct inet6_protocol udpv6_protocol = {
> > .early_demux = udp_v6_early_demux,
> > .early_demux_handler = udp_v6_early_demux,
> > .handler = udpv6_rcv,
> >
>
> This change breaks the kernel if one of these sysctls are changed:
> tcp_early_demux, udp_early_demux
The other patch in the series has the same problem and should be dropped
too.
julia
>
> Check commit dddb64bcb346 ("net: Add sysctl to toggle early demux for
> tcp and udp") why at least 2 structures were no longer const.
>
> (none):~# echo 0 >/proc/sys/net/ipv4/udp_early_demux
> [ 101.746108] BUG: unable to handle kernel paging request at ffffffffb98cf5c0
> [ 101.753093] IP: proc_udp_early_demux+0x46/0x60
> [ 101.757565] PGD 13f540a067
> [ 101.757565] P4D 13f540a067
> [ 101.760372] PUD 13f540b063
> [ 101.763171] PMD 80000013f50001e1
> [ 101.765960]
> [ 101.770790] Oops: 0003 [#1] SMP
> [ 101.774376] gsmi: Log Shutdown Reason 0x03
> [ 101.778473] Modules linked in: w1_therm wire cdc_acm ehci_pci ehci_hcd mlx4_en ib_uverbs mlx4_ib ib_core mlx4_core
> [ 101.788890] CPU: 3 PID: 8819 Comm: bash Not tainted 4.13.0-smp-DEV #290
> [ 101.795549] Hardware name: Intel RML,PCH/Iota_QC_19, BIOS 2.40.0 06/22/2016
> [ 101.802517] task: ffff8e733b9c4140 task.stack: ffffa43548cd0000
> [ 101.808445] RIP: 0010:proc_udp_early_demux+0x46/0x60
> [ 101.813445] RSP: 0018:ffffa43548cd3e60 EFLAGS: 00010246
> [ 101.818676] RAX: 0000000000000000 RBX: 0000000000000001 RCX: 0000000000000000
> [ 101.825816] RDX: ffffffffb98cf5c0 RSI: 0000000000000000 RDI: ffff8e733f400100
> [ 101.832957] RBP: ffffa43548cd3e68 R08: 0000000000000000 R09: 0000000000000001
> [ 101.840096] R10: 0000000000000008 R11: f000000000000000 R12: 0000000000000001
> [ 101.847260] R13: ffffffffffffffea R14: 0000000000000002 R15: ffffffffb9d00380
> [ 101.854434] FS: 00007f7e1f34a700(0000) GS:ffff8e733f8c0000(0000) knlGS:0000000000000000
> [ 101.862518] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 101.868263] CR2: ffffffffb98cf5c0 CR3: 000000100f0c8000 CR4: 00000000001406e0
> [ 101.875439] Call Trace:
> [ 101.877888] proc_sys_call_handler+0xf3/0x190
> [ 101.882260] proc_sys_write+0x14/0x20
> [ 101.885944] vfs_write+0xc8/0x1e0
> [ 101.889261] SyS_write+0x48/0xa0
> [ 101.892520] entry_SYSCALL_64_fastpath+0x13/0x94
> [ 101.897137] RIP: 0033:0x7f7e1ebd64a0
> [ 101.900707] RSP: 002b:00007ffcbb851c58 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
> [ 101.908306] RAX: ffffffffffffffda RBX: 000000000232aba8 RCX: 00007f7e1ebd64a0
> [ 101.915437] RDX: 0000000000000002 RSI: 00000000022ea808 RDI: 0000000000000001
> [ 101.922567] RBP: 00007ffcbb851c50 R08: 00007f7e1ef691b0 R09: 00007f7e1f34a700
> [ 101.929698] R10: 000000000048926a R11: 0000000000000246 R12: 000000000232b288
> [ 101.936871] R13: 0000000002325e28 R14: 00000000022f0ce8 R15: 0000000000000000
> [ 101.944012] Code: 15 e8 07 84 00 8b 0d 9a 3c 7d 00 48 85 d2 74 09 31 f6 85 c9 75 21 48 89 32 48 8b 15 4d 30 84 00 48 85 d2 74 09 31 f6 85 c9 75 06 <48> 89 32 5b 5d c3 48 8b 72 08 eb f4 48 8b 72 08 eb d9 0f 1f 84
> [ 101.962907] RIP: proc_udp_early_demux+0x46/0x60 RSP: ffffa43548cd3e60
> [ 101.969353] CR2: ffffffffb98cf5c0
> [ 101.972680] ---[ end trace 116c0975bf9e19dd ]---
> [ 101.977307] Kernel panic - not syncing: Fatal exception
> [ 101.982590] Kernel Offset: 0x37e00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
>
>
>
^ permalink raw reply
* [GIT] Networking
From: David Miller @ 2017-08-01 5:16 UTC (permalink / raw)
To: torvalds; +Cc: akpm, netdev, linux-kernel
1) Handle notifier registry failures properly in tun/tap driver, from
Tonghao Zhang.
2) Fix bpf verifier handling of subtraction bounds and add a testcase
for this, from Edward Cree.
3) Increase reset timeout in ftgmac100 driver, from Ben Herrenschmidt.
4) Fix use after free in prd_retire_rx_blk_timer_exired() in AF_PACKET,
from Cong Wang.
5) Fix SElinux regression due to recent UDP optimizations, from Paolo
Abeni.
6) We accidently increment IPSTATS_MIB_FRAGFAILS in the ipv6 code paths,
fix from Stefano Brivio.
7) Fix some mem leaks in dccp, from Xin Long.
8) Adjust MDIO_BUS kconfig deps to avoid build errors, from Arnd
Bergmann.
9) Mac address length check and buffer size fixes from Cong Wang.
10) Don't leak sockets in ipv6 udp early demux, from Paolo Abeni.
11) Fix return value when copy_from_user() fails in
bpf_prog_get_info_by_fd(), from Daniel Borkmann.
12) Handle PHY_HALTED properly in phy library state machine, from
Florian Fainelli.
13) Fix OOPS in fib_sync_down_dev(), from Ido Schimmel.
14) Fix truesize calculation in virtio_net which led to performance
regressions, from Michael S. Tsirkin.
Please pull, thanks a lot!
The following changes since commit 96080f697786e0a30006fcbcc5b53f350fcb3e9f:
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net (2017-07-20 16:33:39 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
for you to fetch changes up to cc75f8514db6a3aec517760fccaf954e5b46478c:
samples/bpf: fix bpf tunnel cleanup (2017-07-31 22:02:47 -0700)
----------------------------------------------------------------
Alex Vesker (1):
net/mlx5e: IPoIB, Modify add/remove underlay QPN flows
Arend Van Spriel (2):
brcmfmac: fix regression in brcmf_sdio_txpkt_hdalign()
brcmfmac: fix memleak due to calling brcmf_sdiod_sgtable_alloc() twice
Arnd Bergmann (3):
net: phy: rework Kconfig settings for MDIO_BUS
phy: bcm-ns-usb3: fix MDIO_BUS dependency
tcp: avoid bogus gcc-7 array-bounds warning
Aviv Heller (1):
net/mlx5: Consider tx_enabled in all modes on remap
Benjamin Herrenschmidt (2):
ftgmac100: Increase reset timeout
ftgmac100: Make the MDIO bus a child of the ethernet device
Colin Ian King (1):
net: tc35815: fix spelling mistake: "Intterrupt" -> "Interrupt"
Dan Carpenter (1):
iwlwifi: missing error code in iwl_trans_pcie_alloc()
Daniel Borkmann (2):
bpf: don't indicate success when copy_from_user fails
bpf: fix bpf_prog_get_info_by_fd to dump correct xlated_prog_len
Daniel Stone (1):
brcmfmac: Don't grow SKB by negative size
David S. Miller (4):
Merge branch 'bpf-fix-verifier-min-max-handling-in-BPF_SUB'
Merge tag 'wireless-drivers-for-davem-2017-07-21' of git://git.kernel.org/.../kvalo/wireless-drivers
Merge tag 'mlx5-fixes-2017-07-27-V2' of git://git.kernel.org/.../saeed/linux
Merge tag 'wireless-drivers-for-davem-2017-07-28' of git://git.kernel.org/.../kvalo/wireless-drivers
Edward Cree (2):
selftests/bpf: subtraction bounds test
bpf/verifier: fix min/max handling in BPF_SUB
Emmanuel Grumbach (3):
iwlwifi: dvm: prevent an out of bounds access
iwlwifi: mvm: fix a NULL pointer dereference of error in recovery
iwlwifi: fix tracing when tx only is enabled
Eran Ben Elisha (1):
net/mlx5: Clean SRIOV eswitch resources upon VF creation failure
Eugenia Emantayev (7):
net/mlx5: Fix mlx5_ifc_mtpps_reg_bits structure size
net/mlx5e: Add field select to MTPPS register
net/mlx5e: Fix broken disable 1PPS flow
net/mlx5e: Change 1PPS out scheme
net/mlx5e: Add missing support for PTP_CLK_REQ_PPS request
net/mlx5e: Fix wrong delay calculation for overflow check scheduling
net/mlx5e: Schedule overflow check work to mlx5e workqueue
Florian Fainelli (4):
net: dsa: Initialize ds->cpu_port_mask earlier
net: phy: Correctly process PHY_HALTED in phy_stop_machine()
MAINTAINERS: Add more files to the PHY LIBRARY section
Revert "net: bcmgenet: Remove init parameter from bcmgenet_mii_config"
Gao Feng (1):
ppp: Fix a scheduling-while-atomic bug in del_chan
Ido Schimmel (2):
mlxsw: spectrum_router: Don't offload routes next in list
ipv4: fib: Fix NULL pointer deref during fib_sync_down_dev()
Ilan Tayari (1):
net/mlx5e: Fix outer_header_zero() check size
Jakub Kicinski (1):
bpf: don't zero out the info struct in bpf_obj_get_info_by_fd()
Jason Wang (1):
Revert "vhost: cache used event for better performance"
Joel Stanley (1):
ftgmac100: return error in ftgmac100_alloc_rx_buf
Johannes Berg (1):
iwlwifi: mvm: defer setting IWL_MVM_STATUS_IN_HW_RESTART
Kalle Valo (1):
Merge tag 'iwlwifi-for-kalle-2017-07-21' of git://git.kernel.org/.../iwlwifi/iwlwifi-fixes
Larry Finger (1):
Revert "rtlwifi: btcoex: rtl8723be: fix ant_sel not work"
Liping Zhang (1):
openvswitch: fix potential out of bound access in parse_ct
Luca Coelho (1):
iwlwifi: mvm: handle IBSS probe_queue in a few missing places
Marc Gonzalez (2):
net: phy: Remove trailing semicolon in macro definition
net: ethernet: nb8800: Handle all 4 RGMII modes identically
Mark Brown (1):
net: ethernet: mediatek: Explicitly include linux/interrupt.h
Mark Cave-Ayland (1):
sunhme: fix up GREG_STAT and GREG_IMASK register offsets
Matthias Kaehlcke (1):
netpoll: Fix device name check in netpoll_setup()
Michael S. Tsirkin (1):
virtio_net: fix truesize for mergeable buffers
Mordechai Goodstein (1):
iwlwifi: pcie: fix unused txq NULL pointer dereference
Moshe Shemesh (2):
net/mlx5: Fix command completion after timeout access invalid structure
net/mlx5: Fix command bad flow on command entry allocation failure
Paolo Abeni (5):
net/socket: fix type in assignment and trim long line
udp: preserve head state for IP_CMSG_PASSSEC
udp: unbreak build lacking CONFIG_XFRM
udp6: fix socket leak on early demux
udp6: fix jumbogram reception
Paul Blakey (1):
net/mlx5: Fix mlx5_add_flow_rules call with correct num of dests
Phil Sutter (2):
lib: test_rhashtable: fix for large entry counts
lib: test_rhashtable: Fix KASAN warning
Sean Wang (1):
net: ethernet: mediatek: avoid potential invalid memory access
Sergei Shtylyov (1):
mv643xx_eth: fix of_irq_to_resource() error check
Stefano Brivio (1):
ipv6: Don't increase IPSTATS_MIB_FRAGFAILS twice in ip6_fragment()
Sunil Goutham (1):
net: thunderx: Fix BGX transmit stall due to underflow
Thomas Jarosch (1):
mcs7780: Fix initialization when CONFIG_VMAP_STACK is enabled
Thor Thayer (1):
net: stmmac: Adjust dump offset of DMA registers for ethtool
Tonghao Zhang (1):
tun/tap: Add the missed return value check of register_netdevice_notifier
WANG Cong (4):
packet: fix use-after-free in prb_retire_rx_blk_timer_expired()
bonding: commit link status change after propose
net: check dev->addr_len for dev_set_mac_address()
team: use a larger struct for mac address
William Tu (1):
samples/bpf: fix bpf tunnel cleanup
Xin Long (4):
dccp: fix a memleak that dccp_ipv6 doesn't put reqsk properly
dccp: fix a memleak that dccp_ipv4 doesn't put reqsk properly
dccp: fix a memleak for dccp_feat_init err process
sctp: fix the check for _sctp_walk_params and _sctp_walk_errors
stephen hemminger (1):
Revert "netvsc: optimize calculation of number of slots"
MAINTAINERS | 14 +++--
drivers/net/bonding/bond_main.c | 2 +
drivers/net/ethernet/aurora/nb8800.c | 9 ++--
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 2 +-
drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 +-
drivers/net/ethernet/broadcom/genet/bcmmii.c | 7 +--
drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 27 ++++++++--
drivers/net/ethernet/cavium/thunder/thunder_bgx.h | 2 +
drivers/net/ethernet/faraday/ftgmac100.c | 7 +--
drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +-
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 5 ++
drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 25 +++++++--
drivers/net/ethernet/mellanox/mlx5/core/en.h | 10 +++-
drivers/net/ethernet/mellanox/mlx5/core/en_clock.c | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 1 -
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 3 +-
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 16 ++++--
drivers/net/ethernet/mellanox/mlx5/core/lag.c | 25 ++++-----
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h | 5 ++
drivers/net/ethernet/mellanox/mlx5/core/sriov.c | 5 ++
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 7 +++
drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h | 3 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 5 ++
drivers/net/ethernet/sun/sunhme.h | 6 +--
drivers/net/ethernet/toshiba/tc35815.c | 2 +-
drivers/net/hyperv/netvsc_drv.c | 43 +++++++++++----
drivers/net/irda/mcs7780.c | 16 ++++--
drivers/net/phy/Kconfig | 13 +++--
drivers/net/phy/phy.c | 3 ++
drivers/net/ppp/pptp.c | 2 +-
drivers/net/team/team.c | 8 +--
drivers/net/tun.c | 10 +++-
drivers/net/virtio_net.c | 5 +-
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 2 +-
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 8 +--
drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 2 +-
drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h | 4 +-
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 8 ++-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 6 +--
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 15 +++++-
drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 3 +-
drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 3 ++
drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 3 --
drivers/net/wireless/realtek/rtlwifi/wifi.h | 1 -
drivers/phy/broadcom/Kconfig | 2 +-
drivers/vhost/vhost.c | 28 +++-------
drivers/vhost/vhost.h | 3 --
include/linux/ipv6.h | 6 +++
include/linux/mlx5/mlx5_ifc.h | 10 ++--
include/linux/phy.h | 2 +-
include/net/sctp/sctp.h | 4 +-
include/net/udp.h | 34 ++++++++----
kernel/bpf/syscall.c | 4 +-
kernel/bpf/verifier.c | 21 +++++---
lib/test_rhashtable.c | 57 ++++++++++++--------
net/core/dev_ioctl.c | 2 +
net/core/netpoll.c | 2 +-
net/dccp/feat.c | 7 ++-
net/dccp/ipv4.c | 1 +
net/dccp/ipv6.c | 1 +
net/dsa/dsa2.c | 13 ++---
net/ipv4/fib_semantics.c | 2 +-
net/ipv4/tcp_output.c | 5 +-
net/ipv4/udp.c | 41 +++++++-------
net/ipv6/exthdrs.c | 1 +
net/ipv6/ip6_output.c | 4 --
net/ipv6/udp.c | 38 +++++++++----
net/openvswitch/conntrack.c | 7 ++-
net/packet/af_packet.c | 2 +-
net/socket.c | 5 +-
samples/bpf/tcbpf2_kern.c | 4 +-
samples/bpf/test_tunnel_bpf.sh | 1 +
tools/lib/bpf/bpf.c | 1 -
tools/testing/selftests/bpf/test_progs.c | 8 ++-
tools/testing/selftests/bpf/test_verifier.c | 28 ++++++++++
80 files changed, 629 insertions(+), 296 deletions(-)
^ permalink raw reply
* Re: [PATCH net] samples/bpf: fix bpf tunnel cleanup
From: David Miller @ 2017-08-01 5:02 UTC (permalink / raw)
To: u9012063; +Cc: netdev
In-Reply-To: <1501537250-26371-1-git-send-email-u9012063@gmail.com>
From: William Tu <u9012063@gmail.com>
Date: Mon, 31 Jul 2017 14:40:50 -0700
> test_tunnel_bpf.sh fails to remove the vxlan11 tunnel device, causing the
> next geneve tunnelling test case fails. In addition, the geneve reserved bit
> in tcbpf2_kern.c should be zero, according to the RFC.
>
> Signed-off-by: William Tu <u9012063@gmail.com>
Applied, thank you.
^ permalink raw reply
* Re: [PATCH net] udp6: fix jumbogram reception
From: David Miller @ 2017-08-01 5:01 UTC (permalink / raw)
To: pabeni; +Cc: netdev, lorenzo, dsa, david.lebrun, hannes
In-Reply-To: <70ca36ffa44fb8d6c369a1ab2866220916e2904a.1501512228.git.pabeni@redhat.com>
From: Paolo Abeni <pabeni@redhat.com>
Date: Mon, 31 Jul 2017 16:52:36 +0200
> Since commit 67a51780aebb ("ipv6: udp: leverage scratch area
> helpers") udp6_recvmsg() read the skb len from the scratch area,
> to avoid a cache miss.
> But the UDP6 rx path support RFC 2675 UDPv6 jumbograms, and their
> length exceeds the 16 bits available in the scratch area. As a side
> effect the length returned by recvmsg() is:
> <ingress datagram len> % (1<<16)
>
> This commit addresses the issue allocating one more bit in the
> IP6CB flags field and setting it for incoming jumbograms.
> Such field is still in the first cacheline, so at recvmsg()
> time we can check it and fallback to access skb->len if
> required, without a measurable overhead.
>
> Fixes: 67a51780aebb ("ipv6: udp: leverage scratch area helpers")
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Applied, thanks Paolo.
^ permalink raw reply
* Re: [PATCH net] ppp: Fix a scheduling-while-atomic bug in del_chan
From: David Miller @ 2017-08-01 4:59 UTC (permalink / raw)
To: gfree.wind; +Cc: xeb, netdev
In-Reply-To: <1501495658-119725-1-git-send-email-gfree.wind@vip.163.com>
From: gfree.wind@vip.163.com
Date: Mon, 31 Jul 2017 18:07:38 +0800
> From: Gao Feng <gfree.wind@vip.163.com>
>
> The PPTP set the pptp_sock_destruct as the sock's sk_destruct, it would
> trigger this bug when __sk_free is invoked in atomic context, because of
> the call path pptp_sock_destruct->del_chan->synchronize_rcu.
>
> Now move the synchronize_rcu to pptp_release from del_chan. This is the
> only one case which would free the sock and need the synchronize_rcu.
>
> The following is the panic I met with kernel 3.3.8, but this issue should
> exist in current kernel too according to the codes.
...
> Signed-off-by: Gao Feng <gfree.wind@vip.163.com>
Applied, thanks.
^ permalink raw reply
* Re: [patch net-next 09/20] net: sched: convert actions array into rcu list
From: Jiri Pirko @ 2017-08-01 4:59 UTC (permalink / raw)
To: Cong Wang
Cc: Linux Kernel Network Developers, David Miller, Jamal Hadi Salim,
Daniel Borkmann, mlxsw
In-Reply-To: <CAM_iQpWUUM1rj991FM2c2ruOTfgB3ed30AyQo2_KDtj5G8Ojiw@mail.gmail.com>
Mon, Jul 31, 2017 at 11:07:13PM CEST, xiyou.wangcong@gmail.com wrote:
>On Fri, Jul 28, 2017 at 7:40 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> From: Jiri Pirko <jiri@mellanox.com>
>>
>> Currently the actions are stored in array with array size. To traverse
>> this array in fastpath, tcf_tree_lock is taken to protect it. Convert
>> the array into a singly linked list, similar to the filter chains style
>> and allow traversal protected by rcu.
>
>Did you read commit 22dc13c837c33207548c8ee5116 ?
>
>An action can't be shared by multiple filters if you put them
>in a list (no matter singly or double), this is why I use pointers.
Allright. Will check it out.
^ permalink raw reply
* Re: [patch net-next 04/20] net: sched: use tcf_exts_has_actions in tcf_exts_exec
From: Jiri Pirko @ 2017-08-01 4:53 UTC (permalink / raw)
To: Cong Wang
Cc: Linux Kernel Network Developers, David Miller, Jamal Hadi Salim,
Daniel Borkmann, mlxsw
In-Reply-To: <CAM_iQpWRo1HG8WpZ-0zNferBe44yFpwoLpNWn5CKv9YuD9TKBQ@mail.gmail.com>
Mon, Jul 31, 2017 at 10:37:21PM CEST, xiyou.wangcong@gmail.com wrote:
>On Fri, Jul 28, 2017 at 7:40 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> +static inline int
>> +tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
>> + struct tcf_result *res)
>> +{
>> +#ifdef CONFIG_NET_CLS_ACT
>> + if (tcf_exts_has_actions(exts))
>> + return tcf_action_exec(skb, exts->actions, exts->nr_actions,
>> + res);
>> +#endif
>> + return 0;
>> +}
>
>
>While you are on it, can we get rid of this macro too?
>
>tcf_action_exec() is only defined with CONFIG_NET_CLS_ACT,
>not sure if compiler is kind enough to eliminate the false branch
>for us:
>
>if (false)
> return tcf_action_exec(...); // not defined but the branch is dead
>
>At least you can add a wrapper for tcf_action_exec() to just
>return 0.
Did you see?
net: sched: remove check for number of actions in tcf_exts_exec
I will add static inline stub for tcf_action_exec in case CONFIG_NET_CLS_ACT
is not set.
^ permalink raw reply
* Re: [PATCH net-next v12 0/4] net sched actions: improve dump performance
From: Stephen Hemminger @ 2017-08-01 3:54 UTC (permalink / raw)
To: Jamal Hadi Salim
Cc: David Miller, netdev, jiri, xiyou.wangcong, eric.dumazet, horms,
dsahern
In-Reply-To: <466dd890-ffae-4cdb-dc97-d173bd390148@mojatatu.com>
On Mon, 31 Jul 2017 08:06:42 -0400
Jamal Hadi Salim <jhs@mojatatu.com> wrote:
> On 17-07-30 10:28 PM, David Miller wrote:
> >
> > Series applied, thanks.
> >
>
> Thanks David.
>
> Attaching the iproute2 patch. I will submit an official one with
> man page changes later. Stephen - you take net-next changes?
>
> cheers,
> jamal
Please cleanup and resubmit for net-next.
The header files have been updated in iproute2 net-next branch.
It is not clear to me that the new code is backward compatiable.
Will new versions of tc work on old kernels and vice/versa?
Also, no #ifdef's
^ permalink raw reply
* Re: [PATCH RFC, iproute2] tc/mirred: Extend the mirred/redirect action to accept additional traffic class parameter
From: Stephen Hemminger @ 2017-08-01 3:51 UTC (permalink / raw)
To: Amritha Nambiar
Cc: netdev, alexander.h.duyck, kiran.patil, sridhar.samudrala,
mitch.a.williams, alexander.duyck, neerav.parikh, carolyn.wyborny,
jeffrey.t.kirsher
In-Reply-To: <150154805003.4819.12498976860683140342.stgit@anamdev.jf.intel.com>
On Mon, 31 Jul 2017 17:40:50 -0700
Amritha Nambiar <amritha.nambiar@intel.com> wrote:
The concept is fine, bu t the code looks different than the rest which
is never a good sign.
> + if ((argc > 0) && (matches(*argv, "tc") == 0)) {
Extra () are unnecessary in compound conditional.
> + tc = atoi(*argv);
Prefer using strtoul since it has better error handling than atoi()
> + argc--;
> + argv++;
> + }
Use NEXT_ARG() construct like rest of the code.
^ permalink raw reply
* (unknown),
From: helga.brickl @ 2017-08-01 3:31 UTC (permalink / raw)
To: netdev
[-- Attachment #1: EMAIL_0354141_netdev.zip --]
[-- Type: application/zip, Size: 2628 bytes --]
^ permalink raw reply
* Re: TCP fast retransmit issues
From: Neal Cardwell @ 2017-08-01 3:17 UTC (permalink / raw)
To: Willy Tarreau
Cc: Eric Dumazet, Klavs Klavsen, Netdev, Yuchung Cheng,
Nandita Dukkipati
In-Reply-To: <CADVnQym9JpC+vDVPVjP0ibhPQu3NhxsynRYA--FNzAgKJUJQSg@mail.gmail.com>
On Fri, Jul 28, 2017 at 6:54 PM, Neal Cardwell <ncardwell@google.com> wrote:
> On Wed, Jul 26, 2017 at 3:02 PM, Neal Cardwell <ncardwell@google.com> wrote:
>> On Wed, Jul 26, 2017 at 2:38 PM, Neal Cardwell <ncardwell@google.com> wrote:
>>> Yeah, it looks like I can reproduce this issue with (1) bad sacks
>>> causing repeated TLPs, and (2) TLPs timers being pushed out to later
>>> times due to incoming data. Scripts are attached.
>>
>> I'm testing a fix of only scheduling a TLP if (flag & FLAG_DATA_ACKED)
>> is true...
>
> An update for the TLP aspect of this thread: our team has a proposed
> fix for this RTO/TLP reschedule issue that we have reviewed internally
> and tested with our packetdrill test suite, including some new tests.
> The basic approach in the fix is as follows:
>
> a) only reschedule the xmit timer once per ACK
>
> b) only reschedule the xmit timer if tcp_clean_rtx_queue() deems this
> is safe (a packet was cumulatively ACKed, or we got a SACK for a
> packet that was sent before the most recent retransmit of the write
> queue head).
>
> After further review and testing we will post it. Hopefully next week.
The timer patches are upstream for review for the "net" branch:
https://patchwork.ozlabs.org/patch/796057/
https://patchwork.ozlabs.org/patch/796058/
https://patchwork.ozlabs.org/patch/796059/
Again, thank you for reporting this, and thanks for the packet trace!
neal
^ permalink raw reply
* [PATCH net-next 10/10] net: ipv6: Support for sockets bound to enslaved device
From: David Ahern @ 2017-08-01 3:13 UTC (permalink / raw)
To: netdev; +Cc: David Ahern
In-Reply-To: <1501557206-27503-1-git-send-email-dsahern@gmail.com>
Add support for sockets bound to a network interface enslaved to an
L3 Master device (e.g, VRF). Currently for VRF, skb->dev points to the
VRF device meaning socket lookups only consider this device index. The
real ingress device index is saved to IP6CB(skb)->iif and the VRF driver
marks the skb with IP6SKB_L3SLAVE to know that the real ingress device
is an enslaved one without having to lookup the iif.
Use those flags to add the enslaved device index to the socket lookup
and allow sk->sk_bound_dev_if to match either dif (VRF device) or sdif
(enslaved device).
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/linux/ipv6.h | 8 ++++++++
include/net/inet6_hashtables.h | 5 +++--
include/net/tcp.h | 7 +++++++
net/ipv6/inet6_hashtables.c | 9 +++++----
net/ipv6/raw.c | 5 ++++-
net/ipv6/tcp_ipv6.c | 3 +++
net/ipv6/udp.c | 8 ++++++--
7 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index e1b442996f81..094357907b45 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -153,6 +153,14 @@ static inline int inet6_iif(const struct sk_buff *skb)
}
/* can not be used in TCP layer after tcp_v6_fill_cb */
+static inline int inet6_sdif(const struct sk_buff *skb)
+{
+ bool l3_slave = ipv6_l3mdev_skb(IP6CB(skb)->flags);
+
+ return l3_slave ? IP6CB(skb)->iif : 0;
+}
+
+/* can not be used in TCP layer after tcp_v6_fill_cb */
static inline bool inet6_exact_dif_match(struct net *net, struct sk_buff *skb)
{
#if defined(CONFIG_NET_L3_MASTER_DEV)
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 15db41272ff2..0fc5a2fe4ad3 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -94,13 +94,14 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
int inet6_hash(struct sock *sk);
#endif /* IS_ENABLED(CONFIG_IPV6) */
-#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif) \
+#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif, __sdif) \
(((__sk)->sk_portpair == (__ports)) && \
((__sk)->sk_family == AF_INET6) && \
ipv6_addr_equal(&(__sk)->sk_v6_daddr, (__saddr)) && \
ipv6_addr_equal(&(__sk)->sk_v6_rcv_saddr, (__daddr)) && \
(!(__sk)->sk_bound_dev_if || \
- ((__sk)->sk_bound_dev_if == (__dif))) && \
+ ((__sk)->sk_bound_dev_if == (__dif)) || \
+ ((__sk)->sk_bound_dev_if == (__sdif))) && \
net_eq(sock_net(__sk), (__net)))
#endif /* _INET6_HASHTABLES_H */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 19827dd05dcc..8a081cff33f8 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -848,6 +848,13 @@ static inline int tcp_v6_iif(const struct sk_buff *skb)
return l3_slave ? skb->skb_iif : TCP_SKB_CB(skb)->header.h6.iif;
}
+
+static inline int tcp_v6_sdif(const struct sk_buff *skb)
+{
+ bool l3_slave = ipv6_l3mdev_skb(TCP_SKB_CB(skb)->header.h6.flags);
+
+ return l3_slave ? TCP_SKB_CB(skb)->header.h6.iif : 0;
+}
#endif
/* TCP_SKB_CB reference means this can not be used from early demux */
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 878c03094f2e..06120efb2036 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -74,13 +74,13 @@ struct sock *__inet6_lookup_established(struct net *net,
if (sk->sk_hash != hash)
continue;
if (!INET6_MATCH(sk, net, saddr, daddr, ports,
- params->dif))
+ params->dif, params->sdif))
continue;
if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
goto out;
if (unlikely(!INET6_MATCH(sk, net, saddr, daddr, ports,
- params->dif))) {
+ params->dif, params->sdif))) {
sock_gen_put(sk);
goto begin;
}
@@ -188,8 +188,9 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
const struct in6_addr *daddr = &sk->sk_v6_rcv_saddr;
const struct in6_addr *saddr = &sk->sk_v6_daddr;
const int dif = sk->sk_bound_dev_if;
- const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport);
struct net *net = sock_net(sk);
+ const int sdif = l3mdev_master_ifindex_by_index(net, dif);
+ const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport);
const unsigned int hash = inet6_ehashfn(net, daddr, lport, saddr,
inet->inet_dport);
struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
@@ -205,7 +206,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
continue;
if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports,
- dif))) {
+ dif, sdif))) {
if (sk2->sk_state == TCP_TIME_WAIT) {
tw = inet_twsk(sk2);
if (twsk_unique(sk, sk2, twp))
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 51e651f18ffb..bab365214d17 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -87,7 +87,8 @@ struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
continue;
if (sk->sk_bound_dev_if &&
- sk->sk_bound_dev_if != params->dif)
+ sk->sk_bound_dev_if != params->dif &&
+ sk->sk_bound_dev_if != params->sdif)
continue;
if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
@@ -165,6 +166,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
.daddr.ipv6 = &ipv6_hdr(skb)->daddr,
.hnum = nexthdr,
.dif = inet6_iif(skb),
+ .sdif = inet6_sdif(skb),
};
struct sock *sk;
bool delivered = false;
@@ -375,6 +377,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
struct sk_lookup params = {
.hnum = nexthdr,
.dif = inet6_iif(skb),
+ .sdif = inet6_sdif(skb),
};
/* Note: ipv6_hdr(skb) != skb->data */
const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 19fee98e1ae0..67bd95cec4ec 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -917,6 +917,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
.sport = th->source,
.hnum = ntohs(th->source),
.dif = tcp_v6_iif(skb),
+ .sdif = tcp_v6_sdif(skb),
};
/*
@@ -1414,6 +1415,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
struct net *net = dev_net(skb->dev);
struct sk_lookup params = {
.dif = inet6_iif(skb),
+ .sdif = inet6_sdif(skb),
};
if (skb->pkt_type != PACKET_HOST)
@@ -1577,6 +1579,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
.sport = th->source,
.hnum = ntohs(th->dest),
.dif = tcp_v6_iif(skb),
+ .sdif = tcp_v6_sdif(skb),
};
struct sock *sk2;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 00b362a8bd91..8cf7c5cbd02a 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -220,6 +220,7 @@ struct sock *__udp6_lib_lookup(struct net *net, struct sk_lookup *params,
u32 hash = 0;
params->hnum = hnum;
+ params->sdif = inet6_sdif(skb);
params->exact_dif = udp6_lib_exact_dif_match(net, skb);
if (hslot->count > 10) {
@@ -673,7 +674,8 @@ static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk,
(inet->inet_dport && inet->inet_dport != params->sport) ||
(!ipv6_addr_any(&sk->sk_v6_daddr) &&
!ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) ||
- (sk->sk_bound_dev_if && sk->sk_bound_dev_if != params->dif) ||
+ (sk->sk_bound_dev_if && sk->sk_bound_dev_if != params->dif &&
+ sk->sk_bound_dev_if != params->sdif) ||
(!ipv6_addr_any(&sk->sk_v6_rcv_saddr) &&
!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)))
return false;
@@ -715,6 +717,7 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
.dport = uh->dest,
.hnum = hnum,
.dif = inet6_iif(skb),
+ .sdif = inet6_sdif(skb),
};
if (use_hash2) {
@@ -893,7 +896,7 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net,
if (sk->sk_state == TCP_ESTABLISHED &&
INET6_MATCH(sk, net, params->saddr.ipv6,
params->daddr.ipv6, ports,
- params->dif))
+ params->dif, params->sdif))
return sk;
/* Only check first socket in chain */
@@ -912,6 +915,7 @@ static void udp_v6_early_demux(struct sk_buff *skb)
.saddr.ipv6 = &ipv6_hdr(skb)->saddr,
.daddr.ipv6 = &ipv6_hdr(skb)->daddr,
.dif = skb->dev->ifindex,
+ .sdif = inet6_sdif(skb),
};
if (skb->pkt_type != PACKET_HOST)
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 09/10] net: ipv4: Support for sockets bound to enslaved device
From: David Ahern @ 2017-08-01 3:13 UTC (permalink / raw)
To: netdev; +Cc: David Ahern
In-Reply-To: <1501557206-27503-1-git-send-email-dsahern@gmail.com>
Add support for sockets bound to a network interface enslaved to an
L3 Master device (e.g, VRF). Currently for VRF, skb->dev points to the
VRF device meaning socket lookups only consider this device index. The
real ingress device index is saved to IPCB(skb)->iif and the VRF driver
marks the skb with IPSKB_L3SLAVE to know that the real ingress device
is an enslaved one without having to lookup the iif.
Use those flags to add the enslaved device index to the socket lookup
and allow sk->sk_bound_dev_if to match either dif (VRF device) or sdif
(enslaved device).
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/linux/igmp.h | 3 ++-
include/net/inet_hashtables.h | 10 ++++++----
include/net/ip.h | 10 ++++++++++
include/net/tcp.h | 10 ++++++++++
net/ipv4/igmp.c | 6 ++++--
net/ipv4/inet_hashtables.c | 11 +++++++----
net/ipv4/raw.c | 7 +++++--
net/ipv4/tcp_ipv4.c | 6 ++++--
net/ipv4/udp.c | 11 ++++++++---
9 files changed, 56 insertions(+), 18 deletions(-)
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 97caf1821de8..f8231854b5d6 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -118,7 +118,8 @@ extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
struct ip_msfilter __user *optval, int __user *optlen);
extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
struct group_filter __user *optval, int __user *optlen);
-extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt, int dif);
+extern int ip_mc_sf_allow(struct sock *sk, __be32 local, __be32 rmt,
+ int dif, int sdif);
extern void ip_mc_init_dev(struct in_device *);
extern void ip_mc_destroy_dev(struct in_device *);
extern void ip_mc_up(struct in_device *);
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index c5f4dc3c06e4..2de3d4bc00ba 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -259,22 +259,24 @@ static inline struct sock *inet_lookup_listener(struct net *net,
(((__force __u64)(__be32)(__daddr)) << 32) | \
((__force __u64)(__be32)(__saddr)))
#endif /* __BIG_ENDIAN */
-#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \
(((__sk)->sk_portpair == (__ports)) && \
((__sk)->sk_addrpair == (__cookie)) && \
(!(__sk)->sk_bound_dev_if || \
- ((__sk)->sk_bound_dev_if == (__dif))) && \
+ ((__sk)->sk_bound_dev_if == (__dif)) || \
+ ((__sk)->sk_bound_dev_if == (__sdif))) && \
net_eq(sock_net(__sk), (__net)))
#else /* 32-bit arch */
#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
const int __name __deprecated __attribute__((unused))
-#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif, __sdif) \
(((__sk)->sk_portpair == (__ports)) && \
((__sk)->sk_daddr == (__saddr)) && \
((__sk)->sk_rcv_saddr == (__daddr)) && \
(!(__sk)->sk_bound_dev_if || \
- ((__sk)->sk_bound_dev_if == (__dif))) && \
+ ((__sk)->sk_bound_dev_if == (__dif)) || \
+ ((__sk)->sk_bound_dev_if == (__sdif))) && \
net_eq(sock_net(__sk), (__net)))
#endif /* 64-bit arch */
diff --git a/include/net/ip.h b/include/net/ip.h
index 821cedcc8e73..e10da8814dba 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -78,6 +78,16 @@ struct ipcm_cookie {
#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
#define PKTINFO_SKB_CB(skb) ((struct in_pktinfo *)((skb)->cb))
+/* return enslaved device index if relevant */
+static inline int ip_sdif(struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+ if (skb && ipv4_l3mdev_skb(IPCB(skb)->flags))
+ return IPCB(skb)->iif;
+#endif
+ return 0;
+}
+
struct ip_ra_chain {
struct ip_ra_chain __rcu *next;
struct sock *sk;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 12d68335acd4..19827dd05dcc 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -861,6 +861,16 @@ static inline bool inet_exact_dif_match(struct net *net, struct sk_buff *skb)
return false;
}
+/* TCP_SKB_CB reference means this can not be used from early demux */
+static inline int tcp_v4_sdif(struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+ if (skb && ipv4_l3mdev_skb(TCP_SKB_CB(skb)->header.h4.flags))
+ return TCP_SKB_CB(skb)->header.h4.iif;
+#endif
+ return 0;
+}
+
/* Due to TSO, an SKB can be composed of multiple actual
* packets. To keep these tracked properly, we use this.
*/
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 28f14afd0dd3..5bc8570c2ec3 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -2549,7 +2549,8 @@ int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
/*
* check if a multicast source filter allows delivery for a given <src,dst,intf>
*/
-int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
+int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr,
+ int dif, int sdif)
{
struct inet_sock *inet = inet_sk(sk);
struct ip_mc_socklist *pmc;
@@ -2564,7 +2565,8 @@ int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
rcu_read_lock();
for_each_pmc_rcu(inet, pmc) {
if (pmc->multi.imr_multiaddr.s_addr == loc_addr &&
- pmc->multi.imr_ifindex == dif)
+ (pmc->multi.imr_ifindex == dif ||
+ (sdif && pmc->multi.imr_ifindex == sdif)))
break;
}
ret = inet->mc_all;
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 5fe9300795b8..12c387264a65 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -275,6 +275,7 @@ struct sock *__inet_lookup_established(struct net *net,
__be32 daddr = params->daddr.ipv4;
__be16 sport = params->sport;
u16 hnum = params->hnum;
+ int sdif = params->sdif;
int dif = params->dif;
INET_ADDR_COOKIE(acookie, saddr, daddr);
const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
@@ -292,11 +293,12 @@ struct sock *__inet_lookup_established(struct net *net,
if (sk->sk_hash != hash)
continue;
if (likely(INET_MATCH(sk, net, acookie,
- saddr, daddr, ports, dif))) {
+ saddr, daddr, ports, dif, sdif))) {
if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
goto out;
if (unlikely(!INET_MATCH(sk, net, acookie,
- saddr, daddr, ports, dif))) {
+ saddr, daddr, ports,
+ dif, sdif))) {
sock_gen_put(sk);
goto begin;
}
@@ -327,9 +329,10 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
__be32 daddr = inet->inet_rcv_saddr;
__be32 saddr = inet->inet_daddr;
int dif = sk->sk_bound_dev_if;
+ struct net *net = sock_net(sk);
+ int sdif = l3mdev_master_ifindex_by_index(net, dif);
INET_ADDR_COOKIE(acookie, saddr, daddr);
const __portpair ports = INET_COMBINED_PORTS(inet->inet_dport, lport);
- struct net *net = sock_net(sk);
unsigned int hash = inet_ehashfn(net, daddr, lport,
saddr, inet->inet_dport);
struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
@@ -345,7 +348,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
continue;
if (likely(INET_MATCH(sk2, net, acookie,
- saddr, daddr, ports, dif))) {
+ saddr, daddr, ports, dif, sdif))) {
if (sk2->sk_state == TCP_TIME_WAIT) {
tw = inet_twsk(sk2);
if (twsk_unique(sk, sk2, twp))
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 4da5d87a61a5..a94f8f115b6e 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -132,7 +132,8 @@ struct sock *__raw_v4_lookup(struct net *net, struct sock *sk,
bool dev_match;
dev_match = (!sk->sk_bound_dev_if ||
- sk->sk_bound_dev_if == params->dif);
+ sk->sk_bound_dev_if == params->dif ||
+ sk->sk_bound_dev_if == params->sdif);
if (net_eq(sock_net(sk), net) &&
inet->inet_num == params->hnum &&
@@ -186,6 +187,7 @@ static int __raw_v4_input(struct sk_buff *skb, const struct iphdr *iph,
.daddr.ipv4 = iph->daddr,
.hnum = iph->protocol,
.dif = skb->dev->ifindex,
+ .sdif = ip_sdif(skb),
};
int delivered = 0;
struct sock *sk;
@@ -195,7 +197,7 @@ static int __raw_v4_input(struct sk_buff *skb, const struct iphdr *iph,
delivered = 1;
if ((iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) &&
ip_mc_sf_allow(sk, iph->daddr, iph->saddr,
- skb->dev->ifindex)) {
+ skb->dev->ifindex, params.sdif)) {
struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
/* Not releasing hash table! */
@@ -316,6 +318,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
struct sk_lookup params = {
.hnum = protocol,
.dif = skb->dev->ifindex,
+ .sdif = ip_sdif(skb),
};
iph = (const struct iphdr *)skb->data;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a83d1d437abc..415722007a24 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1664,7 +1664,9 @@ EXPORT_SYMBOL(tcp_filter);
int tcp_v4_rcv(struct sk_buff *skb)
{
struct net *net = dev_net(skb->dev);
- struct sk_lookup params = { };
+ struct sk_lookup params = {
+ .sdif = ip_sdif(skb),
+ };
const struct iphdr *iph;
const struct tcphdr *th;
bool refcounted;
@@ -1846,8 +1848,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
.daddr.ipv4 = iph->daddr,
.sport = th->source,
.dport = th->dest,
- .hnum = ntohs(th->dest),
.dif = inet_iif(skb),
+ .sdif = tcp_v4_sdif(skb),
};
struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
&tcp_hashinfo, skb,
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 132a8f070d16..5c9fffed9c4a 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -485,6 +485,7 @@ struct sock *__udp4_lib_lookup(struct net *net, struct sk_lookup *params,
u32 hash = 0;
params->hnum = hnum;
+ params->sdif = ip_sdif(skb);
params->exact_dif = udp_lib_exact_dif_match(net, skb);
if (hslot->count > 10) {
@@ -597,9 +598,10 @@ static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk,
(inet->inet_dport != params->sport && inet->inet_dport) ||
(inet->inet_rcv_saddr && inet->inet_rcv_saddr != loc_addr) ||
ipv6_only_sock(sk) ||
- (sk->sk_bound_dev_if && sk->sk_bound_dev_if != params->dif))
+ (sk->sk_bound_dev_if && sk->sk_bound_dev_if != params->dif &&
+ sk->sk_bound_dev_if != params->sdif))
return false;
- if (!ip_mc_sf_allow(sk, loc_addr, rmt_addr, params->dif))
+ if (!ip_mc_sf_allow(sk, loc_addr, rmt_addr, params->dif, params->sdif))
return false;
return true;
}
@@ -1970,6 +1972,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
.dport = uh->dest,
.hnum = hnum,
.dif = skb->dev->ifindex,
+ .sdif = ip_sdif(skb),
};
if (use_hash2) {
@@ -2210,7 +2213,8 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
if (INET_MATCH(sk, net, acookie, params->saddr.ipv4,
- params->daddr.ipv4, ports, params->dif))
+ params->daddr.ipv4, ports, params->dif,
+ params->sdif))
return sk;
/* Only check first socket in chain */
break;
@@ -2223,6 +2227,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
struct net *net = dev_net(skb->dev);
struct sk_lookup params = {
.dif = skb->dev->ifindex,
+ .sdif = ip_sdif(skb),
};
const struct iphdr *iph;
const struct udphdr *uh;
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 08/10] net: Add sdif to sk_lookup
From: David Ahern @ 2017-08-01 3:13 UTC (permalink / raw)
To: netdev; +Cc: David Ahern
In-Reply-To: <1501557206-27503-1-git-send-email-dsahern@gmail.com>
Add a second device index, sdif, to the socket lookup struct. sdif
will be the device index for devices enslaved to an l3mdev. It allows
the lookups to consider the enslaved device as well as the L3 master
device when searching for a socket.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/sock.h | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index a2db5fd30192..c5d93a4bcd0a 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -507,23 +507,27 @@ struct sk_lookup {
unsigned short hnum;
int dif;
+ int sdif;
bool exact_dif;
};
-/* Compare sk_bound_dev_if to socket lookup dif
+/* Compare sk_bound_dev_if to socket lookup dif and sdif
* Returns:
* -1 exact dif required and not met
* 0 sk_bound_dev_if is either not set or does not match
- * 1 sk_bound_dev_if is set and matches dif
+ * 1 sk_bound_dev_if is set and matches dif or sdif
*/
static inline int sk_lookup_device_cmp(const struct sock *sk,
const struct sk_lookup *params)
{
+ bool dev_match = (sk->sk_bound_dev_if == params->dif ||
+ sk->sk_bound_dev_if == params->sdif);
+
/* exact_dif true == l3mdev case */
- if (params->exact_dif && sk->sk_bound_dev_if != params->dif)
+ if (params->exact_dif && !dev_match)
return -1;
- if (sk->sk_bound_dev_if && sk->sk_bound_dev_if == params->dif)
+ if (sk->sk_bound_dev_if && dev_match)
return 1;
return 0;
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 07/10] net: ipv6: Convert raw sockets to sk_lookup
From: David Ahern @ 2017-08-01 3:13 UTC (permalink / raw)
To: netdev; +Cc: David Ahern
In-Reply-To: <1501557206-27503-1-git-send-email-dsahern@gmail.com>
Convert __raw_v6_lookup to use the new sk_lookup struct
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/rawv6.h | 3 +--
net/ipv4/raw_diag.c | 15 ++++++++++-----
net/ipv6/raw.c | 41 +++++++++++++++++++++++------------------
3 files changed, 34 insertions(+), 25 deletions(-)
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index cbe4e9de1894..406268324d26 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -5,8 +5,7 @@
extern struct raw_hashinfo raw_v6_hashinfo;
struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
- unsigned short num, const struct in6_addr *loc_addr,
- const struct in6_addr *rmt_addr, int dif);
+ const struct sk_lookup *params);
int raw_abort(struct sock *sk, int err);
diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c
index a708de070cc6..e081c03fd408 100644
--- a/net/ipv4/raw_diag.c
+++ b/net/ipv4/raw_diag.c
@@ -53,11 +53,16 @@ static struct sock *raw_lookup(struct net *net, struct sock *from,
sk = __raw_v4_lookup(net, from, ¶ms);
}
#if IS_ENABLED(CONFIG_IPV6)
- else
- sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol,
- (const struct in6_addr *)r->id.idiag_src,
- (const struct in6_addr *)r->id.idiag_dst,
- r->id.idiag_if);
+ else {
+ struct sk_lookup params = {
+ .saddr.ipv6 = (const struct in6_addr *)r->id.idiag_dst,
+ .daddr.ipv6 = (const struct in6_addr *)r->id.idiag_src,
+ .hnum = r->sdiag_raw_protocol,
+ .dif = r->id.idiag_if,
+ };
+
+ sk = __raw_v6_lookup(net, from, ¶ms);
+ }
#endif
return sk;
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 60be012fe708..51e651f18ffb 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -71,14 +71,14 @@ struct raw_hashinfo raw_v6_hashinfo = {
EXPORT_SYMBOL_GPL(raw_v6_hashinfo);
struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
- unsigned short num, const struct in6_addr *loc_addr,
- const struct in6_addr *rmt_addr, int dif)
+ const struct sk_lookup *params)
{
+ const struct in6_addr *loc_addr = params->daddr.ipv6;
+ const struct in6_addr *rmt_addr = params->saddr.ipv6;
bool is_multicast = ipv6_addr_is_multicast(loc_addr);
sk_for_each_from(sk)
- if (inet_sk(sk)->inet_num == num) {
-
+ if (inet_sk(sk)->inet_num == params->hnum) {
if (!net_eq(sock_net(sk), net))
continue;
@@ -86,7 +86,8 @@ struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
!ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr))
continue;
- if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)
+ if (sk->sk_bound_dev_if &&
+ sk->sk_bound_dev_if != params->dif)
continue;
if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
@@ -159,15 +160,17 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister);
*/
static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
{
- const struct in6_addr *saddr;
- const struct in6_addr *daddr;
+ struct sk_lookup params = {
+ .saddr.ipv6 = &ipv6_hdr(skb)->saddr,
+ .daddr.ipv6 = &ipv6_hdr(skb)->daddr,
+ .hnum = nexthdr,
+ .dif = inet6_iif(skb),
+ };
struct sock *sk;
bool delivered = false;
__u8 hash;
struct net *net;
- saddr = &ipv6_hdr(skb)->saddr;
- daddr = saddr + 1;
hash = nexthdr & (RAW_HTABLE_SIZE - 1);
@@ -178,7 +181,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
goto out;
net = dev_net(skb->dev);
- sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, inet6_iif(skb));
+ sk = __raw_v6_lookup(net, sk, ¶ms);
while (sk) {
int filtered;
@@ -221,8 +224,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
rawv6_rcv(sk, clone);
}
}
- sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr,
- inet6_iif(skb));
+ sk = __raw_v6_lookup(net, sk_next(sk), ¶ms);
}
out:
read_unlock(&raw_v6_hashinfo.lock);
@@ -362,23 +364,26 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
u8 type, u8 code, int inner_offset, __be32 info)
{
struct sock *sk;
- int hash;
- const struct in6_addr *saddr, *daddr;
struct net *net;
+ int hash;
hash = nexthdr & (RAW_HTABLE_SIZE - 1);
read_lock(&raw_v6_hashinfo.lock);
sk = sk_head(&raw_v6_hashinfo.ht[hash]);
if (sk) {
+ struct sk_lookup params = {
+ .hnum = nexthdr,
+ .dif = inet6_iif(skb),
+ };
/* Note: ipv6_hdr(skb) != skb->data */
const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data;
- saddr = &ip6h->saddr;
- daddr = &ip6h->daddr;
+
+ params.daddr.ipv6 = &ip6h->saddr;
+ params.saddr.ipv6 = &ip6h->daddr;
net = dev_net(skb->dev);
- while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr,
- inet6_iif(skb)))) {
+ while ((sk = __raw_v6_lookup(net, sk, ¶ms))) {
rawv6_err(sk, skb, NULL, type, code,
inner_offset, info);
sk = sk_next(sk);
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 06/10] net: ipv6: Convert inet socket lookups to new struct
From: David Ahern @ 2017-08-01 3:13 UTC (permalink / raw)
To: netdev; +Cc: David Ahern
In-Reply-To: <1501557206-27503-1-git-send-email-dsahern@gmail.com>
Convert the various inet6_lookup functions to use the new sk_lookup
struct.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/net/inet6_hashtables.h | 39 +++++++-------------
net/dccp/ipv6.c | 22 ++++++++----
net/ipv4/inet_diag.c | 19 ++++++----
net/ipv4/udp_diag.c | 2 ++
net/ipv6/inet6_hashtables.c | 72 +++++++++++++++++++------------------
net/ipv6/netfilter/nf_socket_ipv6.c | 5 ++-
net/ipv6/tcp_ipv6.c | 60 +++++++++++++++++++++----------
net/netfilter/xt_TPROXY.c | 8 ++---
8 files changed, 125 insertions(+), 102 deletions(-)
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index b87becacd9d3..15db41272ff2 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -46,63 +46,50 @@ static inline unsigned int __inet6_ehashfn(const u32 lhash,
*/
struct sock *__inet6_lookup_established(struct net *net,
struct inet_hashinfo *hashinfo,
- const struct in6_addr *saddr,
- const __be16 sport,
- const struct in6_addr *daddr,
- const u16 hnum, const int dif);
+ const struct sk_lookup *params);
struct sock *inet6_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
- const struct in6_addr *saddr,
- const __be16 sport,
- const struct in6_addr *daddr,
- const unsigned short hnum, const int dif);
+ struct sk_lookup *params);
static inline struct sock *__inet6_lookup(struct net *net,
struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
- const struct in6_addr *saddr,
- const __be16 sport,
- const struct in6_addr *daddr,
- const u16 hnum,
- const int dif,
+ struct sk_lookup *params,
bool *refcounted)
{
- struct sock *sk = __inet6_lookup_established(net, hashinfo, saddr,
- sport, daddr, hnum, dif);
+ struct sock *sk = __inet6_lookup_established(net, hashinfo, params);
+
*refcounted = true;
if (sk)
return sk;
*refcounted = false;
- return inet6_lookup_listener(net, hashinfo, skb, doff, saddr, sport,
- daddr, hnum, dif);
+ return inet6_lookup_listener(net, hashinfo, skb, doff, params);
}
static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
- const __be16 sport,
- const __be16 dport,
- int iif,
+ struct sk_lookup *params,
bool *refcounted)
{
struct sock *sk = skb_steal_sock(skb);
+ params->saddr.ipv6 = &ipv6_hdr(skb)->saddr,
+ params->daddr.ipv6 = &ipv6_hdr(skb)->daddr,
+ params->hnum = ntohs(params->dport),
+
*refcounted = true;
if (sk)
return sk;
return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb,
- doff, &ipv6_hdr(skb)->saddr, sport,
- &ipv6_hdr(skb)->daddr, ntohs(dport),
- iif, refcounted);
+ doff, params, refcounted);
}
struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
- const struct in6_addr *saddr, const __be16 sport,
- const struct in6_addr *daddr, const __be16 dport,
- const int dif);
+ struct sk_lookup *params);
int inet6_hash(struct sock *sk);
#endif /* IS_ENABLED(CONFIG_IPV6) */
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index c376af5bfdfb..e92f10a832dd 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -70,6 +70,11 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
u8 type, u8 code, int offset, __be32 info)
{
const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
+ struct sk_lookup params = {
+ .saddr.ipv6 = &hdr->daddr,
+ .daddr.ipv6 = &hdr->saddr,
+ .dif = inet6_iif(skb),
+ };
const struct dccp_hdr *dh;
struct dccp_sock *dp;
struct ipv6_pinfo *np;
@@ -86,11 +91,10 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
BUILD_BUG_ON(offsetofend(struct dccp_hdr, dccph_dport) > 8);
dh = (struct dccp_hdr *)(skb->data + offset);
- sk = __inet6_lookup_established(net, &dccp_hashinfo,
- &hdr->daddr, dh->dccph_dport,
- &hdr->saddr, ntohs(dh->dccph_sport),
- inet6_iif(skb));
-
+ params.sport = dh->dccph_dport;
+ params.dport = dh->dccph_sport;
+ params.hnum = ntohs(dh->dccph_sport);
+ sk = __inet6_lookup_established(net, &dccp_hashinfo, ¶ms);
if (!sk) {
__ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
ICMP6_MIB_INERRORS);
@@ -656,6 +660,9 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
static int dccp_v6_rcv(struct sk_buff *skb)
{
+ struct sk_lookup params = {
+ .dif = inet6_iif(skb),
+ };
const struct dccp_hdr *dh;
bool refcounted;
struct sock *sk;
@@ -683,10 +690,11 @@ static int dccp_v6_rcv(struct sk_buff *skb)
else
DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
+ params.sport = dh->dccph_sport;
+ params.dport = dh->dccph_dport;
lookup:
sk = __inet6_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh),
- dh->dccph_sport, dh->dccph_dport,
- inet6_iif(skb), &refcounted);
+ ¶ms, &refcounted);
if (!sk) {
dccp_pr_debug("failed to look up flow ID in table and "
"get corresponding socket\n");
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 6c3bc4e408d0..c1ec0d3cc4b9 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -422,13 +422,18 @@ struct sock *inet_diag_find_one_icsk(struct net *net,
};
sk = inet_lookup(net, hashinfo, NULL, 0, ¶ms);
- } else
- sk = inet6_lookup(net, hashinfo, NULL, 0,
- (struct in6_addr *)req->id.idiag_dst,
- req->id.idiag_dport,
- (struct in6_addr *)req->id.idiag_src,
- req->id.idiag_sport,
- req->id.idiag_if);
+ } else {
+ struct sk_lookup params = {
+ .saddr.ipv6 = (struct in6_addr *)req->id.idiag_dst,
+ .daddr.ipv6 = (struct in6_addr *)req->id.idiag_src,
+ .sport = req->id.idiag_dport,
+ .dport = req->id.idiag_sport,
+ .hnum = ntohs(req->id.idiag_sport),
+ .dif = req->id.idiag_if,
+ };
+
+ sk = inet6_lookup(net, hashinfo, NULL, 0, ¶ms);
+ }
}
#endif
else {
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 10738c10c5ae..bd358f9dde1f 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -60,6 +60,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
.daddr.ipv6 = (struct in6_addr *)req->id.idiag_dst,
.sport = req->id.idiag_sport,
.dport = req->id.idiag_dport,
+ .hnum = ntohs(req->id.idiag_dport),
.dif = req->id.idiag_if,
};
@@ -221,6 +222,7 @@ static int __udp_diag_destroy(struct sk_buff *in_skb,
.daddr.ipv6 = (struct in6_addr *)req->id.idiag_src,
.sport = req->id.idiag_dport,
.dport = req->id.idiag_sport,
+ .hnum = ntohs(req->id.idiag_sport),
.dif = req->id.idiag_if,
};
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index b13b8f93079d..878c03094f2e 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -52,33 +52,35 @@ u32 inet6_ehashfn(const struct net *net,
*/
struct sock *__inet6_lookup_established(struct net *net,
struct inet_hashinfo *hashinfo,
- const struct in6_addr *saddr,
- const __be16 sport,
- const struct in6_addr *daddr,
- const u16 hnum,
- const int dif)
+ const struct sk_lookup *params)
{
+ const __portpair ports = INET_COMBINED_PORTS(params->sport,
+ params->hnum);
+ const struct in6_addr *saddr = params->saddr.ipv6;
+ const struct in6_addr *daddr = params->daddr.ipv6;
struct sock *sk;
const struct hlist_nulls_node *node;
- const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
+
/* Optimize here for direct hit, only listening connections can
* have wildcards anyways.
*/
- unsigned int hash = inet6_ehashfn(net, daddr, hnum, saddr, sport);
+ unsigned int hash = inet6_ehashfn(net, daddr, params->hnum,
+ saddr, params->sport);
unsigned int slot = hash & hashinfo->ehash_mask;
struct inet_ehash_bucket *head = &hashinfo->ehash[slot];
-
begin:
sk_nulls_for_each_rcu(sk, node, &head->chain) {
if (sk->sk_hash != hash)
continue;
- if (!INET6_MATCH(sk, net, saddr, daddr, ports, dif))
+ if (!INET6_MATCH(sk, net, saddr, daddr, ports,
+ params->dif))
continue;
if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
goto out;
- if (unlikely(!INET6_MATCH(sk, net, saddr, daddr, ports, dif))) {
+ if (unlikely(!INET6_MATCH(sk, net, saddr, daddr, ports,
+ params->dif))) {
sock_gen_put(sk);
goto begin;
}
@@ -94,26 +96,27 @@ struct sock *__inet6_lookup_established(struct net *net,
EXPORT_SYMBOL(__inet6_lookup_established);
static inline int compute_score(struct sock *sk, struct net *net,
- const unsigned short hnum,
- const struct in6_addr *daddr,
- const int dif, bool exact_dif)
+ const struct sk_lookup *params)
{
int score = -1;
- if (net_eq(sock_net(sk), net) && inet_sk(sk)->inet_num == hnum &&
+ if (net_eq(sock_net(sk), net) &&
+ inet_sk(sk)->inet_num == params->hnum &&
sk->sk_family == PF_INET6) {
+ int rc;
score = 1;
if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) {
- if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr))
+ if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr,
+ params->daddr.ipv6))
return -1;
score++;
}
- if (sk->sk_bound_dev_if || exact_dif) {
- if (sk->sk_bound_dev_if != dif)
- return -1;
+ rc = sk_lookup_device_cmp(sk, params);
+ if (rc < 0)
+ return -1;
+ if (rc > 0)
score++;
- }
if (sk->sk_incoming_cpu == raw_smp_processor_id())
score++;
}
@@ -122,26 +125,27 @@ static inline int compute_score(struct sock *sk, struct net *net,
/* called with rcu_read_lock() */
struct sock *inet6_lookup_listener(struct net *net,
- struct inet_hashinfo *hashinfo,
- struct sk_buff *skb, int doff,
- const struct in6_addr *saddr,
- const __be16 sport, const struct in6_addr *daddr,
- const unsigned short hnum, const int dif)
+ struct inet_hashinfo *hashinfo,
+ struct sk_buff *skb, int doff,
+ struct sk_lookup *params)
{
- unsigned int hash = inet_lhashfn(net, hnum);
+ unsigned int hash = inet_lhashfn(net, params->hnum);
struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
int score, hiscore = 0, matches = 0, reuseport = 0;
- bool exact_dif = inet6_exact_dif_match(net, skb);
struct sock *sk, *result = NULL;
u32 phash = 0;
+ params->exact_dif = inet6_exact_dif_match(net, skb);
+
sk_for_each(sk, &ilb->head) {
- score = compute_score(sk, net, hnum, daddr, dif, exact_dif);
+ score = compute_score(sk, net, params);
if (score > hiscore) {
reuseport = sk->sk_reuseport;
if (reuseport) {
- phash = inet6_ehashfn(net, daddr, hnum,
- saddr, sport);
+ phash = inet6_ehashfn(net, params->daddr.ipv6,
+ params->hnum,
+ params->saddr.ipv6,
+ params->sport);
result = reuseport_select_sock(sk, phash,
skb, doff);
if (result)
@@ -163,15 +167,12 @@ EXPORT_SYMBOL_GPL(inet6_lookup_listener);
struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
- const struct in6_addr *saddr, const __be16 sport,
- const struct in6_addr *daddr, const __be16 dport,
- const int dif)
+ struct sk_lookup *params)
{
struct sock *sk;
bool refcounted;
- sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr,
- ntohs(dport), dif, &refcounted);
+ sk = __inet6_lookup(net, hashinfo, skb, doff, params, &refcounted);
if (sk && !refcounted && !refcount_inc_not_zero(&sk->sk_refcnt))
sk = NULL;
return sk;
@@ -203,7 +204,8 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
if (sk2->sk_hash != hash)
continue;
- if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports, dif))) {
+ if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports,
+ dif))) {
if (sk2->sk_state == TCP_TIME_WAIT) {
tw = inet_twsk(sk2);
if (twsk_unique(sk, sk2, twp))
diff --git a/net/ipv6/netfilter/nf_socket_ipv6.c b/net/ipv6/netfilter/nf_socket_ipv6.c
index c1c193103063..1d815e0933b7 100644
--- a/net/ipv6/netfilter/nf_socket_ipv6.c
+++ b/net/ipv6/netfilter/nf_socket_ipv6.c
@@ -91,14 +91,13 @@ nf_socket_get_sock_v6(struct net *net, struct sk_buff *skb, int doff,
.daddr.ipv6 = daddr,
.sport = sport,
.dport = dport,
+ .hnum = ntohs(dport),
.dif = in->ifindex,
};
switch (protocol) {
case IPPROTO_TCP:
- return inet6_lookup(net, &tcp_hashinfo, skb, doff,
- saddr, sport, daddr, dport,
- in->ifindex);
+ return inet6_lookup(net, &tcp_hashinfo, skb, doff, ¶ms);
case IPPROTO_UDP:
return udp6_lib_lookup(net, ¶ms);
}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 2968a33cca7d..19fee98e1ae0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -45,6 +45,7 @@
#include <linux/random.h>
#include <net/tcp.h>
+#include <net/inet_hashtables.h>
#include <net/ndisc.h>
#include <net/inet6_hashtables.h>
#include <net/inet6_connection_sock.h>
@@ -338,6 +339,13 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
{
const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
+ struct sk_lookup params = {
+ .saddr.ipv6 = &hdr->daddr,
+ .daddr.ipv6 = &hdr->saddr,
+ .sport = th->dest,
+ .hnum = ntohs(th->source),
+ .dif = skb->dev->ifindex,
+ };
struct net *net = dev_net(skb->dev);
struct request_sock *fastopen;
struct ipv6_pinfo *np;
@@ -347,11 +355,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
bool fatal;
int err;
- sk = __inet6_lookup_established(net, &tcp_hashinfo,
- &hdr->daddr, th->dest,
- &hdr->saddr, ntohs(th->source),
- skb->dev->ifindex);
-
+ sk = __inet6_lookup_established(net, &tcp_hashinfo, ¶ms);
if (!sk) {
__ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
ICMP6_MIB_INERRORS);
@@ -907,6 +911,14 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
if (sk && sk_fullsock(sk)) {
key = tcp_v6_md5_do_lookup(sk, &ipv6h->saddr);
} else if (hash_location) {
+ struct sk_lookup params = {
+ .saddr.ipv6 = &ipv6h->saddr,
+ .daddr.ipv6 = &ipv6h->daddr,
+ .sport = th->source,
+ .hnum = ntohs(th->source),
+ .dif = tcp_v6_iif(skb),
+ };
+
/*
* active side is lost. Try to find listening socket through
* source port, and then find md5 key through listening socket.
@@ -915,10 +927,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
* no RST generated if md5 hash doesn't match.
*/
sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
- &tcp_hashinfo, NULL, 0,
- &ipv6h->saddr,
- th->source, &ipv6h->daddr,
- ntohs(th->source), tcp_v6_iif(skb));
+ &tcp_hashinfo, NULL, 0, ¶ms);
if (!sk1)
goto out;
@@ -1403,6 +1412,9 @@ static int tcp_v6_rcv(struct sk_buff *skb)
struct sock *sk;
int ret;
struct net *net = dev_net(skb->dev);
+ struct sk_lookup params = {
+ .dif = inet6_iif(skb),
+ };
if (skb->pkt_type != PACKET_HOST)
goto discard_it;
@@ -1428,10 +1440,11 @@ static int tcp_v6_rcv(struct sk_buff *skb)
th = (const struct tcphdr *)skb->data;
hdr = ipv6_hdr(skb);
+ params.sport = th->source;
+ params.dport = th->dest;
lookup:
sk = __inet6_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th),
- th->source, th->dest, inet6_iif(skb),
- &refcounted);
+ ¶ms, &refcounted);
if (!sk)
goto no_tcp_socket;
@@ -1558,13 +1571,17 @@ static int tcp_v6_rcv(struct sk_buff *skb)
switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
case TCP_TW_SYN:
{
+ struct sk_lookup params = {
+ .saddr.ipv6 = &ipv6_hdr(skb)->saddr,
+ .daddr.ipv6 = &ipv6_hdr(skb)->daddr,
+ .sport = th->source,
+ .hnum = ntohs(th->dest),
+ .dif = tcp_v6_iif(skb),
+ };
struct sock *sk2;
sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
- skb, __tcp_hdrlen(th),
- &ipv6_hdr(skb)->saddr, th->source,
- &ipv6_hdr(skb)->daddr,
- ntohs(th->dest), tcp_v6_iif(skb));
+ skb, __tcp_hdrlen(th), ¶ms);
if (sk2) {
struct inet_timewait_sock *tw = inet_twsk(sk);
inet_twsk_deschedule_put(tw);
@@ -1591,6 +1608,10 @@ static int tcp_v6_rcv(struct sk_buff *skb)
static void tcp_v6_early_demux(struct sk_buff *skb)
{
+ /* Note : We use inet6_iif() here, not tcp_v6_iif() */
+ struct sk_lookup params = {
+ .dif = inet6_iif(skb),
+ };
const struct ipv6hdr *hdr;
const struct tcphdr *th;
struct sock *sk;
@@ -1607,11 +1628,12 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
if (th->doff < sizeof(struct tcphdr) / 4)
return;
- /* Note : We use inet6_iif() here, not tcp_v6_iif() */
+ params.saddr.ipv6 = &hdr->saddr,
+ params.daddr.ipv6 = &hdr->daddr,
+ params.sport = th->source,
+ params.hnum = ntohs(th->dest),
sk = __inet6_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
- &hdr->saddr, th->source,
- &hdr->daddr, ntohs(th->dest),
- inet6_iif(skb));
+ ¶ms);
if (sk) {
skb->sk = sk;
skb->destructor = sock_edemux;
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
index 56bb40544035..3ee75189d1c3 100644
--- a/net/netfilter/xt_TPROXY.c
+++ b/net/netfilter/xt_TPROXY.c
@@ -193,6 +193,7 @@ nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
.daddr.ipv6 = daddr,
.sport = sport,
.dport = dport,
+ .hnum = ntohs(dport),
.dif = in->ifindex,
};
struct sock *sk;
@@ -205,9 +206,7 @@ nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
tcph = hp;
sk = inet6_lookup_listener(net, &tcp_hashinfo, skb,
thoff + __tcp_hdrlen(tcph),
- saddr, sport,
- daddr, ntohs(dport),
- in->ifindex);
+ ¶ms);
if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
sk = NULL;
@@ -219,8 +218,7 @@ nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp,
break;
case NFT_LOOKUP_ESTABLISHED:
sk = __inet6_lookup_established(net, &tcp_hashinfo,
- saddr, sport, daddr, ntohs(dport),
- in->ifindex);
+ ¶ms);
break;
default:
BUG();
--
2.1.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox