* Re: [PATCH] cxgb3: Set vlan_feature on net_device
From: Breno Leitao @ 2012-07-27 18:57 UTC (permalink / raw)
To: brenohl; +Cc: jitendra.kalsaria, ron.mercer, netdev
In-Reply-To: <1343413351-48710-1-git-send-email-brenohl@br.ibm.com>
On 07/27/2012 03:22 PM, brenohl@br.ibm.com wrote:
> cxgb3 interface has a bad performance when VLAN is set. On my current
> setup, a PowerLinux 7R2, I am able to get around 7 Gbps on a TCP_STREAM
> (8 instances, 4k message).
> With this patch, I am able to reach 9.5 Gbps.
Please do not consider this patch. I'd send a qlge patch, but wrongly made
a shell-completion mistake and sent the wrong patch. The correct patch is
under its way.
^ permalink raw reply
* Re: [PATCH 00/16] Remove the ipv4 routing cache
From: Alexander Duyck @ 2012-07-27 19:06 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Eric W. Biederman, David Miller, netdev
In-Reply-To: <1343406533.2626.13104.camel@edumazet-glaptop>
On Fri, Jul 27, 2012 at 9:28 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Fri, 2012-07-27 at 09:23 -0700, Eric W. Biederman wrote:
>
>> I am familiar. But does hardware prefetching make a difference
>> if your object is less than 64 bytes?
>>
>
> Apparently yes, if the prefetch touches a dirtied neighbour cache line.
>
>> I don't believe only allocating 64 bytes will be a problem,
>> as no one else well be dirtying your cache line.
>>
>> I suppose you could run into pathologies where your object
>> is 3*64 bytes in size, but your expression doesn't handle
>> that case either.
>>
>
> Sure, but in most cases fib objects are under 128 bytes.
>
>
>> The other alternative to guarantee very good cache behavior is
>> to ensure you are allocating a power of two size up to some limit,
>> perhaps page size.
>>
>
> Good idea.
>
>> My point is the magic 128 likely requires an explicatory comment and I
>> think the net result is you have encoded something fragile that is good
>> for testing but that will in the fullness of time do strange things that
>> will be easy to overlook.
>
> Sure, I'll send a v2, thanks.
>
>
I tested out v1 of your patch and didn't seem much of a change in my
test environment. I figure I will spend most of today going through
the code trying to figure out what is causing the issues I am seeing
and why your changes had no effect on my setup.
Thanks,
Alex
^ permalink raw reply
* Re: [PATCH v2 0/7] TCP Fast Open client
From: Michael Kerrisk @ 2012-07-27 19:06 UTC (permalink / raw)
To: Jerry Chu
Cc: Yuchung Cheng, davem, edumazet, ncardwell, sivasankar, netdev,
rick jones, Terry Lam, Michael Kerrisk
In-Reply-To: <CAPshTCjxUQ=juO3POX1oSaLTO_g3EmxjQNkSxLjEZGyxDBkMJQ@mail.gmail.com>
On Fri, Jul 27, 2012 at 7:28 PM, Jerry Chu <hkchu@google.com> wrote:
> +rick, terry
>
> Hi Michael,
>
> Thanks for your interest!
>
> On Fri, Jul 27, 2012 at 4:42 AM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
>> Yuchung,
>>
>> On Wed, Jul 18, 2012 at 11:01 PM, Yuchung Cheng <ycheng@google.com> wrote:
>>> ChangeLog since v1:
>>> - Reduce tons of code by storing Fast Open stats in the TCP metrics :)
>>> - Clarify the purpose of using an experimental option in patch 1/7
>>>
>>> This patch series implement the client functionality of TCP Fast Open.
>>> TCP Fast Open (TFO) allows data to be carried in the SYN and SYN-ACK
>>> packets and consumed by the receiving end during the initial connection
>>> handshake, thus providing a saving of up to one full round trip time (RTT)
>>> compared to standard TCP requiring a three-way handshake (3WHS) to
>>> complete before data can be exchanged.
>>>
>>> The protocol change is detailed in the IETF internet draft at
>>> http://www.ietf.org/id/draft-ietf-tcpm-fastopen-00.txt . The research
>>
>> This URL appears to be invalid. I assume the following is the correct
>> current version:
>> http://tools.ietf.org/html/draft-ietf-tcpm-fastopen-01
>> ?
>
> Correct.
>
>>
>> Is there some sample client and server userspace test code available?
>
> There are some sample code in a SIGCOMM paper (
> http://conferences.sigcomm.org/co-next/2011/papers/1569470463.pdf). It's
> real simple but we haven't published the server side code yet. (It's been
> ready but I need to rebase it to the latest net-next.)
The examples in that paper seem to be outdated. At the very least,
names of constants for socket options etc have changed.
I've been trying to test this feature from userspace, but am not
getting quite the results I expect. It sounds like you are saying that
not all the kernel pieces are there yet to support TFO in userspace.
Is that correct?
Thanks,
Michael
--
Michael Kerrisk Linux man-pages maintainer;
http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface", http://blog.man7.org/
^ permalink raw reply
* TCP stalls with 802.3ad + bridge + kvm guest
From: Peter Samuelson @ 2012-07-27 18:38 UTC (permalink / raw)
To: netdev; +Cc: jgoerzen
So, we have the following network stack:
ixgbe [10 Gbit port] -- bonding [802.3ad] -- bridge -- KVM guest
(There's also a VLAN layer, but I can reproduce this problem without
it.) It all works, except that with some flows in the KVM guest - I
can reproduce using smbclient - transfers keep stalling, such that I'm
averaging well under 1 MB/s. Should be more like 100 MB/s.
Oddly, this only occurs when both the 802.3ad and KVM are used:
Server Agg Client TCP stalls
--------------------------------------------------
external none KVM guest no
external 802.3ad KVM host no
KVM host 802.3ad KVM guest no
external 802.3ad KVM guest yes
I don't understand the stalls. 'ping -f' does not show any dropped
packets. tcpdump seems to show a lot of retransmits (server to
client), out-of-order TCP segments (server to client), and duplicate
ACKs (client to server).
Further notes:
- OS for KVM host (and guest) is Debian stable, with kernels from
Debian backports. I've tried several kernels including 3.4,
currently using 3.2.20.
- Arista 10 Gbit switch, no congestion to speak of, all the test
traffic is local to the switch.
- I can reproduce with either 1 or 2 active ports in the LACP group.
- The host IP is bound to the bridge, not directly to bond0.
- First noticed problem with a Windows VM and SMB. I can reproduce
100% using smbclient, but wget (http) goes full speed.
Does any of this sound familiar? Is it a known issue? Can anyone
offer any hints? I can run tcpdump on the client, the server or any
point in the KVM host network stack, in case anyone is better at
interpreting them than I am.
Thanks,
Peter
^ permalink raw reply
* Re: [PATCH v2 0/7] TCP Fast Open client
From: Jerry Chu @ 2012-07-27 19:39 UTC (permalink / raw)
To: Michael Kerrisk
Cc: Yuchung Cheng, davem, edumazet, ncardwell, sivasankar, netdev,
rick jones, Terry Lam
In-Reply-To: <CAHO5Pa3eLRrjGx52o26sN9OS7PMbKu3e3=Zz72E7Z6i5XwDnvw@mail.gmail.com>
On Fri, Jul 27, 2012 at 12:06 PM, Michael Kerrisk
<mtk.manpages@gmail.com> wrote:
> On Fri, Jul 27, 2012 at 7:28 PM, Jerry Chu <hkchu@google.com> wrote:
>> +rick, terry
>>
>> Hi Michael,
>>
>> Thanks for your interest!
>>
>> On Fri, Jul 27, 2012 at 4:42 AM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
>>> Yuchung,
>>>
>>> On Wed, Jul 18, 2012 at 11:01 PM, Yuchung Cheng <ycheng@google.com> wrote:
>>>> ChangeLog since v1:
>>>> - Reduce tons of code by storing Fast Open stats in the TCP metrics :)
>>>> - Clarify the purpose of using an experimental option in patch 1/7
>>>>
>>>> This patch series implement the client functionality of TCP Fast Open.
>>>> TCP Fast Open (TFO) allows data to be carried in the SYN and SYN-ACK
>>>> packets and consumed by the receiving end during the initial connection
>>>> handshake, thus providing a saving of up to one full round trip time (RTT)
>>>> compared to standard TCP requiring a three-way handshake (3WHS) to
>>>> complete before data can be exchanged.
>>>>
>>>> The protocol change is detailed in the IETF internet draft at
>>>> http://www.ietf.org/id/draft-ietf-tcpm-fastopen-00.txt . The research
>>>
>>> This URL appears to be invalid. I assume the following is the correct
>>> current version:
>>> http://tools.ietf.org/html/draft-ietf-tcpm-fastopen-01
>>> ?
>>
>> Correct.
>>
>>>
>>> Is there some sample client and server userspace test code available?
>>
>> There are some sample code in a SIGCOMM paper (
>> http://conferences.sigcomm.org/co-next/2011/papers/1569470463.pdf). It's
>> real simple but we haven't published the server side code yet. (It's been
>> ready but I need to rebase it to the latest net-next.)
>
> The examples in that paper seem to be outdated. At the very least,
> names of constants for socket options etc have changed.
>
> I've been trying to test this feature from userspace, but am not
> getting quite the results I expect. It sounds like you are saying that
> not all the kernel pieces are there yet to support TFO in userspace.
> Is that correct?
Correct. Only the client side code is in net-next but not the server
code. If you
tcpdump you'll see your TFO TCP option is not getting ack'ed because the
server side does not understand TFO yet.
The server side code is ready for review as well, except I just discovered
an implementation detail that I need to fix - I have conveniently added TCP
code for TFO directly to request_sock.c but just realized request_sock is
being used by non-TCP transport (e.g., DCCP) as well so I need to remove
TCP specific code and make it more generic wrt rsk...
Anyway hopefully the code will be ready for review soon (i'm leaving for
vacation in a few days so it will be a little more delay). If you can't wait to
test it i can send you a patch.
Thanks,
Jerry
>
> Thanks,
>
> Michael
>
> --
> Michael Kerrisk Linux man-pages maintainer;
> http://www.kernel.org/doc/man-pages/
> Author of "The Linux Programming Interface", http://blog.man7.org/
^ permalink raw reply
* Re: [PATCH v2 0/7] TCP Fast Open client
From: Vijay Subramanian @ 2012-07-27 19:52 UTC (permalink / raw)
To: Jerry Chu
Cc: Michael Kerrisk, Yuchung Cheng, davem, edumazet, ncardwell,
sivasankar, netdev, rick jones, Terry Lam
In-Reply-To: <CAPshTCgR585z5sFUbxgR5azb2kZe2mnx=x6i_0M=iint5NEpJg@mail.gmail.com>
>
> Anyway hopefully the code will be ready for review soon (i'm leaving for
> vacation in a few days so it will be a little more delay). If you can't wait to
> test it i can send you a patch.
>
Jerry,
If you don't mind, can you CC me the patches too if they are ready? I
was planning to test TFO too and was waiting for the server side
patches,
For the user space, as far as I understand, replacing connect() with
sendmsg() with MSG_FASTOPEN flag should be the only change needed
right?
Thanks,
Vijay
^ permalink raw reply
* Re: TCP stalls with 802.3ad + bridge + kvm guest
From: Jay Vosburgh @ 2012-07-27 20:00 UTC (permalink / raw)
To: Peter Samuelson; +Cc: netdev, jgoerzen
In-Reply-To: <20120727183840.GE17572@p12n.org>
Peter Samuelson <psamuelson@efolder.net> wrote:
>So, we have the following network stack:
>
> ixgbe [10 Gbit port] -- bonding [802.3ad] -- bridge -- KVM guest
>
>(There's also a VLAN layer, but I can reproduce this problem without
>it.) It all works, except that with some flows in the KVM guest - I
>can reproduce using smbclient - transfers keep stalling, such that I'm
>averaging well under 1 MB/s. Should be more like 100 MB/s.
>
>Oddly, this only occurs when both the 802.3ad and KVM are used:
>
> Server Agg Client TCP stalls
> --------------------------------------------------
> external none KVM guest no
> external 802.3ad KVM host no
> KVM host 802.3ad KVM guest no
> external 802.3ad KVM guest yes
Does the "none" for Agg (the first line) mean no bonding at all?
Does the problem happen if the bond is a different mode
(balance-xor, for example)?
>I don't understand the stalls. 'ping -f' does not show any dropped
>packets. tcpdump seems to show a lot of retransmits (server to
>client), out-of-order TCP segments (server to client), and duplicate
>ACKs (client to server).
Do the various stats on the host and guest show any drops?
E.g., from "netstat -i" and "tc -s qdisc"
>Further notes:
>
>- OS for KVM host (and guest) is Debian stable, with kernels from
> Debian backports. I've tried several kernels including 3.4,
> currently using 3.2.20.
>
>- Arista 10 Gbit switch, no congestion to speak of, all the test
> traffic is local to the switch.
>
>- I can reproduce with either 1 or 2 active ports in the LACP group.
>
>- The host IP is bound to the bridge, not directly to bond0.
>
>- First noticed problem with a Windows VM and SMB. I can reproduce
> 100% using smbclient, but wget (http) goes full speed.
>
>Does any of this sound familiar? Is it a known issue? Can anyone
>offer any hints? I can run tcpdump on the client, the server or any
>point in the KVM host network stack, in case anyone is better at
>interpreting them than I am.
Maybe; I've seen a similar-sounding problem with CIFS wherein
the loss of the last or near-last packet that's part of the CIFS request
will cause TCP to run a full RTO. This occurs because CIFS has no more
packets to send, as it's waiting for a response, so there is no
subsequent traffic that will trigger duplicate ACKs from the peer and
thus initiate a fast retransmission. I may be mangling the CIFS
details, but that's the packet exchange that occurs, and it resulted in
very poor performance for CIFS.
The case I saw this in was not using KVM, but was instead
dropping some packets at a network bottleneck. In that case, CIFS
experienced the poor performance, but NFS did not; the NFS packet
captures also showed the lost packets, but NFS would continue to send
and issue fast retransmissions in response to the duplicate ACKs it
received. Perhaps this mirrors your experience with CIFS vs. wget, and
your bottleneck is somewhere on the host itself in the virtual
networking.
-J
---
-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
^ permalink raw reply
* [PATCH] Revert "openvswitch: potential NULL deref in sample()"
From: Jesse Gross @ 2012-07-27 20:19 UTC (permalink / raw)
To: David Miller
Cc: dev-yBygre7rU0TnMu66kgdUjQ, netdev-u79uwXL29TY76Z2rM5mHXA,
Dan Carpenter
This reverts commit 5b3e7e6cb5771bedda51cdb6f715d1da8cd9e644.
The problem that the original commit was attempting to fix can
never happen in practice because validation is done one a per-flow
basis rather than a per-packet basis. Adding additional checks at
runtime is unnecessary and inconsistent with the rest of the code.
CC: Dan Carpenter <dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Jesse Gross <jesse-l0M0P4e3n4LQT0dZR+AlfA@public.gmane.org>
---
net/openvswitch/actions.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 320fa0e..f3f96ba 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -325,9 +325,6 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
}
}
- if (!acts_list)
- return 0;
-
return do_execute_actions(dp, skb, nla_data(acts_list),
nla_len(acts_list), true);
}
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] tcp: perform DMA to userspace only if there is a task waiting for it
From: David Miller @ 2012-07-27 20:31 UTC (permalink / raw)
To: jkosina; +Cc: christopher.leech, linux-kernel, netdev, jbohac
In-Reply-To: <alpine.LNX.2.00.1207271556320.11375@pobox.suse.cz>
From: Jiri Kosina <jkosina@suse.cz>
Date: Fri, 27 Jul 2012 16:05:06 +0200 (CEST)
> #ifdef CONFIG_NET_DMA
> - if (tcp_dma_try_early_copy(sk, skb, tcp_header_len)) {
> + if (tp->ucopy.task == current &&
> + sock_owned_by_user(sk) &&
> + tcp_dma_try_early_copy(sk,
> + skb, tcp_header_len)) {
This indentation is absolutely terrible.
If you are only able to indent lines using TAB characters, rather than
using an appropriate mixture of TAB and SPACE characters to get the
lines to line up properly, please do not even bother submitting
patches here.
^ permalink raw reply
* [PATCH v2] tcp: perform DMA to userspace only if there is a task waiting for it
From: Jiri Kosina @ 2012-07-27 20:38 UTC (permalink / raw)
To: David Miller; +Cc: christopher.leech, linux-kernel, netdev, jbohac
In-Reply-To: <20120727.133135.2017747630291360657.davem@davemloft.net>
Back in 2006, commit 1a2449a87b ("[I/OAT]: TCP recv offload to I/OAT")
added support for receive offloading to IOAT dma engine if available.
The code in tcp_rcv_established() tries to perform early DMA copy if
applicable. It however does so without checking whether the userspace
task is actually expecting the data in the buffer.
This is not a problem under normal circumstances, but there is a corner
case where this doesn't work -- and that's when MSG_TRUNC flag to
recvmsg() is used.
If the IOAT dma engine is not used, the code properly checks whether
there is a valid ucopy.task and the socket is owned by userspace, but
misses the check in the dmaengine case.
This problem can be observed in real trivially -- for example 'tbench' is a
good reproducer, as it makes a heavy use of MSG_TRUNC. On systems utilizing
IOAT, you will soon find tbench waiting indefinitely in sk_wait_data(), as they
have been already early-copied in tcp_rcv_established() using dma engine.
This patch introduces the same check we are performing in the simple
iovec copy case to the IOAT case as well. It fixes the indefinite
recvmsg(MSG_TRUNC) hangs.
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
---
net/ipv4/tcp_input.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 3e07a64..76e3bf6 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5475,7 +5475,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
if (tp->copied_seq == tp->rcv_nxt &&
len - tcp_header_len <= tp->ucopy.len) {
#ifdef CONFIG_NET_DMA
- if (tcp_dma_try_early_copy(sk, skb, tcp_header_len)) {
+ if (tp->ucopy.task == current &&
+ sock_owned_by_user(sk) &&
+ tcp_dma_try_early_copy(sk, skb, tcp_header_len)) {
copied_early = 1;
eaten = 1;
}
--
Jiri Kosina
SUSE Labs
^ permalink raw reply related
* Re: [PATCH net-next] GRE over IPv6
From: David Miller @ 2012-07-27 20:42 UTC (permalink / raw)
To: xeb; +Cc: netdev
In-Reply-To: <1588984.2XtHtDpxor@dima>
Why have you submitted these patches two times?
^ permalink raw reply
* Re: [PATCH] tcp: Add TCP_USER_TIMEOUT negative value check
From: David Miller @ 2012-07-27 20:46 UTC (permalink / raw)
To: liuhangbin; +Cc: netdev, hkchu
In-Reply-To: <1343379141-5516-1-git-send-email-liuhangbin@gmail.com>
From: Hangbin Liu <liuhangbin@gmail.com>
Date: Fri, 27 Jul 2012 16:52:21 +0800
> TCP_USER_TIMEOUT is a TCP level socket option that takes an unsigned int. But
> patch "tcp: Add TCP_USER_TIMEOUT socket option"(dca43c75) didn't check the negative
> values. If a user assign -1 to it, the socket will set successfully and wait
> for 4294967295 miliseconds. This patch add a negative value check to avoid
> this issue.
>
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Applied.
^ permalink raw reply
* Re: [patch] USB: kaweth.c: use GFP_ATOMIC under spin_lock
From: David Miller @ 2012-07-27 20:46 UTC (permalink / raw)
To: dan.carpenter; +Cc: gregkh, linux-usb, netdev, kernel-janitors
In-Reply-To: <20120727114651.GA15492@elgon.mountain>
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Fri, 27 Jul 2012 14:46:51 +0300
> The problem is that we call this with a spin lock held. The call tree
> is:
> kaweth_start_xmit() holds kaweth->device_lock.
> -> kaweth_async_set_rx_mode()
> -> kaweth_control()
> -> kaweth_internal_control_msg()
>
> The kaweth_internal_control_msg() function is only called from
> kaweth_control() which used GFP_ATOMIC for its allocations.
>
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Applied.
^ permalink raw reply
* Re: [PATCH] net: fix rtnetlink IFF_PROMISC and IFF_ALLMULTI handling
From: David Miller @ 2012-07-27 20:46 UTC (permalink / raw)
To: jbenc; +Cc: netdev, makc
In-Reply-To: <20120727145822.7efd10d4@griffin>
From: Jiri Benc <jbenc@redhat.com>
Date: Fri, 27 Jul 2012 14:58:22 +0200
> When device flags are set using rtnetlink, IFF_PROMISC and IFF_ALLMULTI
> flags are handled specially. Function dev_change_flags sets IFF_PROMISC and
> IFF_ALLMULTI bits in dev->gflags according to the passed value but
> do_setlink passes a result of rtnl_dev_combine_flags which takes those bits
> from dev->flags.
>
> This can be easily trigerred by doing:
>
> tcpdump -i eth0 &
> ip l s up eth0
>
> ip sets IFF_UP flag in ifi_flags and ifi_change, which is combined with
> IFF_PROMISC by rtnl_dev_combine_flags, causing __dev_change_flags to set
> IFF_PROMISC in gflags.
>
> Reported-by: Max Matveev <makc@redhat.com>
> Signed-off-by: Jiri Benc <jbenc@redhat.com>
Applied.
^ permalink raw reply
* Re: [PATCH] ipv4: fix TCP early demux
From: David Miller @ 2012-07-27 20:47 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1343406220.2626.13092.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 27 Jul 2012 18:23:40 +0200
> From: Eric Dumazet <edumazet@google.com>
>
> commit 92101b3b2e317 (ipv4: Prepare for change of rt->rt_iif encoding.)
> invalidated TCP early demux, because rx_dst_ifindex is not properly
> initialized and checked.
>
> Also remove the use of inet_iif(skb) in favor or skb->skb_iif
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Applied.
^ permalink raw reply
* Re: [PATCH] Revert "openvswitch: potential NULL deref in sample()"
From: David Miller @ 2012-07-27 20:47 UTC (permalink / raw)
To: jesse; +Cc: netdev, dev, dan.carpenter
In-Reply-To: <1343420380-23119-1-git-send-email-jesse@nicira.com>
From: Jesse Gross <jesse@nicira.com>
Date: Fri, 27 Jul 2012 13:19:40 -0700
> This reverts commit 5b3e7e6cb5771bedda51cdb6f715d1da8cd9e644.
>
> The problem that the original commit was attempting to fix can
> never happen in practice because validation is done one a per-flow
> basis rather than a per-packet basis. Adding additional checks at
> runtime is unnecessary and inconsistent with the rest of the code.
>
> CC: Dan Carpenter <dan.carpenter@oracle.com>
> Signed-off-by: Jesse Gross <jesse@nicira.com>
Applied.
^ permalink raw reply
* Re: [PATCH v2] tcp: perform DMA to userspace only if there is a task waiting for it
From: David Miller @ 2012-07-27 20:48 UTC (permalink / raw)
To: jkosina; +Cc: christopher.leech, linux-kernel, netdev, jbohac
In-Reply-To: <alpine.LNX.2.00.1207272237470.30412@pobox.suse.cz>
From: Jiri Kosina <jkosina@suse.cz>
Date: Fri, 27 Jul 2012 22:38:50 +0200 (CEST)
> Back in 2006, commit 1a2449a87b ("[I/OAT]: TCP recv offload to I/OAT")
> added support for receive offloading to IOAT dma engine if available.
>
> The code in tcp_rcv_established() tries to perform early DMA copy if
> applicable. It however does so without checking whether the userspace
> task is actually expecting the data in the buffer.
>
> This is not a problem under normal circumstances, but there is a corner
> case where this doesn't work -- and that's when MSG_TRUNC flag to
> recvmsg() is used.
>
> If the IOAT dma engine is not used, the code properly checks whether
> there is a valid ucopy.task and the socket is owned by userspace, but
> misses the check in the dmaengine case.
>
> This problem can be observed in real trivially -- for example 'tbench' is a
> good reproducer, as it makes a heavy use of MSG_TRUNC. On systems utilizing
> IOAT, you will soon find tbench waiting indefinitely in sk_wait_data(), as they
> have been already early-copied in tcp_rcv_established() using dma engine.
>
> This patch introduces the same check we are performing in the simple
> iovec copy case to the IOAT case as well. It fixes the indefinite
> recvmsg(MSG_TRUNC) hangs.
>
> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Applied.
^ permalink raw reply
* Re: [PATCH] sctp: Make "Invalid Stream Identifier" ERROR follows SACK when bundling
From: Vlad Yasevich @ 2012-07-27 21:22 UTC (permalink / raw)
To: Xufeng Zhang
Cc: Neil Horman, xufeng zhang, sri, davem, linux-sctp, netdev,
linux-kernel
In-Reply-To: <CA+=dFzguqjjnnqHO53Mx859VB6NU=4MaPWAUzGQB2qtZGfdAUg@mail.gmail.com>
here is an untested prototype of what I was talking about. This should
handle multiple data chunks.
-vlad
---
include/net/sctp/command.h | 1 +
net/sctp/sm_sideeffect.c | 22 ++++++++++++++++++++++
net/sctp/sm_statefuns.c | 18 ++++++++++--------
3 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 712b3be..4043445 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -110,6 +110,7 @@ typedef enum {
SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */
SCTP_CMD_PURGE_ASCONF_QUEUE, /* Purge all asconf queues.*/
SCTP_CMD_SET_ASOC, /* Restore association context */
+ SCTP_CMD_GEN_BAD_STREAM, /* Issue an Invalid Stream error */
SCTP_CMD_LAST
} sctp_verb_t;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 1ff51c9..c5a1322 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1036,6 +1036,22 @@ static void sctp_cmd_send_asconf(struct
sctp_association *asoc)
}
}
+static void sctp_cmd_make_inv_stream_err(sctp_cmd_seq_t *commands,
+ struct sctp_association *asoc,
+ struct sctp_chunk *chunk,
+ struct sctp_datahdr *data_hdr)
+{
+ struct sctp_chunk *err;
+
+ err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
+ &data_hdr->stream,
+ sizeof(data_hdr->stream),
+ sizeof(u16));
+ if (err)
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+ SCTP_CHUNK(err));
+}
+
/* These three macros allow us to pull the debugging code out of the
* main flow of sctp_do_sm() to keep attention focused on the real
@@ -1700,6 +1716,12 @@ static int sctp_cmd_interpreter(sctp_event_t
event_type,
asoc = cmd->obj.asoc;
break;
+ case SCTP_CMD_GEN_BAD_STREAM:
+ sctp_cmd_make_inv_stream_err(commands,
+ asoc, chunk,
+ (struct sctp_datahdr *)cmd->obj.ptr);
+ break;
+
default:
pr_warn("Impossible command: %u, %p\n",
cmd->verb, cmd->obj.ptr);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 891f5db..57532e3 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -2972,6 +2972,12 @@ discard_noforce:
if (chunk->end_of_packet)
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force);
+ /* Queue the INVALID STREAM error after the SACK if one is needed. */
+ if (SCTP_IERROR_BAD_STREAM == error) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_GEN_BAD_STREAM,
+ SCTP_PTR(chunk->subh.data_hdr));
+ }
+
return SCTP_DISPOSITION_DISCARD;
consume:
return SCTP_DISPOSITION_CONSUME;
@@ -3044,6 +3050,10 @@ sctp_disposition_t
sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
*/
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SHUTDOWN, SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE());
+ if (SCTP_IERROR_BAD_STREAM == error) {
+ sctp_add_cmd_sf(commands, SCTP_CMD_GEN_BAD_STREAM,
+ SCTP_PTR(chunk->subh.data_hdr));
+ }
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
}
@@ -6140,14 +6150,6 @@ static int sctp_eat_data(const struct
sctp_association *asoc,
if (sid >= asoc->c.sinit_max_instreams) {
/* Mark tsn as received even though we drop it */
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
-
- err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
- &data_hdr->stream,
- sizeof(data_hdr->stream),
- sizeof(u16));
- if (err)
- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
- SCTP_CHUNK(err));
return SCTP_IERROR_BAD_STREAM;
}
-- 1.7.7.6
^ permalink raw reply related
* Re: pull request: wireless 2012-07-27
From: David Miller @ 2012-07-27 21:26 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20120727155806.GB6110@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Fri, 27 Jul 2012 11:58:06 -0400
> These fixes are intended for the 3.6 stream.
>
> Hauke Mehrtens provides a pair of bcma fixes, one to fix a build
> regression on mips and another to correct a pair of missing iounmap
> calls.
>
> Thomas Huehn offers a mac80211_hwsim fix to avoid a possible
> use-after-free bug.
>
> Please let me know if there are problems!
Pulled, thanks John.
^ permalink raw reply
* Re: [PATCH] ipv4: fix TCP early demux
From: Eric Dumazet @ 2012-07-27 21:34 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20120727.134713.1437322148321890583.davem@davemloft.net>
On Fri, 2012-07-27 at 13:47 -0700, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Fri, 27 Jul 2012 18:23:40 +0200
>
> > From: Eric Dumazet <edumazet@google.com>
> >
> > commit 92101b3b2e317 (ipv4: Prepare for change of rt->rt_iif encoding.)
> > invalidated TCP early demux, because rx_dst_ifindex is not properly
> > initialized and checked.
> >
> > Also remove the use of inet_iif(skb) in favor or skb->skb_iif
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
>
> Applied.
Thanks David
IPv6 part is screwed because of the bogus dst_check(dst, 0)
(and missing code that was moved out from tcp_rcv_established() to
tcp_v4_do_rcv() : I was wondering if we could make it generic to move it
back to tcp_rcv_established()) :
if (sk->sk_rx_dst) {
struct dst_entry *dst = sk->sk_rx_dst;
if (dst->ops->check(dst, 0) == NULL) {
dst_release(dst);
sk->sk_rx_dst = NULL;
}
}
if (unlikely(sk->sk_rx_dst == NULL)) {
sk->sk_rx_dst = dst_clone(skb_dst(skb));
inet_sk(sk)->rx_dst_ifindex = inet_iif(skb);
}
IPv6 wants a cookie here, not 0
I wonder why cookie is not stored in dst, and must be stored outside of
it ?
We could then use :
if (sk->sk_rx_dst) {
struct dst_entry *dst = sk->sk_rx_dst;
if (dst->ops->check(dst) == NULL) {
dst_release(dst);
sk->sk_rx_dst = NULL;
}
}
^ permalink raw reply
* Re: [PATCH] ipv4: fix TCP early demux
From: David Miller @ 2012-07-27 23:00 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1343424873.2626.13112.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 27 Jul 2012 23:34:33 +0200
> I wonder why cookie is not stored in dst, and must be stored outside
> of it ?
Because in ipv6, cloned routes are never invalidated on a route
insertion or deletion. We keep them around.
The fn_sernum tracks path reachability, rather than validation of
dsts.
So when we delete or insert a new ipv6 route, we update the serial
number of all the FIB nodes on the way down to the insert/delete
point.
If, afterwards, we can still reach a route cloned from one of those
entries successfully. It is still valid.
If we were to store the serial number on the dst, it would invalidate
the cloned route, which the ipv6 code is largely not designed for.
To be honest, the whole route validation scheme in ipv6 was
jackhammered into place. It was basically two years of Alexey
repairing the largely broken scheme that Pedro had put into place.
This is ~1997 legacy stuff.
It deserves a complete rewrite, but we are too busy with ipv4 at the
moment. And frankly if nobody other than myself was concerned enough
to delete the ipv4 routing cache (code people actually use) the
likelyhood of anyone embarking on a task of similar size for ipv6 is
basically zero.
^ permalink raw reply
* [PATCH v2] ppp: add 64 bit stats
From: Kevin Groeneveld @ 2012-07-28 3:38 UTC (permalink / raw)
To: netdev; +Cc: Kevin Groeneveld
Add 64 bit stats to ppp driver. The 64 bit stats include tx_bytes,
rx_bytes, tx_packets and rx_packets. Other stats are still 32 bit.
The 64 bit stats can be retrieved via the ndo_get_stats operation. The
SIOCGPPPSTATS ioctl is still 32 bit stats only.
Signed-off-by: Kevin Groeneveld <kgroeneveld@gmail.com>
---
v2: - do not use percpu variables for stats
- use ppp_recv_lock/ppp_xmit_lock when reading 64 bit stats
drivers/net/ppp/ppp_generic.c | 58 ++++++++++++++++++++++++++++++++++-------
1 file changed, 48 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 5c05572..eb3f5ce 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -94,6 +94,18 @@ struct ppp_file {
#define PF_TO_CHANNEL(pf) PF_TO_X(pf, struct channel)
/*
+ * Data structure to hold primary network stats for which
+ * we want to use 64 bit storage. Other network stats
+ * are stored in dev->stats of the ppp strucute.
+ */
+struct ppp_link_stats {
+ u64 rx_packets;
+ u64 tx_packets;
+ u64 rx_bytes;
+ u64 tx_bytes;
+};
+
+/*
* Data structure describing one ppp unit.
* A ppp unit corresponds to a ppp network interface device
* and represents a multilink bundle.
@@ -136,6 +148,7 @@ struct ppp {
unsigned pass_len, active_len;
#endif /* CONFIG_PPP_FILTER */
struct net *ppp_net; /* the net we belong to */
+ struct ppp_link_stats stats64; /* 64 bit network stats */
};
/*
@@ -1021,9 +1034,34 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return err;
}
+struct rtnl_link_stats64*
+ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
+{
+ struct ppp *ppp = netdev_priv(dev);
+
+ ppp_recv_lock(ppp);
+ stats64->rx_packets = ppp->stats64.rx_packets;
+ stats64->rx_bytes = ppp->stats64.rx_bytes;
+ ppp_recv_unlock(ppp);
+
+ ppp_xmit_lock(ppp);
+ stats64->tx_packets = ppp->stats64.tx_packets;
+ stats64->tx_bytes = ppp->stats64.tx_bytes;
+ ppp_xmit_unlock(ppp);
+
+ stats64->rx_errors = dev->stats.rx_errors;
+ stats64->tx_errors = dev->stats.tx_errors;
+ stats64->rx_dropped = dev->stats.rx_dropped;
+ stats64->tx_dropped = dev->stats.tx_dropped;
+ stats64->rx_length_errors = dev->stats.rx_length_errors;
+
+ return stats64;
+}
+
static const struct net_device_ops ppp_netdev_ops = {
- .ndo_start_xmit = ppp_start_xmit,
- .ndo_do_ioctl = ppp_net_ioctl,
+ .ndo_start_xmit = ppp_start_xmit,
+ .ndo_do_ioctl = ppp_net_ioctl,
+ .ndo_get_stats64 = ppp_get_stats64,
};
static void ppp_setup(struct net_device *dev)
@@ -1157,8 +1195,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
#endif /* CONFIG_PPP_FILTER */
}
- ++ppp->dev->stats.tx_packets;
- ppp->dev->stats.tx_bytes += skb->len - 2;
+ ++ppp->stats64.tx_packets;
+ ppp->stats64.tx_bytes += skb->len - 2;
switch (proto) {
case PPP_IP:
@@ -1745,8 +1783,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
break;
}
- ++ppp->dev->stats.rx_packets;
- ppp->dev->stats.rx_bytes += skb->len - 2;
+ ++ppp->stats64.rx_packets;
+ ppp->stats64.rx_bytes += skb->len - 2;
npi = proto_to_npindex(proto);
if (npi < 0) {
@@ -2570,12 +2608,12 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
struct slcompress *vj = ppp->vj;
memset(st, 0, sizeof(*st));
- st->p.ppp_ipackets = ppp->dev->stats.rx_packets;
+ st->p.ppp_ipackets = ppp->stats64.rx_packets;
st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
- st->p.ppp_ibytes = ppp->dev->stats.rx_bytes;
- st->p.ppp_opackets = ppp->dev->stats.tx_packets;
+ st->p.ppp_ibytes = ppp->stats64.rx_bytes;
+ st->p.ppp_opackets = ppp->stats64.tx_packets;
st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
- st->p.ppp_obytes = ppp->dev->stats.tx_bytes;
+ st->p.ppp_obytes = ppp->stats64.tx_bytes;
if (!vj)
return;
st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH 00/16] Remove the ipv4 routing cache
From: David Miller @ 2012-07-28 4:15 UTC (permalink / raw)
To: alexander.duyck; +Cc: eric.dumazet, netdev
In-Reply-To: <20120726.230246.219188476590178857.davem@davemloft.net>
From: David Miller <davem@davemloft.net>
Date: Thu, 26 Jul 2012 23:02:46 -0700 (PDT)
> Therefore one area of simplification would be to just return a pointer
> to the FIB nexthop, rather than the fib_info pointer and the nexthop
> index. We can get to the fib_info, if we need to, via the nh_parent
> pointer of the nexthop.
So I'm about to post an RFC set of patches which show this kind
of simplification. It gets fib_result down to two members:
u32 tclassid;
struct fib_nh *nh;
If I could get rid of that tclassid it would be really nice. But
that's hard because the tclassid is fetched from the fib_rule and
all of that lookup path is abstracted behind a common layer
that's shared between ipv4 and ipv6 so it's a bit of work changing
arg conventions.
These changes help, but only ever so slightly, in my testing.
^ permalink raw reply
* [PATCH 0/7] Deconstruct struct fib_result
From: David Miller @ 2012-07-28 4:18 UTC (permalink / raw)
To: alexander.duyck; +Cc: eric.dumazet, netdev
This patch set tries to move towards reducing struct fib_result down
to it's absolute minimum.
The eventual idea is to make it so that fib_lookup() simply
returns a "struct fib_nh *" and pointer encoded errnos, instead
of writing into a complicated structure as the return value on
the stack as is done now.
Signed-off-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply
* [PATCH 1/7] ipv4: Provide fib_nh instead of fib_info in fib_result.
From: David Miller @ 2012-07-28 4:18 UTC (permalink / raw)
To: alexander.duyck; +Cc: eric.dumazet, netdev
The latter can be obtained via nh->nh_parent, and this makes
the fib_result->nh_sel member no longer necessary.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
include/net/ip_fib.h | 43 +++++++++++-------------
net/ipv4/devinet.c | 2 +-
net/ipv4/fib_frontend.c | 28 +++++++++-------
net/ipv4/fib_lookup.h | 11 -------
net/ipv4/fib_semantics.c | 54 +++++++++++++++---------------
net/ipv4/fib_trie.c | 7 ++--
net/ipv4/route.c | 82 ++++++++++++++++++++++------------------------
7 files changed, 108 insertions(+), 119 deletions(-)
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index e69c3a4..eb62a2f 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -123,14 +123,14 @@ struct fib_rule;
struct fib_table;
struct fib_result {
- unsigned char prefixlen;
- unsigned char nh_sel;
- unsigned char type;
- unsigned char scope;
- u32 tclassid;
- struct fib_info *fi;
- struct fib_table *table;
- struct list_head *fa_head;
+ unsigned char prefixlen;
+ unsigned char __pad;
+ unsigned char type;
+ unsigned char scope;
+ u32 tclassid;
+ struct fib_nh *nh;
+ struct fib_table *table;
+ struct list_head *fa_head;
};
struct fib_result_nl {
@@ -150,31 +150,28 @@ struct fib_result_nl {
#ifdef CONFIG_IP_ROUTE_MULTIPATH
-#define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
-
#define FIB_TABLE_HASHSZ 2
#else /* CONFIG_IP_ROUTE_MULTIPATH */
-#define FIB_RES_NH(res) ((res).fi->fib_nh[0])
-
#define FIB_TABLE_HASHSZ 256
#endif /* CONFIG_IP_ROUTE_MULTIPATH */
extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
-#define FIB_RES_SADDR(net, res) \
- ((FIB_RES_NH(res).nh_saddr_genid == \
- atomic_read(&(net)->ipv4.dev_addr_genid)) ? \
- FIB_RES_NH(res).nh_saddr : \
- fib_info_update_nh_saddr((net), &FIB_RES_NH(res)))
-#define FIB_RES_GW(res) (FIB_RES_NH(res).nh_gw)
-#define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev)
-#define FIB_RES_OIF(res) (FIB_RES_NH(res).nh_oif)
+static inline __be32 fib_res_prefsrc(struct net *net, struct fib_result *res)
+{
+ struct fib_nh *nh = res->nh;
+ struct fib_info *fi;
-#define FIB_RES_PREFSRC(net, res) ((res).fi->fib_prefsrc ? : \
- FIB_RES_SADDR(net, res))
+ fi = nh->nh_parent;
+ if (fi->fib_prefsrc)
+ return fi->fib_prefsrc;
+ if (nh->nh_saddr_genid == atomic_read(&net->ipv4.dev_addr_genid))
+ return nh->nh_saddr;
+ return fib_info_update_nh_saddr(net, nh);
+}
struct fib_table {
struct hlist_node tb_hlist;
@@ -302,7 +299,7 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
#ifdef CONFIG_IP_MULTIPLE_TABLES
u32 rtag;
#endif
- *itag = FIB_RES_NH(*res).nh_tclassid<<16;
+ *itag = res->nh->nh_tclassid<<16;
#ifdef CONFIG_IP_MULTIPLE_TABLES
rtag = res->tclassid;
if (*itag == 0)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 44bf82e..1baaa53 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -164,7 +164,7 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
if (local &&
!fib_table_lookup(local, &fl4, &res, FIB_LOOKUP_NOREF) &&
res.type == RTN_LOCAL)
- result = FIB_RES_DEV(res);
+ result = res.nh->nh_dev;
}
if (result && devref)
dev_hold(result);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 8732cc7..d2e8dbe 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -174,7 +174,7 @@ static inline unsigned int __inet_dev_addr_type(struct net *net,
ret = RTN_UNICAST;
rcu_read_lock();
if (!fib_table_lookup(local_table, &fl4, &res, FIB_LOOKUP_NOREF)) {
- if (!dev || dev == res.fi->fib_dev)
+ if (!dev || dev == res.nh->nh_dev)
ret = res.type;
}
rcu_read_unlock();
@@ -225,7 +225,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
fl4.flowi4_scope = scope;
fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
if (!fib_lookup(net, &fl4, &res))
- return FIB_RES_PREFSRC(net, res);
+ return fib_res_prefsrc(net, &res);
} else {
scope = RT_SCOPE_LINK;
}
@@ -247,6 +247,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
{
int ret, no_addr, accept_local;
struct fib_result res;
+ struct fib_info *fi;
struct flowi4 fl4;
struct net *net;
bool dev_match;
@@ -273,21 +274,17 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
fib_combine_itag(itag, &res);
dev_match = false;
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
- for (ret = 0; ret < res.fi->fib_nhs; ret++) {
- struct fib_nh *nh = &res.fi->fib_nh[ret];
+ fi = res.nh->nh_parent;
+ for (ret = 0; ret < fi->fib_nhs; ret++) {
+ struct fib_nh *nh = &fi->fib_nh[ret];
if (nh->nh_dev == dev) {
dev_match = true;
break;
}
}
-#else
- if (FIB_RES_DEV(res) == dev)
- dev_match = true;
-#endif
if (dev_match) {
- ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+ ret = res.nh->nh_scope >= RT_SCOPE_HOST;
return ret;
}
if (no_addr)
@@ -299,7 +296,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
ret = 0;
if (fib_lookup(net, &fl4, &res) == 0) {
if (res.type == RTN_UNICAST)
- ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+ ret = res.nh->nh_scope >= RT_SCOPE_HOST;
}
return ret;
@@ -939,8 +936,15 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
frn->err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF);
if (!frn->err) {
+ struct fib_nh *nh = res.nh;
+ struct fib_info *fi;
+ int nhsel;
+
+ fi = nh->nh_parent;
+ nhsel = nh - &fi->fib_nh[0];
+
frn->prefixlen = res.prefixlen;
- frn->nh_sel = res.nh_sel;
+ frn->nh_sel = nhsel;
frn->type = res.type;
frn->scope = res.scope;
}
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index af0f14a..5f110b6 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -36,17 +36,6 @@ extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
unsigned int nlm_flags);
extern struct fib_alias *fib_find_alias(struct list_head *fah,
u8 tos, u32 prio);
-extern int fib_detect_death(struct fib_info *fi, int order,
- struct fib_info **last_resort,
- int *last_idx, int dflt);
-
-static inline void fib_result_assign(struct fib_result *res,
- struct fib_info *fi)
-{
- /* we used to play games with refcounts, but we now use RCU */
- res->fi = fi;
-}
-
struct fib_prop {
int error;
u8 scope;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index da0cc2e..b830245 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -393,13 +393,14 @@ struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio)
return NULL;
}
-int fib_detect_death(struct fib_info *fi, int order,
- struct fib_info **last_resort, int *last_idx, int dflt)
+int fib_detect_death(struct fib_nh *nh, int order,
+ struct fib_nh **last_resort, int *last_idx,
+ int dflt)
{
struct neighbour *n;
int state = NUD_NONE;
- n = neigh_lookup(&arp_tbl, &fi->fib_nh[0].nh_gw, fi->fib_dev);
+ n = neigh_lookup(&arp_tbl, &nh->nh_gw, nh->nh_dev);
if (n) {
state = n->nud_state;
neigh_release(n);
@@ -410,7 +411,7 @@ int fib_detect_death(struct fib_info *fi, int order,
return 0;
if ((state & NUD_VALID) ||
(*last_idx < 0 && order > dflt)) {
- *last_resort = fi;
+ *last_resort = nh;
*last_idx = order;
}
return 1;
@@ -612,8 +613,8 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
goto out;
nh->nh_scope = res.scope;
- nh->nh_oif = FIB_RES_OIF(res);
- nh->nh_dev = dev = FIB_RES_DEV(res);
+ nh->nh_oif = res.nh->nh_oif;
+ nh->nh_dev = dev = res.nh->nh_dev;
if (!dev)
goto out;
dev_hold(dev);
@@ -1130,54 +1131,55 @@ int fib_sync_down_dev(struct net_device *dev, int force)
/* Must be invoked inside of an RCU protected region. */
void fib_select_default(struct fib_result *res)
{
- struct fib_info *fi = NULL, *last_resort = NULL;
+ struct fib_nh *nh = NULL, *last_resort = NULL;
struct list_head *fa_head = res->fa_head;
struct fib_table *tb = res->table;
int order = -1, last_idx = -1;
struct fib_alias *fa;
list_for_each_entry_rcu(fa, fa_head, fa_list) {
- struct fib_info *next_fi = fa->fa_info;
+ struct fib_nh *next_nh = &fa->fa_info->fib_nh[0];
- if (next_fi->fib_scope != res->scope ||
+ if (next_nh->nh_parent->fib_scope != res->scope ||
fa->fa_type != RTN_UNICAST)
continue;
- if (next_fi->fib_priority > res->fi->fib_priority)
+ if (next_nh->nh_parent->fib_priority >
+ res->nh->nh_parent->fib_priority)
break;
- if (!next_fi->fib_nh[0].nh_gw ||
- next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+
+ if (!next_nh->nh_gw || next_nh->nh_scope != RT_SCOPE_LINK)
continue;
fib_alias_accessed(fa);
- if (fi == NULL) {
- if (next_fi != res->fi)
+ if (nh == NULL) {
+ if (next_nh != res->nh)
break;
- } else if (!fib_detect_death(fi, order, &last_resort,
+ } else if (!fib_detect_death(nh, order, &last_resort,
&last_idx, tb->tb_default)) {
- fib_result_assign(res, fi);
+ res->nh = nh;
tb->tb_default = order;
goto out;
}
- fi = next_fi;
+ nh = next_nh;
order++;
}
- if (order <= 0 || fi == NULL) {
+ if (order <= 0 || nh == NULL) {
tb->tb_default = -1;
goto out;
}
- if (!fib_detect_death(fi, order, &last_resort, &last_idx,
- tb->tb_default)) {
- fib_result_assign(res, fi);
+ if (!fib_detect_death(nh, order, &last_resort, &last_idx,
+ tb->tb_default)) {
+ res->nh = nh;
tb->tb_default = order;
goto out;
}
if (last_idx >= 0)
- fib_result_assign(res, last_resort);
+ res->nh = last_resort;
tb->tb_default = last_idx;
out:
return;
@@ -1249,7 +1251,7 @@ int fib_sync_up(struct net_device *dev)
*/
void fib_select_multipath(struct fib_result *res)
{
- struct fib_info *fi = res->fi;
+ struct fib_info *fi = res->nh->nh_parent;
int w;
spin_lock_bh(&fib_multipath_lock);
@@ -1265,7 +1267,7 @@ void fib_select_multipath(struct fib_result *res)
if (power <= 0) {
spin_unlock_bh(&fib_multipath_lock);
/* Race condition: route has just become dead. */
- res->nh_sel = 0;
+ res->nh = &fi->fib_nh[0];
return;
}
}
@@ -1284,7 +1286,7 @@ void fib_select_multipath(struct fib_result *res)
if (w <= 0) {
nexthop_nh->nh_power--;
fi->fib_power--;
- res->nh_sel = nhsel;
+ res->nh = &fi->fib_nh[nhsel];
spin_unlock_bh(&fib_multipath_lock);
return;
}
@@ -1292,7 +1294,7 @@ void fib_select_multipath(struct fib_result *res)
} endfor_nexthops(fi);
/* Race condition: route has just become dead. */
- res->nh_sel = 0;
+ res->nh = &fi->fib_nh[0];
spin_unlock_bh(&fib_multipath_lock);
}
#endif
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 18cbc15..04b0e26 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1384,7 +1384,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
if (fi->fib_flags & RTNH_F_DEAD)
continue;
for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
- const struct fib_nh *nh = &fi->fib_nh[nhsel];
+ struct fib_nh *nh = &fi->fib_nh[nhsel];
if (nh->nh_flags & RTNH_F_DEAD)
continue;
@@ -1395,10 +1395,9 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
t->stats.semantic_match_passed++;
#endif
res->prefixlen = li->plen;
- res->nh_sel = nhsel;
res->type = fa->fa_type;
- res->scope = fa->fa_info->fib_scope;
- res->fi = fi;
+ res->scope = fi->fib_scope;
+ res->nh = nh;
res->table = tb;
res->fa_head = &li->falh;
if (!(fib_flags & FIB_LOOKUP_NOREF))
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index fc1a81c..0b3277c 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -722,7 +722,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
neigh_event_send(n, NULL);
} else {
if (fib_lookup(net, fl4, &res) == 0) {
- struct fib_nh *nh = &FIB_RES_NH(res);
+ struct fib_nh *nh = res.nh;
update_or_create_fnhe(nh, fl4->daddr, new_gw,
0, 0);
@@ -926,7 +926,7 @@ static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
mtu = ip_rt_min_pmtu;
if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) {
- struct fib_nh *nh = &FIB_RES_NH(res);
+ struct fib_nh *nh = res.nh;
update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
jiffies + ip_rt_mtu_expires);
@@ -1085,7 +1085,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt)
rcu_read_lock();
if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0)
- src = FIB_RES_PREFSRC(dev_net(rt->dst.dev), res);
+ src = fib_res_prefsrc(dev_net(rt->dst.dev), &res);
else
src = inet_select_addr(rt->dst.dev,
rt_nexthop(rt, iph->daddr),
@@ -1237,16 +1237,14 @@ static bool rt_cache_valid(const struct rtable *rt)
static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
const struct fib_result *res,
struct fib_nh_exception *fnhe,
- struct fib_info *fi, u16 type, u32 itag)
+ struct fib_nh *nh, u16 type, u32 itag)
{
- if (fi) {
- struct fib_nh *nh = &FIB_RES_NH(*res);
-
+ if (nh) {
if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
rt->rt_gateway = nh->nh_gw;
if (unlikely(fnhe))
rt_bind_exception(rt, fnhe, daddr);
- dst_init_metrics(&rt->dst, fi->fib_metrics, true);
+ dst_init_metrics(&rt->dst, nh->nh_parent->fib_metrics, true);
#ifdef CONFIG_IP_ROUTE_CLASSID
rt->dst.tclassid = nh->nh_tclassid;
#endif
@@ -1373,6 +1371,7 @@ static int __mkroute_input(struct sk_buff *skb,
struct in_device *in_dev,
__be32 daddr, __be32 saddr, u32 tos)
{
+ struct fib_nh *nh = res->nh;
struct rtable *rth;
int err;
struct in_device *out_dev;
@@ -1381,14 +1380,14 @@ static int __mkroute_input(struct sk_buff *skb,
u32 itag;
/* get a working reference to the output device */
- out_dev = __in_dev_get_rcu(FIB_RES_DEV(*res));
+ out_dev = __in_dev_get_rcu(nh->nh_dev);
if (out_dev == NULL) {
net_crit_ratelimited("Bug in ip_route_input_slow(). Please report.\n");
return -EINVAL;
}
- err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res),
+ err = fib_validate_source(skb, saddr, daddr, tos, nh->nh_oif,
in_dev->dev, in_dev, &itag);
if (err < 0) {
ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr,
@@ -1399,7 +1398,7 @@ static int __mkroute_input(struct sk_buff *skb,
if (out_dev == in_dev && err &&
(IN_DEV_SHARED_MEDIA(out_dev) ||
- inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
+ inet_addr_onlink(out_dev, saddr, nh->nh_gw)))
flags |= RTCF_DOREDIRECT;
if (skb->protocol != htons(ETH_P_IP)) {
@@ -1418,15 +1417,13 @@ static int __mkroute_input(struct sk_buff *skb,
}
do_cache = false;
- if (res->fi) {
- if (!itag) {
- rth = FIB_RES_NH(*res).nh_rth_input;
- if (rt_cache_valid(rth)) {
- skb_dst_set_noref(skb, &rth->dst);
- goto out;
- }
- do_cache = true;
+ if (!itag) {
+ rth = nh->nh_rth_input;
+ if (rt_cache_valid(rth)) {
+ skb_dst_set_noref(skb, &rth->dst);
+ goto out;
}
+ do_cache = true;
}
rth = rt_dst_alloc(out_dev->dev,
@@ -1448,7 +1445,7 @@ static int __mkroute_input(struct sk_buff *skb,
rth->dst.input = ip_forward;
rth->dst.output = ip_output;
- rt_set_nexthop(rth, daddr, res, NULL, res->fi, res->type, itag);
+ rt_set_nexthop(rth, daddr, res, NULL, nh, res->type, itag);
skb_dst_set(skb, &rth->dst);
out:
err = 0;
@@ -1463,7 +1460,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
__be32 daddr, __be32 saddr, u32 tos)
{
#ifdef CONFIG_IP_ROUTE_MULTIPATH
- if (res->fi && res->fi->fib_nhs > 1)
+ if (res->nh->nh_parent->fib_nhs > 1)
fib_select_multipath(res);
#endif
@@ -1507,7 +1504,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))
goto martian_source;
- res.fi = NULL;
+ res.nh = NULL;
if (ipv4_is_lbcast(daddr) || (saddr == 0 && daddr == 0))
goto brd_input;
@@ -1580,9 +1577,9 @@ brd_input:
local_input:
do_cache = false;
- if (res.fi) {
+ if (res.nh) {
if (!itag) {
- rth = FIB_RES_NH(res).nh_rth_input;
+ rth = res.nh->nh_rth_input;
if (rt_cache_valid(rth)) {
skb_dst_set_noref(skb, &rth->dst);
err = 0;
@@ -1616,7 +1613,7 @@ local_input:
rth->rt_flags &= ~RTCF_LOCAL;
}
if (do_cache)
- rt_cache_route(&FIB_RES_NH(res), rth);
+ rt_cache_route(res.nh, rth);
skb_dst_set(skb, &rth->dst);
err = 0;
goto out;
@@ -1706,8 +1703,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
struct net_device *dev_out,
unsigned int flags)
{
- struct fib_info *fi = res->fi;
struct fib_nh_exception *fnhe;
+ struct fib_nh *nh = res->nh;
struct in_device *in_dev;
u16 type = res->type;
struct rtable *rth;
@@ -1732,7 +1729,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
if (type == RTN_BROADCAST) {
flags |= RTCF_BROADCAST | RTCF_LOCAL;
- fi = NULL;
+ nh = NULL;
} else if (type == RTN_MULTICAST) {
flags |= RTCF_MULTICAST | RTCF_LOCAL;
if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr,
@@ -1742,15 +1739,15 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
* default one, but do not gateway in this case.
* Yes, it is hack.
*/
- if (fi && res->prefixlen < 4)
- fi = NULL;
+ if (nh && res->prefixlen < 4)
+ nh = NULL;
}
fnhe = NULL;
- if (fi) {
- fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr);
+ if (nh) {
+ fnhe = find_exception(nh, fl4->daddr);
if (!fnhe) {
- rth = FIB_RES_NH(*res).nh_rth_output;
+ rth = nh->nh_rth_output;
if (rt_cache_valid(rth)) {
dst_hold(&rth->dst);
return rth;
@@ -1760,7 +1757,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
rth = rt_dst_alloc(dev_out,
IN_DEV_CONF_GET(in_dev, NOPOLICY),
IN_DEV_CONF_GET(in_dev, NOXFRM),
- fi && !fnhe);
+ nh && !fnhe);
if (!rth)
return ERR_PTR(-ENOBUFS);
@@ -1795,7 +1792,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
#endif
}
- rt_set_nexthop(rth, fl4->daddr, res, fnhe, fi, type, 0);
+ rt_set_nexthop(rth, fl4->daddr, res, fnhe, nh, type, 0);
return rth;
}
@@ -1814,7 +1811,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
int orig_oif;
res.tclassid = 0;
- res.fi = NULL;
+ res.nh = NULL;
res.table = NULL;
orig_oif = fl4->flowi4_oif;
@@ -1915,7 +1912,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
}
if (fib_lookup(net, fl4, &res)) {
- res.fi = NULL;
+ res.nh = NULL;
res.table = NULL;
if (fl4->flowi4_oif) {
/* Apparently, routing tables are wrong. Assume,
@@ -1948,20 +1945,21 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
if (res.type == RTN_LOCAL) {
if (!fl4->saddr) {
- if (res.fi->fib_prefsrc)
- fl4->saddr = res.fi->fib_prefsrc;
+ struct fib_info *fi = res.nh->nh_parent;
+ if (fi->fib_prefsrc)
+ fl4->saddr = fi->fib_prefsrc;
else
fl4->saddr = fl4->daddr;
}
dev_out = net->loopback_dev;
fl4->flowi4_oif = dev_out->ifindex;
- res.fi = NULL;
+ res.nh = NULL;
flags |= RTCF_LOCAL;
goto make_route;
}
#ifdef CONFIG_IP_ROUTE_MULTIPATH
- if (res.fi->fib_nhs > 1 && fl4->flowi4_oif == 0)
+ if (res.nh->nh_parent->fib_nhs > 1 && fl4->flowi4_oif == 0)
fib_select_multipath(&res);
else
#endif
@@ -1971,9 +1969,9 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
fib_select_default(&res);
if (!fl4->saddr)
- fl4->saddr = FIB_RES_PREFSRC(net, res);
+ fl4->saddr = fib_res_prefsrc(net, &res);
- dev_out = FIB_RES_DEV(res);
+ dev_out = res.nh->nh_dev;
fl4->flowi4_oif = dev_out->ifindex;
--
1.7.10.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