* Re: [PATCH] htb: improved accuracy at high rates
From: Rick Jones @ 2012-10-22 17:35 UTC (permalink / raw)
To: Vimal; +Cc: davem, eric.dumazet, Jamal Hadi Salim, netdev
In-Reply-To: <CAK3Ji116nZ79csrq9GJ7C5e3zLPJina1r2+VasdVRsdY7n+3ww@mail.gmail.com>
On 10/19/2012 05:51 PM, Vimal wrote:
> On 19 October 2012 16:52, Rick Jones <rick.jones2@hp.com> wrote:
>>
>> First some netperf/operational kinds of questions:
>>
>> Did it really take 20 concurrent netperf UDP_STREAM tests to get to those
>> rates? And why UDP_STREAM rather than TCP_STREAM?
>
> Nope, even 1 netperf was sufficient. Before I couldn't get TCP_STREAM
> to send small byte packets, but I checked my script now and I forgot
> to enable TCP_NODELAY + send buffer size (-s $size).
>
> With one tcp sender I am unable to reach the 1Gb/s limit (only
> ~100Mb/s) even with a lot of CPU to spare, which indicates that the
> test is limited by e2e latency. With 10 connections, I could get only
> 800Mb/s, and with 20 connections it went to 1160Mb/s, which violates
> the 1Gb/s limit set.
Were you explicitly constraining the TCP socketbuffer/window via
test-specific -s and -S options? Or was this a system with little
enough memory that the upper limit for the TCP socket/window autotuning
wasn't the somewhat common, which would have been sufficient to cover a
rather large RTT, The results of the TCP_RR tests below suggest there
was actually very little e2e latency... which suggests something else
was holding-back the TCP performance. Perhaps lost packets?
Or does this suggest the need for an htb_codel?-) If your system can
have rrdtool installed on it, and you are indeed using a contemporary
version of netperf, you can run the bloat.sh script from doc/examples
and get an idea of how much bufferbloat there is in the setup.
If you are using a "current" version of netperf, you can use the omni
output selectors to have netperf emit the number of TCP retransmissions
on the data connection during the test. Otherwise, if the netperf tests
are the only things running at the time, you can take a snapshot of
netstat -s output before and after the test and run it through something
like beforeafter, or the other script I keep forgetting the name of :(
>> Which reported throughput was used from the UDP_STREAM tests - send side or
>> receive side?
>
> Send side.
Given the nature of UDP and that netperf makes no attempt to compensate
for that, it would be rather better to use receive-side throughout. The
receive side throughput is known to have made it through everything.
The send side throughput is only that which didn't report an error in
the sendto() call. And lack of error on the sendto() call does not
guarantee a successful transmission on the wire. Even under Linux with
intra-stack flow-control.
>> Is there much/any change in service demand on a netperf test? That is what
>> is the service demand of a mumble_STREAM test running through the old HTB
>> versus the new HTB? And/or the performance of a TCP_RR test (both
>> transactions per second and service demand per transaction) before vs after.
>>
>
> At 1Gb/s with just one TCP_STREAM:
> With old HTB:
> Sdem local: 0.548us/KB, Sdem remote: 1.426us/KB.
>
> With new HTB:
> Sdem local: 0.598us/KB, Sdem remote: 1.089us/KB.
Presumably the receive side service demand should have remained
unaffected by the HTB changes. That it changed by 40% suggests there
wasn't actually all that much stability - at least not on the receive
side. Was there a large change in throughput for the single-stream?
That there was a 9% increase in sending service demand is a bit
troubling, and at least slightly at odds with the little to no change in
the sending service demand for the TCP_RR tests below. I suppose that
the "timing" nature of having things like small sends and TCP_NODELAY
set can introduce too many variables.
One other way to skin the cat of "what does it do to sending service
demand would be to stick with TCP_RR and walk-up the request size.
Without a burst mode enabled, and just the one transaction in flight at
one time, TCP_NODELAY on/off should be a don't care. So, something
along the lines of:
HDR="-P 1"
for r in 1 4 16 64 256 1024 4096 16384 65535
do
netperf $HDR -H <remote> -t TCP_RR -c -C -l 30 -- -r ${r},1
HDR="-P 0"
done
> TCP_RR: 1b req/response consumed very little bandwidth (~12Mb/s)
That is why, by default, it reports a transaction per second rate and
not a bandwidth :)
> old HTB at 1Gb/s
> Sdem local: 14.738us/trans, Sdem remote: 11.485us/Tran, latency: 41.622us/Tran.
>
> new HTB at 1Gb/s
> Sdem local: 14.505us/trans, Sdem remote: 11.440us/Tran, latency: 41.709us/Tran.
>
> With multiple tests, these values are fairly stable. :)
Those do look like they were within the noise level.
Out of mostly idle curiousity, just what sort of system was being used
for the testing? CPU, bitness, memory etc.
happy benchmarking,
rick jones
^ permalink raw reply
* Re: Re: A reliable kernel panic (3.6.2) and system crash when visiting a particular website
From: Artem S. Tashkinov @ 2012-10-22 17:30 UTC (permalink / raw)
To: stern
Cc: zonque, bp, pavel, linux-kernel, netdev, security, linux-media,
linux-usb, alsa-devel
In-Reply-To: <Pine.LNX.4.44L0.1210221153140.1724-100000@iolanthe.rowland.org>
On Oct 22, 2012, Alan Stern <stern@rowland.harvard.edu> wrote:
> A BUG() at these points would crash the machine hard. And where we
> came from doesn't matter; what matters is the values in the pointers.
OK, here's what the kernel prints with your patch:
usb 6.1.4: ep 86 list del corruption prev: e5103b54 e5103a94 e51039d4
A small delay before I got thousands of list_del corruption messages would
have been nice, but I managed to catch the message anyway.
Artem
^ permalink raw reply
* Re: PROBLEM: Memory leak (at least with SLUB) from "secpath_dup" (xfrm) in 3.5+ kernels
From: Eric Dumazet @ 2012-10-22 17:24 UTC (permalink / raw)
To: Mike Kazantsev; +Cc: Paul Moore, netdev, linux-mm
In-Reply-To: <20121022225918.32d86a5f@sacrilege>
On Mon, 2012-10-22 at 22:59 +0600, Mike Kazantsev wrote:
> On Mon, 22 Oct 2012 17:28:02 +0200
> Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
> > On Mon, 2012-10-22 at 17:22 +0200, Eric Dumazet wrote:
> > > On Mon, 2012-10-22 at 17:16 +0200, Eric Dumazet wrote:
> > >
> > > > OK, I believe I found the bug in IPv4 defrag / IPv6 reasm
> > > >
> > > > Please test the following patch.
> > > >
> > > > Thanks !
> > >
> > > I'll send a more generic patch in a few minutes, changing
> > > kfree_skb_partial() to call skb_release_head_state()
> > >
> >
> > Here it is :
> >
> ...
>
> Problem is indeed gone in v3.7-rc2 with the proposed generic patch, I
> haven't read the mail in time to test the first one, but I guess it's
> not relevant now that the latter one works.
>
> Thank you for taking your time to look into the problem and actually
> fix it.
>
> I'm unclear about policies in place on the matter, but I think this
> patch might be a good candidate to backport into 3.5 and 3.6 kernels,
> because they seem to suffer from the issue as well.
Thanks a lot Mike for your help.
Dont worry, I'll submit an official patch with details and all credits.
David Miller will forward it to stable teams.
Thanks !
^ permalink raw reply
* RE: [PATCH] qla3xxx: Ensure request/response queue addr writes to the registers
From: Jitendra Kalsaria @ 2012-10-22 17:17 UTC (permalink / raw)
To: Joe Jin, Ron Mercer, Dept-Eng Linux Driver, David Miller,
Andrew Morton
Cc: netdev, linux-kernel, Greg Marsden
In-Reply-To: <50849604.9050109@oracle.com>
>From: Joe Jin [mailto:joe.jin@oracle.com]
>Sent: Sunday, October 21, 2012 5:41 PM
>To: Jitendra Kalsaria; Ron Mercer; Dept-Eng Linux Driver; David Miller; Andrew Morton
>Cc: netdev; linux-kernel; Greg Marsden
>Subject: [PATCH] qla3xxx: Ensure request/response queue addr writes to the registers
>
>Before use the request and response queue addr, make sure it has wrote
>to the registers.
>
>Signed-off-by: Joe Jin <joe.jin@oracle.com>
>Cc: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
>Cc: Ron Mercer <ron.mercer@qlogic.com>
>---
> drivers/net/ethernet/qlogic/qla3xxx.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
>diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c
>index df09b1c..6407d0d 100644
>--- a/drivers/net/ethernet/qlogic/qla3xxx.c
>+++ b/drivers/net/ethernet/qlogic/qla3xxx.c
>@@ -2525,6 +2525,13 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
> qdev->req_q_size =
> (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req));
>
>+ qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
>+
>+ /* The barrier is required to ensure request and response queue
>+ * addr writes to the registers.
>+ */
>+ wmb();
>+
> qdev->req_q_virt_addr =
> pci_alloc_consistent(qdev->pdev,
> (size_t) qdev->req_q_size,
>@@ -2536,8 +2543,6 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
> return -ENOMEM;
> }
>
>- qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
>-
> qdev->rsp_q_virt_addr =
> pci_alloc_consistent(qdev->pdev,
> (size_t) qdev->rsp_q_size,
Acked-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
--
1.7.11.7
^ permalink raw reply
* [PATCH v2 3/3] pppoatm: protect against freeing of vcc
From: Krzysztof Mazur @ 2012-10-22 17:14 UTC (permalink / raw)
To: davem; +Cc: dwmw2, netdev, linux-kernel, Krzysztof Mazur
In-Reply-To: <1350926091-12642-1-git-send-email-krzysiek@podlesie.net>
The pppoatm gets a reference to atmvcc, but does not increment vcc
usage count. The vcc uses vcc->sk socket for reference counting,
so sock_hold() and sock_put() should be used by pppoatm.
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Cc: David Woodhouse <dwmw2@infradead.org>
---
net/atm/pppoatm.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index e3b2d69..a766d96 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -154,6 +154,7 @@ static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
tasklet_kill(&pvcc->wakeup_tasklet);
ppp_unregister_channel(&pvcc->chan);
atmvcc->user_back = NULL;
+ sock_put(sk_atm(pvcc->atmvcc));
kfree(pvcc);
/* Gee, I hope we have the big kernel lock here... */
module_put(THIS_MODULE);
@@ -373,6 +374,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
if (pvcc == NULL)
return -ENOMEM;
pvcc->atmvcc = atmvcc;
+ sock_hold(sk_atm(atmvcc));
/* Maximum is zero, so that we can use atomic_inc_not_zero() */
atomic_set(&pvcc->inflight, NONE_INFLIGHT);
@@ -387,6 +389,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
pvcc->wakeup_tasklet.data = (unsigned long) &pvcc->chan;
err = ppp_register_channel(&pvcc->chan);
if (err != 0) {
+ sock_put(sk_atm(atmvcc));
kfree(pvcc);
return err;
}
--
1.8.0.2.g35080e9
^ permalink raw reply related
* [PATCH v2 2/3] pppoatm: fix race condition with destroying of vcc
From: Krzysztof Mazur @ 2012-10-22 17:14 UTC (permalink / raw)
To: davem; +Cc: dwmw2, netdev, linux-kernel, Krzysztof Mazur
In-Reply-To: <1350926091-12642-1-git-send-email-krzysiek@podlesie.net>
The pppoatm_send() calls vcc->send() and now also checks for
some vcc flags that indicate destroyed vcc without proper locking.
The vcc_sendmsg() uses lock_sock(sk). This lock is used by
vcc_release(), so vcc_destroy_socket() will not be called between
check and during ->send(). The vcc_release_async() sets ATM_VF_CLOSE,
but it should be safe to call ->send() after it, because
vcc->dev->ops->close() is not called.
The pppoatm_send() is called with BH disabled, so bh_lock_sock()
should be used instead of lock_sock().
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Cc: David Woodhouse <dwmw2@infradead.org>
---
net/atm/pppoatm.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 0dcb5dc..e3b2d69 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -270,6 +270,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
{
struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
struct atm_vcc *vcc;
+ int ret;
ATM_SKB(skb)->vcc = pvcc->atmvcc;
pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
@@ -304,17 +305,24 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
}
vcc = ATM_SKB(skb)->vcc;
+ bh_lock_sock(sk_atm(vcc));
+ if (sock_owned_by_user(sk_atm(vcc)))
+ goto nospace_unlock_sock;
if (test_bit(ATM_VF_RELEASED, &vcc->flags)
|| test_bit(ATM_VF_CLOSE, &vcc->flags)
|| !test_bit(ATM_VF_READY, &vcc->flags))
- goto nospace;
+ goto nospace_unlock_sock;
atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
- return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
+ ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
? DROP_PACKET : 1;
+ bh_unlock_sock(sk_atm(vcc));
+ return ret;
+nospace_unlock_sock:
+ bh_unlock_sock(sk_atm(vcc));
nospace:
/*
* We don't have space to send this SKB now, but we might have
--
1.8.0.2.g35080e9
^ permalink raw reply related
* [PATCH v2 1/3] pppoatm: don't send frames to destroyed vcc
From: Krzysztof Mazur @ 2012-10-22 17:14 UTC (permalink / raw)
To: davem; +Cc: dwmw2, netdev, linux-kernel, Krzysztof Mazur
The pppoatm_send() uses vcc->send() directly and does not check if vcc
is ready for send(). This causes Oops when send() is used after
vcc_destroy_socket() at least with usbatm driver:
Oops: 0000 [#1] PREEMPT
Pid: 0, comm: swapper Not tainted 3.6.0-krzysiek-00001-gb7cd93b-dirty #60 /AK32
EIP: 0060:[<c01413c6>] EFLAGS: 00010082 CPU: 0
EIP is at __wake_up_common+0x16/0x70
EAX: 30707070 EBX: 00000292 ECX: 00000001 EDX: dca75fc0
ESI: 00000000 EDI: de7f500f EBP: df409f24 ESP: df409f08
DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068
CR0: 8005003b CR2: 30707070 CR3: 1c920000 CR4: 000007d0
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
Process swapper (pid: 0, ti=df408000 task=c07bd4e0 task.ti=c07b0000)
Stack:
00000000 00000001 00000001 dca75fc0 00000292 00000000 de7f500f df409f3c
c0143299 00000000 00000000 dc84f000 dc84f000 df409f4c c0602bf0 00000000
dc84f000 df409f58 c0604301 dc840cc0 df409fb4 c04672e5 c076a240 00000000
Call Trace:
[<c0143299>] __wake_up+0x29/0x50
[<c0602bf0>] vcc_write_space+0x40/0x80
[<c0604301>] atm_pop_raw+0x21/0x30
[<c04672e5>] usbatm_tx_process+0x2a5/0x380
[<c0126cf9>] tasklet_action+0x39/0x70
[<c0126f1f>] __do_softirq+0x7f/0x120
[<c0126ea0>] ? local_bh_enable_ip+0xa0/0xa0
<IRQ>
Now pppoatm_send(), like vcc_sendmsg(), checks for vcc flags that
indicate that vcc is not ready.
Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net>
Cc: David Woodhouse <dwmw2@infradead.org>
---
Previously sent with more details as:
http://marc.info/?l=linux-kernel&m=134952646810580&w=2
This patch extends race window between pppoatm_send() and vcc_destroy_socket().
This race exists also without this patch and it's fixed in patch 2.
net/atm/pppoatm.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 226dca9..0dcb5dc 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -269,6 +269,8 @@ static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
{
struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
+ struct atm_vcc *vcc;
+
ATM_SKB(skb)->vcc = pvcc->atmvcc;
pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
@@ -301,6 +303,12 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
return 1;
}
+ vcc = ATM_SKB(skb)->vcc;
+ if (test_bit(ATM_VF_RELEASED, &vcc->flags)
+ || test_bit(ATM_VF_CLOSE, &vcc->flags)
+ || !test_bit(ATM_VF_READY, &vcc->flags))
+ goto nospace;
+
atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
--
1.8.0.2.g35080e9
^ permalink raw reply related
* Re: [PATCH RESEND net-next] bluetooth: hci_core: Replace list_for_each with list_for_each_entry() helper
From: Marcel Holtmann @ 2012-10-22 17:00 UTC (permalink / raw)
To: Denis Kirjanov
Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q,
linux-bluetooth-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1350912121-24171-1-git-send-email-kirjanov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Hi Denis,
> Replace list_for_each with list_for_each_entry() helper
>
> Signed-off-by: Denis Kirjanov <kirjanov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> include/net/bluetooth/hci_core.h | 20 ++++++++------------
> 1 files changed, 8 insertions(+), 12 deletions(-)
Acked-by: Marcel Holtmann <marcel-kz+m5ild9QBg9hUCZPvPmw@public.gmane.org>
Regards
Marcel
^ permalink raw reply
* Re: PROBLEM: Memory leak (at least with SLUB) from "secpath_dup" (xfrm) in 3.5+ kernels
From: Mike Kazantsev @ 2012-10-22 16:59 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Paul Moore, netdev, linux-mm
In-Reply-To: <1350919682.8609.877.camel@edumazet-glaptop>
[-- Attachment #1: Type: text/plain, Size: 1012 bytes --]
On Mon, 22 Oct 2012 17:28:02 +0200
Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Mon, 2012-10-22 at 17:22 +0200, Eric Dumazet wrote:
> > On Mon, 2012-10-22 at 17:16 +0200, Eric Dumazet wrote:
> >
> > > OK, I believe I found the bug in IPv4 defrag / IPv6 reasm
> > >
> > > Please test the following patch.
> > >
> > > Thanks !
> >
> > I'll send a more generic patch in a few minutes, changing
> > kfree_skb_partial() to call skb_release_head_state()
> >
>
> Here it is :
>
...
Problem is indeed gone in v3.7-rc2 with the proposed generic patch, I
haven't read the mail in time to test the first one, but I guess it's
not relevant now that the latter one works.
Thank you for taking your time to look into the problem and actually
fix it.
I'm unclear about policies in place on the matter, but I think this
patch might be a good candidate to backport into 3.5 and 3.6 kernels,
because they seem to suffer from the issue as well.
--
Mike Kazantsev // fraggod.net
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [nf-next PATCH] ipvs: fix build error when CONFIG_IP_VS_IPV6 is disabled
From: Pablo Neira Ayuso @ 2012-10-22 16:30 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Jesper Dangaard Brouer, Simon Horman, fengguang.wu, yuanhan.liu,
netdev, lvs-devel, netfilter-devel
In-Reply-To: <Pine.LNX.4.64.1210221732480.3065@ask.diku.dk>
On Mon, Oct 22, 2012 at 05:39:43PM +0200, Jesper Dangaard Brouer wrote:
>
> Hi Pablo,
>
> Argh - there is one more CONFIG option combi that can cause issues.
>
> *So hold off on this patch*
>
> Which is related to including linux/netfilter_ipv6/ip6_tables.h
> under CONFIG_IPV6 when CONFIG_NETFILTER is disabled, as
> kernel/sysctl_binary.c include net/ip_vs.h. I'll send a new patch
> soon!
Ok, wait for it.
Thanks for your quick response.
^ permalink raw reply
* Re: A reliable kernel panic (3.6.2) and system crash when visiting a particular website
From: Alan Stern @ 2012-10-22 15:54 UTC (permalink / raw)
To: Daniel Mack
Cc: Artem S. Tashkinov, bp, pavel, linux-kernel, netdev, security,
linux-media, linux-usb, alsa-devel
In-Reply-To: <5085667A.70408@gmail.com>
On Mon, 22 Oct 2012, Daniel Mack wrote:
> On 22.10.2012 17:17, Alan Stern wrote:
> > On Sun, 21 Oct 2012, Artem S. Tashkinov wrote:
> >
> >> dmesg messages up to a crash can be seen here: https://bugzilla.kernel.org/attachment.cgi?id=84221
> >
> > The first problem in the log is endpoint list corruption. Here's a
> > debugging patch which should provide a little more information.
>
> Maybe add a BUG() after each of these dev_err() so we stop at the first
> occurance and also see where we're coming from?
A BUG() at these points would crash the machine hard. And where we
came from doesn't matter; what matters is the values in the pointers.
Alan Stern
^ permalink raw reply
* Re: [nf-next PATCH] ipvs: fix build error when CONFIG_IP_VS_IPV6 is disabled
From: Jesper Dangaard Brouer @ 2012-10-22 15:39 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Pablo Neira Ayuso, Simon Horman, fengguang.wu, yuanhan.liu,
netdev, lvs-devel, netfilter-devel
In-Reply-To: <20121022121711.31397.6231.stgit@dragon>
Hi Pablo,
Argh - there is one more CONFIG option combi that can cause issues.
*So hold off on this patch*
Which is related to including linux/netfilter_ipv6/ip6_tables.h under
CONFIG_IPV6 when CONFIG_NETFILTER is disabled, as kernel/sysctl_binary.c
include net/ip_vs.h. I'll send a new patch soon!
--Jesper
On Mon, 22 Oct 2012, Jesper Dangaard Brouer wrote:
> From: Yuanhan Liu <yuanhan.liu@linux.intel.com>
>
> Fix build error introduced by commit 63dca2c0:
> "ipvs: Fix faulty IPv6 extension header handling in IPVS"
>
> The build error only occur, when CONFIG_IP_VS_IPV6 is disabled.
>
> Reported-by: Fengguang Wu <fengguang.wu@intel.com>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
> ---
>
> include/net/ip_vs.h | 3 ++-
> 1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
> index a681ad6..d930749 100644
> --- a/include/net/ip_vs.h
> +++ b/include/net/ip_vs.h
> @@ -212,8 +212,9 @@ ip_vs_fill_iph_addr_only(int af, const struct sk_buff *skb,
> (struct ipv6hdr *)skb_network_header(skb);
> iphdr->saddr.in6 = iph->saddr;
> iphdr->daddr.in6 = iph->daddr;
> - } else {
> + } else
> #endif
> + {
> const struct iphdr *iph =
> (struct iphdr *)skb_network_header(skb);
> iphdr->saddr.ip = iph->saddr;
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
Hilsen
Jesper Brouer
--
-------------------------------------------------------------------
MSc. Master of Computer Science
Dept. of Computer Science, University of Copenhagen
Author of http://www.adsl-optimizer.dk
-------------------------------------------------------------------
^ permalink raw reply
* Re: A reliable kernel panic (3.6.2) and system crash when visiting a particular website
From: Daniel Mack @ 2012-10-22 15:30 UTC (permalink / raw)
To: Alan Stern
Cc: Artem S. Tashkinov, bp, pavel, linux-kernel, netdev, security,
linux-media, linux-usb, alsa-devel
In-Reply-To: <Pine.LNX.4.44L0.1210221116040.1724-100000@iolanthe.rowland.org>
On 22.10.2012 17:17, Alan Stern wrote:
> On Sun, 21 Oct 2012, Artem S. Tashkinov wrote:
>
>> dmesg messages up to a crash can be seen here: https://bugzilla.kernel.org/attachment.cgi?id=84221
>
> The first problem in the log is endpoint list corruption. Here's a
> debugging patch which should provide a little more information.
Maybe add a BUG() after each of these dev_err() so we stop at the first
occurance and also see where we're coming from?
> drivers/usb/core/hcd.c | 36 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 36 insertions(+)
>
> Index: usb-3.6/drivers/usb/core/hcd.c
> ===================================================================
> --- usb-3.6.orig/drivers/usb/core/hcd.c
> +++ usb-3.6/drivers/usb/core/hcd.c
> @@ -1083,6 +1083,8 @@ EXPORT_SYMBOL_GPL(usb_calc_bus_time);
>
> /*-------------------------------------------------------------------------*/
>
> +static bool list_error;
> +
> /**
> * usb_hcd_link_urb_to_ep - add an URB to its endpoint queue
> * @hcd: host controller to which @urb was submitted
> @@ -1126,6 +1128,20 @@ int usb_hcd_link_urb_to_ep(struct usb_hc
> */
> if (HCD_RH_RUNNING(hcd)) {
> urb->unlinked = 0;
> +
> + {
> + struct list_head *cur = &urb->ep->urb_list;
> + struct list_head *prev = cur->prev;
> +
> + if (prev->next != cur && !list_error) {
> + list_error = true;
> + dev_err(&urb->dev->dev,
> + "ep %x list add corruption: %p %p %p\n",
> + urb->ep->desc.bEndpointAddress,
> + cur, prev, prev->next);
> + }
> + }
> +
> list_add_tail(&urb->urb_list, &urb->ep->urb_list);
> } else {
> rc = -ESHUTDOWN;
> @@ -1193,6 +1209,26 @@ void usb_hcd_unlink_urb_from_ep(struct u
> {
> /* clear all state linking urb to this dev (and hcd) */
> spin_lock(&hcd_urb_list_lock);
> + {
> + struct list_head *cur = &urb->urb_list;
> + struct list_head *prev = cur->prev;
> + struct list_head *next = cur->next;
> +
> + if (prev->next != cur && !list_error) {
> + list_error = true;
> + dev_err(&urb->dev->dev,
> + "ep %x list del corruption prev: %p %p %p\n",
> + urb->ep->desc.bEndpointAddress,
> + cur, prev, prev->next);
> + }
> + if (next->prev != cur && !list_error) {
> + list_error = true;
> + dev_err(&urb->dev->dev,
> + "ep %x list del corruption next: %p %p %p\n",
> + urb->ep->desc.bEndpointAddress,
> + cur, next, next->prev);
> + }
> + }
> list_del_init(&urb->urb_list);
> spin_unlock(&hcd_urb_list_lock);
> }
>
^ permalink raw reply
* Re: PROBLEM: Memory leak (at least with SLUB) from "secpath_dup" (xfrm) in 3.5+ kernels
From: Eric Dumazet @ 2012-10-22 15:28 UTC (permalink / raw)
To: Mike Kazantsev; +Cc: Paul Moore, netdev, linux-mm
In-Reply-To: <1350919337.8609.869.camel@edumazet-glaptop>
On Mon, 2012-10-22 at 17:22 +0200, Eric Dumazet wrote:
> On Mon, 2012-10-22 at 17:16 +0200, Eric Dumazet wrote:
>
> > OK, I believe I found the bug in IPv4 defrag / IPv6 reasm
> >
> > Please test the following patch.
> >
> > Thanks !
>
> I'll send a more generic patch in a few minutes, changing
> kfree_skb_partial() to call skb_release_head_state()
>
Here it is :
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 6e04b1f..4007c14 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3379,10 +3379,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding);
void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)
{
- if (head_stolen)
+ if (head_stolen) {
+ skb_release_head_state(skb);
kmem_cache_free(skbuff_head_cache, skb);
- else
+ } else {
__kfree_skb(skb);
+ }
}
EXPORT_SYMBOL(kfree_skb_partial);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* Re: PROBLEM: Memory leak (at least with SLUB) from "secpath_dup" (xfrm) in 3.5+ kernels
From: Eric Dumazet @ 2012-10-22 15:22 UTC (permalink / raw)
To: Mike Kazantsev; +Cc: Paul Moore, netdev, linux-mm
In-Reply-To: <1350918997.8609.858.camel@edumazet-glaptop>
On Mon, 2012-10-22 at 17:16 +0200, Eric Dumazet wrote:
> OK, I believe I found the bug in IPv4 defrag / IPv6 reasm
>
> Please test the following patch.
>
> Thanks !
I'll send a more generic patch in a few minutes, changing
kfree_skb_partial() to call skb_release_head_state()
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: net,sctp: oops in sctp_do_sm
From: Neil Horman @ 2012-10-22 15:19 UTC (permalink / raw)
To: Sasha Levin
Cc: vyasevich, sri, davem, linux-sctp, netdev,
linux-kernel@vger.kernel.org, Dave Jones
In-Reply-To: <5080BBF9.1080208@oracle.com>
On Thu, Oct 18, 2012 at 10:33:29PM -0400, Sasha Levin wrote:
> Hi all,
>
> While fuzzing with trinity inside a KVM tools (lkvm) guest running today's linux-next, I've
> stumbled on the following:
>
> [ 439.574039] BUG: unable to handle kernel paging request at ffff88001b9f40c8
> [ 439.576486] IP: [<ffffffff83746fc3>] sctp_do_sm+0x293/0x310
> [ 439.578128] PGD 4e27063 PUD 4e2b063 PMD 1fa57067 PTE 1b9f4160
> [ 439.580796] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
> [ 439.581635] Dumping ftrace buffer:
> [ 439.582171] (ftrace buffer empty)
> [ 439.582673] CPU 3
> [ 439.582957] Pid: 7101, comm: trinity-child16 Tainted: G W 3.7.0-rc1-next-20121018-sasha-00002-g60a870d-dirty #62
> [ 439.582986] RIP: 0010:[<ffffffff83746fc3>] [<ffffffff83746fc3>] sctp_do_sm+0x293/0x310
> [ 439.582986] RSP: 0018:ffff880010c57988 EFLAGS: 00010286
> [ 439.582986] RAX: 0000000000000003 RBX: 0000000000000001 RCX: 0000000000000006
> [ 439.582986] RDX: 0000000000000003 RSI: 0000000000000001 RDI: ffff880010c579d0
> [ 439.582986] RBP: ffff880010c57ae8 R08: 0000000000000000 R09: 0000000000000000
> [ 439.582986] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000004
> [ 439.582986] R13: ffff88001b9f4000 R14: ffff880065d22600 R15: 0000000000000003
> [ 439.582986] FS: 00007f9a949c3700(0000) GS:ffff880067600000(0000) knlGS:0000000000000000
> [ 439.582986] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [ 439.582986] CR2: ffff88001b9f40c8 CR3: 0000000015850000 CR4: 00000000000406e0
> [ 439.582986] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> [ 439.582986] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> [ 439.582986] Process trinity-child16 (pid: 7101, threadinfo ffff880010c56000, task ffff880010a98000)
> [ 439.582986] Stack:
> [ 439.582986] ffffffff000000d0 0000000000000000 ffffffff84c92d36 ffffffff84cc4b50
> [ 439.582986] ffffffff83763b30 0000000000000004 ffffffff842c0370 0000000181152f15
> [ 439.582986] ffff880010c579f8 0000000000000002 0000000000000015 0000000000000000
> [ 439.582986] Call Trace:
> [ 439.582986] [<ffffffff83763b30>] ? sctp_cname+0x70/0x70
> [ 439.582986] [<ffffffff83761403>] sctp_primitive_SHUTDOWN+0x43/0x50
> [ 439.582986] [<ffffffff8375bd70>] sctp_close+0x150/0x310
> [ 439.606533] [<ffffffff8351bf22>] inet_release+0x1b2/0x1c0
> [ 439.606533] [<ffffffff8351bd8d>] ? inet_release+0x1d/0x1c0
> [ 439.606533] [<ffffffff83578b04>] inet6_release+0x34/0x60
> [ 439.606533] [<ffffffff833c17b8>] sock_release+0x18/0x80
> [ 439.610261] [<ffffffff833c1849>] sock_close+0x29/0x30
> [ 439.610261] [<ffffffff812773f2>] __fput+0x122/0x2d0
> [ 439.610261] [<ffffffff812775a9>] ____fput+0x9/0x10
> [ 439.610261] [<ffffffff81131afe>] task_work_run+0xbe/0x100
> [ 439.610261] [<ffffffff811107e2>] do_exit+0x432/0xbd0
> [ 439.610261] [<ffffffff811243d9>] ? get_signal_to_deliver+0x899/0x910
> [ 439.610261] [<ffffffff8117b2e2>] ? get_lock_stats+0x22/0x70
> [ 439.610261] [<ffffffff8117b36e>] ? put_lock_stats.isra.16+0xe/0x40
> [ 439.610261] [<ffffffff83a6802b>] ? _raw_spin_unlock_irq+0x2b/0x80
> [ 439.610261] [<ffffffff81111044>] do_group_exit+0x84/0xd0
> [ 439.610261] [<ffffffff8112433d>] get_signal_to_deliver+0x7fd/0x910
> [ 439.610261] [<ffffffff8117dffd>] ? trace_hardirqs_off+0xd/0x10
> [ 439.620391] [<ffffffff819fe7db>] ? debug_object_assert_init+0xbb/0x110
> [ 439.620391] [<ffffffff8106d59a>] do_signal+0x3a/0x950
> [ 439.620391] [<ffffffff811c62c3>] ? rcu_cleanup_after_idle+0x23/0x170
> [ 439.620391] [<ffffffff811ca824>] ? rcu_eqs_exit_common+0x64/0x270
> [ 439.620391] [<ffffffff811c90bd>] ? rcu_user_enter+0x10d/0x140
> [ 439.620391] [<ffffffff811cae05>] ? rcu_user_exit+0xc5/0xf0
> [ 439.620391] [<ffffffff8106df1f>] do_notify_resume+0x4f/0xa0
> [ 439.620391] [<ffffffff83a69bea>] int_signal+0x12/0x17
> [ 439.620391] Code: e8 eb 48 2c 00 0f 0b 90 41 b8 f4 ff ff ff 66 2e 0f 1f 84 00 00 00 00 00 8b 35 5a 0a 06 02 85 f6 74 66 4d 85
> ed 75 04 31 c0 eb 2a <41> 8b b5 c8 00 00 00 44 89 85 b8 fe ff ff 49 8b 7e 20 e8 f6 51
> [ 439.630251] RIP [<ffffffff83746fc3>] sctp_do_sm+0x293/0x310
> [ 439.630251] RSP <ffff880010c57988>
> [ 439.630251] CR2: ffff88001b9f40c8
> [ 439.630251] ---[ end trace aa5ad9f036ee09dd ]---
>
> This points to the DEBUG_POST_SFX macro in sctp_do_sm().
>
>
> Thanks,
> Sasha
You don't have any of the logs right before this oops available do you? It
might be helpful in determining what went wrong here
Thanks
Neil
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: Re: Re: Re: Re: Re: A reliable kernel panic (3.6.2) and system crash when visiting a particular website
From: Alan Stern @ 2012-10-22 15:17 UTC (permalink / raw)
To: Artem S. Tashkinov
Cc: bp, pavel, linux-kernel, netdev, security, linux-media, linux-usb,
zonque, alsa-devel
In-Reply-To: <1906833625.122006.1350848941352.JavaMail.mail@webmail16>
On Sun, 21 Oct 2012, Artem S. Tashkinov wrote:
> dmesg messages up to a crash can be seen here: https://bugzilla.kernel.org/attachment.cgi?id=84221
The first problem in the log is endpoint list corruption. Here's a
debugging patch which should provide a little more information.
Alan Stern
drivers/usb/core/hcd.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
Index: usb-3.6/drivers/usb/core/hcd.c
===================================================================
--- usb-3.6.orig/drivers/usb/core/hcd.c
+++ usb-3.6/drivers/usb/core/hcd.c
@@ -1083,6 +1083,8 @@ EXPORT_SYMBOL_GPL(usb_calc_bus_time);
/*-------------------------------------------------------------------------*/
+static bool list_error;
+
/**
* usb_hcd_link_urb_to_ep - add an URB to its endpoint queue
* @hcd: host controller to which @urb was submitted
@@ -1126,6 +1128,20 @@ int usb_hcd_link_urb_to_ep(struct usb_hc
*/
if (HCD_RH_RUNNING(hcd)) {
urb->unlinked = 0;
+
+ {
+ struct list_head *cur = &urb->ep->urb_list;
+ struct list_head *prev = cur->prev;
+
+ if (prev->next != cur && !list_error) {
+ list_error = true;
+ dev_err(&urb->dev->dev,
+ "ep %x list add corruption: %p %p %p\n",
+ urb->ep->desc.bEndpointAddress,
+ cur, prev, prev->next);
+ }
+ }
+
list_add_tail(&urb->urb_list, &urb->ep->urb_list);
} else {
rc = -ESHUTDOWN;
@@ -1193,6 +1209,26 @@ void usb_hcd_unlink_urb_from_ep(struct u
{
/* clear all state linking urb to this dev (and hcd) */
spin_lock(&hcd_urb_list_lock);
+ {
+ struct list_head *cur = &urb->urb_list;
+ struct list_head *prev = cur->prev;
+ struct list_head *next = cur->next;
+
+ if (prev->next != cur && !list_error) {
+ list_error = true;
+ dev_err(&urb->dev->dev,
+ "ep %x list del corruption prev: %p %p %p\n",
+ urb->ep->desc.bEndpointAddress,
+ cur, prev, prev->next);
+ }
+ if (next->prev != cur && !list_error) {
+ list_error = true;
+ dev_err(&urb->dev->dev,
+ "ep %x list del corruption next: %p %p %p\n",
+ urb->ep->desc.bEndpointAddress,
+ cur, next, next->prev);
+ }
+ }
list_del_init(&urb->urb_list);
spin_unlock(&hcd_urb_list_lock);
}
^ permalink raw reply
* Re: PROBLEM: Memory leak (at least with SLUB) from "secpath_dup" (xfrm) in 3.5+ kernels
From: Eric Dumazet @ 2012-10-22 15:16 UTC (permalink / raw)
To: Mike Kazantsev; +Cc: Paul Moore, netdev, linux-mm
In-Reply-To: <20121022180655.50a50401@sacrilege>
On Mon, 2012-10-22 at 18:06 +0600, Mike Kazantsev wrote:
> On Mon, 22 Oct 2012 10:15:43 +0200
> Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
> > On Mon, 2012-10-22 at 04:58 +0600, Mike Kazantsev wrote:
> >
> > > I've grepped for "/org/free" specifically and sure enough, same scraps
> > > of data seem to be in some of the (varied) dumps there.
> >
> > Content is not meaningful, as we dont initialize it.
> > So you see previous content.
> >
> > Could you try the following :
> >
> ...
>
> With this patch on top of v3.7-rc2 (w/o patches from your previous
> mail), leak seem to be still present.
OK, I believe I found the bug in IPv4 defrag / IPv6 reasm
Please test the following patch.
Thanks !
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 448e685..0a52771 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -48,6 +48,7 @@
#include <linux/inet.h>
#include <linux/netfilter_ipv4.h>
#include <net/inet_ecn.h>
+#include <net/xfrm.h>
/* NOTE. Logic of IP defragmentation is parallel to corresponding IPv6
* code now. If you change something here, _PLEASE_ update ipv6/reassembly.c
@@ -634,6 +635,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
else if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_add(head->csum, fp->csum);
+ secpath_reset(fp);
if (skb_try_coalesce(head, fp, &headstolen, &delta)) {
kfree_skb_partial(fp, headstolen);
} else {
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index da8a4e3..4fcc463 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -55,6 +55,7 @@
#include <net/ndisc.h>
#include <net/addrconf.h>
#include <net/inet_frag.h>
+#include <net/xfrm.h>
struct ip6frag_skb_cb
{
@@ -456,6 +457,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
else if (head->ip_summed == CHECKSUM_COMPLETE)
head->csum = csum_add(head->csum, fp->csum);
+ secpath_reset(fp);
if (skb_try_coalesce(head, fp, &headstolen, &delta)) {
kfree_skb_partial(fp, headstolen);
} else {
^ permalink raw reply related
* [PATCH 3/3] pch_gbe: don't reset MAC_RX on FIFO overflow
From: Veaceslav Falico @ 2012-10-22 14:43 UTC (permalink / raw)
To: netdev; +Cc: davem, richardcochran, tshimizu818, andy.cress, erwan.velu,
agospoda
In-Reply-To: <1350917005-26350-1-git-send-email-vfalico@redhat.com>
Currently, when FIFO_ERR happens, we stop the dma, wait for it to become
idle and then reset the whole MAC_RX logic (and after that we must re-set
multicast addresses and also re-enable MAC_RX when we're finally ready to
accept new packets). This leads to CRC errors on high number of incoming
packets and is not needed according to the datasheet.
This patch fixes it by the following steps:
1) remove this reset in pch_gbe_stop_receive(), which causes some functions
to not be used anywhere
2) remove already unused functions pch_gbe_wait_clr_bit_irq() and
pch_gbe_mac_reset_rx() to correctly build
3) move pch_gbe_enable_mac_rx() out of pch_gbe_start_receive() to
pch_gbe_up() where it's only needed after we've removed the MAC_RX reset
4) rename pch_gbe_start/stop_receive() to pch_gbe_enable/disable_dma_rx()
to more precisely reflect what the functions are now doing.
After these changes we already don't see the CRC errors and gain some
increase in RX processing speed.
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
.../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 66 ++------------------
1 files changed, 6 insertions(+), 60 deletions(-)
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 4ffad78..a8854d0 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -339,26 +339,6 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit)
}
/**
- * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context
- * @reg: Pointer of register
- * @busy: Busy bit
- */
-static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit)
-{
- u32 tmp;
- int ret = -1;
- /* wait busy */
- tmp = 20;
- while ((ioread32(reg) & bit) && --tmp)
- udelay(5);
- if (!tmp)
- pr_err("Error: busy bit is not cleared\n");
- else
- ret = 0;
- return ret;
-}
-
-/**
* pch_gbe_mac_mar_set - Set MAC address register
* @hw: Pointer to the HW structure
* @addr: Pointer to the MAC address
@@ -409,17 +389,6 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)
return;
}
-static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw)
-{
- /* Read the MAC addresses. and store to the private data */
- pch_gbe_mac_read_mac_addr(hw);
- iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET);
- pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST);
- /* Setup the MAC addresses */
- pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
- return;
-}
-
static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw)
{
u32 rctl;
@@ -1330,38 +1299,17 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
-static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter)
+static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw)
{
- struct pch_gbe_hw *hw = &adapter->hw;
u32 rxdma;
- u16 value;
- int ret;
/* Disable Receive DMA */
rxdma = ioread32(&hw->reg->DMA_CTRL);
rxdma &= ~PCH_GBE_RX_DMA_EN;
iowrite32(rxdma, &hw->reg->DMA_CTRL);
- /* Wait Rx DMA BUS is IDLE */
- ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK);
- if (ret) {
- /* Disable Bus master */
- pci_read_config_word(adapter->pdev, PCI_COMMAND, &value);
- value &= ~PCI_COMMAND_MASTER;
- pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
- /* Stop Receive */
- pch_gbe_mac_reset_rx(hw);
- /* Enable Bus master */
- value |= PCI_COMMAND_MASTER;
- pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
- } else {
- /* Stop Receive */
- pch_gbe_mac_reset_rx(hw);
- }
- /* reprogram multicast address register after reset */
- pch_gbe_set_multi(adapter->netdev);
}
-static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
+static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw)
{
u32 rxdma;
@@ -1369,9 +1317,6 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
rxdma = ioread32(&hw->reg->DMA_CTRL);
rxdma |= PCH_GBE_RX_DMA_EN;
iowrite32(rxdma, &hw->reg->DMA_CTRL);
-
- pch_gbe_enable_mac_rx(hw);
- return;
}
/**
@@ -1407,7 +1352,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data)
int_en = ioread32(&hw->reg->INT_EN);
iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR),
&hw->reg->INT_EN);
- pch_gbe_stop_receive(adapter);
+ pch_gbe_disable_dma_rx(&adapter->hw);
int_st |= ioread32(&hw->reg->INT_ST);
int_st = int_st & ioread32(&hw->reg->INT_EN);
}
@@ -2014,7 +1959,8 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
pch_gbe_alloc_tx_buffers(adapter, tx_ring);
pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count);
adapter->tx_queue_len = netdev->tx_queue_len;
- pch_gbe_start_receive(&adapter->hw);
+ pch_gbe_enable_dma_rx(&adapter->hw);
+ pch_gbe_enable_mac_rx(&adapter->hw);
mod_timer(&adapter->watchdog_timer, jiffies);
@@ -2440,7 +2386,7 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
if (adapter->rx_stop_flag) {
adapter->rx_stop_flag = false;
- pch_gbe_start_receive(&adapter->hw);
+ pch_gbe_enable_dma_rx(&adapter->hw);
}
pr_debug("poll_end_flag : %d work_done : %d budget : %d\n",
--
1.7.1
^ permalink raw reply related
* [PATCH 2/3] pch_gbe: don't re-set RX_FIFO_ERR flag in napi_poll
From: Veaceslav Falico @ 2012-10-22 14:43 UTC (permalink / raw)
To: netdev; +Cc: davem, richardcochran, tshimizu818, andy.cress, erwan.velu,
agospoda
In-Reply-To: <1350917005-26350-1-git-send-email-vfalico@redhat.com>
If we were in RX_FIFO_ERR state and entered pch_gbe_napi_poll(), we'll
anyway clean some rx space and thus can continue to receive more packets.
Currently, we re-set the RX_FIFO_ERR in situations when we've exhausted our
budget for RX cleaning or cleaned some TX packets. Removing it gives us
+20%-40% speed increase and a lot less of RX_FIFO_ERRors reported.
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
.../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 19 ++++++-------------
1 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index d5190bf..4ffad78 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -2419,7 +2419,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
int work_done = 0;
bool poll_end_flag = false;
bool cleaned = false;
- u32 int_en;
pr_debug("budget : %d\n", budget);
@@ -2436,19 +2435,13 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
if (poll_end_flag) {
napi_complete(napi);
- if (adapter->rx_stop_flag) {
- adapter->rx_stop_flag = false;
- pch_gbe_start_receive(&adapter->hw);
- }
pch_gbe_irq_enable(adapter);
- } else
- if (adapter->rx_stop_flag) {
- adapter->rx_stop_flag = false;
- pch_gbe_start_receive(&adapter->hw);
- int_en = ioread32(&adapter->hw.reg->INT_EN);
- iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR),
- &adapter->hw.reg->INT_EN);
- }
+ }
+
+ if (adapter->rx_stop_flag) {
+ adapter->rx_stop_flag = false;
+ pch_gbe_start_receive(&adapter->hw);
+ }
pr_debug("poll_end_flag : %d work_done : %d budget : %d\n",
poll_end_flag, work_done, budget);
--
1.7.1
^ permalink raw reply related
* [PATCH 1/3] pch_gbe: create functions for MAC_RX {en,dis}able
From: Veaceslav Falico @ 2012-10-22 14:43 UTC (permalink / raw)
To: netdev; +Cc: davem, richardcochran, tshimizu818, andy.cress, erwan.velu,
agospoda
In-Reply-To: <1350917005-26350-1-git-send-email-vfalico@redhat.com>
Move MAC_RX-related bits into separate functions.
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
---
.../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 26 +++++++++++++++----
1 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index b2a94d0..d5190bf 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -420,6 +420,22 @@ static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw)
return;
}
+static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw)
+{
+ u32 rctl;
+ /* Disables Receive MAC */
+ rctl = ioread32(&hw->reg->MAC_RX_EN);
+ iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+}
+
+static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw)
+{
+ u32 rctl;
+ /* Enables Receive MAC */
+ rctl = ioread32(&hw->reg->MAC_RX_EN);
+ iowrite32((rctl | PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+}
+
/**
* pch_gbe_mac_init_rx_addrs - Initialize receive address's
* @hw: Pointer to the HW structure
@@ -913,7 +929,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)
static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
{
struct pch_gbe_hw *hw = &adapter->hw;
- u32 rdba, rdlen, rctl, rxdma;
+ u32 rdba, rdlen, rxdma;
pr_debug("dma adr = 0x%08llx size = 0x%08x\n",
(unsigned long long)adapter->rx_ring->dma,
@@ -921,9 +937,7 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
pch_gbe_mac_force_mac_fc(hw);
- /* Disables Receive MAC */
- rctl = ioread32(&hw->reg->MAC_RX_EN);
- iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+ pch_gbe_disable_mac_rx(hw);
/* Disables Receive DMA */
rxdma = ioread32(&hw->reg->DMA_CTRL);
@@ -1355,8 +1369,8 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
rxdma = ioread32(&hw->reg->DMA_CTRL);
rxdma |= PCH_GBE_RX_DMA_EN;
iowrite32(rxdma, &hw->reg->DMA_CTRL);
- /* Enables Receive */
- iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
+
+ pch_gbe_enable_mac_rx(hw);
return;
}
--
1.7.1
^ permalink raw reply related
* [PATCH 0/3] pch_gbe: fix CRC errors and improve speed
From: Veaceslav Falico @ 2012-10-22 14:43 UTC (permalink / raw)
To: netdev; +Cc: davem, richardcochran, tshimizu818, andy.cress, erwan.velu,
agospoda
This patch series tries to get rid of CRC errors and other instability
caused by wrong RX_FIFO overrun processing. It also cleans the code a bit.
Now (without the patch applied) on high number of incoming packets and/or
stressed system pch_gbe driver reports CRC errors and huge numbers of
RX_FIFO_ERR (overruns). It also sometimes just freezes (caused by not
waiting enough on DMA_RX to stop before issuing a reset on MAC_RX logic).
This patchset removes the unneeded (as per datasheet) MAC_RX reset and
corrects the processing of RX_FIFO_ERR in pch_gbe_napi_poll().
With the patchset applied there are no more CRC errors, sane number of
RX_FIFO_ERR and improved speed/stability. The patchset was tested on
Informix SYS940X and Kontron Tunnel Creek EG20T on 1gbps direct-connected
link and different rx/tx descriptors count.
.../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 99 +++++--------------
1 files changed, 26 insertions(+), 73 deletions(-)
^ permalink raw reply
* Re: [RFC PATCH v2 6/6] USB: forbid memory allocation with I/O during bus reset
From: Alan Stern @ 2012-10-22 14:37 UTC (permalink / raw)
To: Ming Lei
Cc: linux-kernel, Oliver Neukum, Minchan Kim, Greg Kroah-Hartman,
Rafael J. Wysocki, Jens Axboe, David S. Miller, Andrew Morton,
netdev, linux-usb, linux-pm, linux-mm
In-Reply-To: <1350894794-1494-7-git-send-email-ming.lei@canonical.com>
On Mon, 22 Oct 2012, Ming Lei wrote:
> If one storage interface or usb network interface(iSCSI case)
> exists in current configuration, memory allocation with
> GFP_KERNEL during usb_device_reset() might trigger I/O transfer
> on the storage interface itself and cause deadlock because
> the 'us->dev_mutex' is held in .pre_reset() and the storage
> interface can't do I/O transfer when the reset is triggered
> by other interface, or the error handling can't be completed
> if the reset is triggered by the storage itself(error handling path).
>
> Cc: Alan Stern <stern@rowland.harvard.edu>
> Cc: Oliver Neukum <oneukum@suse.de>
> Signed-off-by: Ming Lei <ming.lei@canonical.com>
> ---
> drivers/usb/core/hub.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 522ad57..106a80a 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -5038,6 +5038,7 @@ int usb_reset_device(struct usb_device *udev)
> {
> int ret;
> int i;
> + unsigned int noio_flag;
> struct usb_host_config *config = udev->actconfig;
>
> if (udev->state == USB_STATE_NOTATTACHED ||
> @@ -5047,6 +5048,15 @@ int usb_reset_device(struct usb_device *udev)
> return -EINVAL;
> }
>
> + /*
> + * Don't allocate memory with GFP_KERNEL in current
> + * context to avoid possible deadlock if usb mass
> + * storage interface or usbnet interface(iSCSI case)
> + * is included in current configuration. The easiest
> + * approach is to do it for all devices.
> + */
> + memalloc_noio_save(noio_flag);
Why not check dev->power.memalloc_noio_resume here too?
Alan Stern
^ permalink raw reply
* Re: [RFC PATCH v2 2/6] PM / Runtime: introduce pm_runtime_set_memalloc_noio()
From: Alan Stern @ 2012-10-22 14:33 UTC (permalink / raw)
To: Ming Lei
Cc: linux-kernel, Oliver Neukum, Minchan Kim, Greg Kroah-Hartman,
Rafael J. Wysocki, Jens Axboe, David S. Miller, Andrew Morton,
netdev, linux-usb, linux-pm, linux-mm
In-Reply-To: <1350894794-1494-3-git-send-email-ming.lei@canonical.com>
On Mon, 22 Oct 2012, Ming Lei wrote:
> +void pm_runtime_set_memalloc_noio(struct device *dev, bool enable)
> +{
> + dev->power.memalloc_noio_resume = enable;
> +
> + if (!dev->parent)
> + return;
> +
> + if (enable) {
> + pm_runtime_set_memalloc_noio(dev->parent, 1);
> + } else {
> + /* only clear the flag for one device if all
> + * children of the device don't set the flag.
> + */
> + if (device_for_each_child(dev->parent, NULL,
> + dev_memalloc_noio))
> + return;
> +
> + pm_runtime_set_memalloc_noio(dev->parent, 0);
> + }
> +}
> +EXPORT_SYMBOL_GPL(pm_runtime_set_memalloc_noio);
Tail recursion should be implemented as a loop, not as an explicit
recursion. That is, the function should be:
void pm_runtime_set_memalloc_noio(struct device *dev, bool enable)
{
do {
dev->power.memalloc_noio_resume = enable;
if (!enable) {
/*
* Don't clear the parent's flag if any of the
* parent's children have their flag set.
*/
if (device_for_each_child(dev->parent, NULL,
dev_memalloc_noio))
return;
}
dev = dev->parent;
} while (dev);
}
except that you need to add locking, for two reasons:
There's a race. What happens if another child sets the flag
between the time device_for_each_child() runs and the next loop
iteration?
Even without a race, access to bitfields is not SMP-safe
without locking.
Alan Stern
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [PATCH net-next v8 1/1] ipv6: add support of equal cost multipath (ECMP)
From: nicolas.dichtel @ 2012-10-22 13:42 UTC (permalink / raw)
To: davem; +Cc: joe, bernat, netdev, yoshfuji, eric.dumazet, Nicolas Dichtel
In-Reply-To: <1350913329-4044-1-git-send-email-nicolas.dichtel@6wind.com>
From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Each nexthop is added like a single route in the routing table. All routes
that have the same metric/weight and destination but not the same gateway
are considering as ECMP routes. They are linked together, through a list called
rt6i_siblings.
ECMP routes can be added in one shot, with RTA_MULTIPATH attribute or one after
the other (in both case, the flag NLM_F_EXCL should not be set).
The patch is based on a previous work from
Luc Saillard <luc.saillard@6wind.com>.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/ip6_fib.h | 10 ++++
net/ipv6/ip6_fib.c | 57 +++++++++++++++++++++
net/ipv6/route.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 200 insertions(+), 3 deletions(-)
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 8a2a203..20210d7 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -47,6 +47,8 @@ struct fib6_config {
unsigned long fc_expires;
struct nlattr *fc_mx;
int fc_mx_len;
+ int fc_mp_len;
+ struct nlattr *fc_mp;
struct nl_info fc_nlinfo;
};
@@ -99,6 +101,14 @@ struct rt6_info {
struct in6_addr rt6i_gateway;
+ /* Multipath routes:
+ * siblings is a list of rt6_info that have the the same metric/weight,
+ * destination, but not the same gateway. nsiblings is just a cache
+ * to speed up lookup.
+ */
+ struct list_head rt6i_siblings;
+ unsigned int rt6i_nsiblings;
+
atomic_t rt6i_ref;
/* These are in a separate cache line. */
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 24995a9..710cafd 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -672,6 +672,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
iter->rt6i_idev == rt->rt6i_idev &&
ipv6_addr_equal(&iter->rt6i_gateway,
&rt->rt6i_gateway)) {
+ if (rt->rt6i_nsiblings)
+ rt->rt6i_nsiblings = 0;
if (!(iter->rt6i_flags & RTF_EXPIRES))
return -EEXIST;
if (!(rt->rt6i_flags & RTF_EXPIRES))
@@ -680,6 +682,21 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
rt6_set_expires(iter, rt->dst.expires);
return -EEXIST;
}
+ /* If we have the same destination and the same metric,
+ * but not the same gateway, then the route we try to
+ * add is sibling to this route, increment our counter
+ * of siblings, and later we will add our route to the
+ * list.
+ * Only static routes (which don't have flag
+ * RTF_EXPIRES) are used for ECMPv6.
+ *
+ * To avoid long list, we only had siblings if the
+ * route have a gateway.
+ */
+ if (rt->rt6i_flags & RTF_GATEWAY &&
+ !(rt->rt6i_flags & RTF_EXPIRES) &&
+ !(iter->rt6i_flags & RTF_EXPIRES))
+ rt->rt6i_nsiblings++;
}
if (iter->rt6i_metric > rt->rt6i_metric)
@@ -692,6 +709,35 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
if (ins == &fn->leaf)
fn->rr_ptr = NULL;
+ /* Link this route to others same route. */
+ if (rt->rt6i_nsiblings) {
+ unsigned int rt6i_nsiblings;
+ struct rt6_info *sibling, *temp_sibling;
+
+ /* Find the first route that have the same metric */
+ sibling = fn->leaf;
+ while (sibling) {
+ if (sibling->rt6i_metric == rt->rt6i_metric) {
+ list_add_tail(&rt->rt6i_siblings,
+ &sibling->rt6i_siblings);
+ break;
+ }
+ sibling = sibling->dst.rt6_next;
+ }
+ /* For each sibling in the list, increment the counter of
+ * siblings. BUG() if counters does not match, list of siblings
+ * is broken!
+ */
+ rt6i_nsiblings = 0;
+ list_for_each_entry_safe(sibling, temp_sibling,
+ &rt->rt6i_siblings, rt6i_siblings) {
+ sibling->rt6i_nsiblings++;
+ BUG_ON(sibling->rt6i_nsiblings != rt->rt6i_nsiblings);
+ rt6i_nsiblings++;
+ }
+ BUG_ON(rt6i_nsiblings != rt->rt6i_nsiblings);
+ }
+
/*
* insert node
*/
@@ -1193,6 +1239,17 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
if (fn->rr_ptr == rt)
fn->rr_ptr = NULL;
+ /* Remove this entry from other siblings */
+ if (rt->rt6i_nsiblings) {
+ struct rt6_info *sibling, *next_sibling;
+
+ list_for_each_entry_safe(sibling, next_sibling,
+ &rt->rt6i_siblings, rt6i_siblings)
+ sibling->rt6i_nsiblings--;
+ rt->rt6i_nsiblings = 0;
+ list_del_init(&rt->rt6i_siblings);
+ }
+
/* Adjust walkers */
read_lock(&fib6_walker_lock);
FOR_WALKERS(w) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 7c7e963..126da56 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -57,6 +57,7 @@
#include <net/xfrm.h>
#include <net/netevent.h>
#include <net/netlink.h>
+#include <net/nexthop.h>
#include <asm/uaccess.h>
@@ -289,6 +290,8 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
rt->rt6i_genid = rt_genid(net);
+ INIT_LIST_HEAD(&rt->rt6i_siblings);
+ rt->rt6i_nsiblings = 0;
}
return rt;
}
@@ -385,6 +388,69 @@ static bool rt6_need_strict(const struct in6_addr *daddr)
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
}
+/* Multipath route selection:
+ * Hash based function using packet header and flowlabel.
+ * Adapted from fib_info_hashfn()
+ */
+static int rt6_info_hash_nhsfn(unsigned int candidate_count,
+ const struct flowi6 *fl6)
+{
+ unsigned int val = fl6->flowi6_proto;
+
+ val ^= fl6->daddr.s6_addr32[0];
+ val ^= fl6->daddr.s6_addr32[1];
+ val ^= fl6->daddr.s6_addr32[2];
+ val ^= fl6->daddr.s6_addr32[3];
+
+ val ^= fl6->saddr.s6_addr32[0];
+ val ^= fl6->saddr.s6_addr32[1];
+ val ^= fl6->saddr.s6_addr32[2];
+ val ^= fl6->saddr.s6_addr32[3];
+
+ /* Work only if this not encapsulated */
+ switch (fl6->flowi6_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ val ^= fl6->fl6_sport;
+ val ^= fl6->fl6_dport;
+ break;
+
+ case IPPROTO_ICMPV6:
+ val ^= fl6->fl6_icmp_type;
+ val ^= fl6->fl6_icmp_code;
+ break;
+ }
+ /* RFC6438 recommands to use flowlabel */
+ val ^= fl6->flowlabel;
+
+ /* Perhaps, we need to tune, this function? */
+ val = val ^ (val >> 7) ^ (val >> 12);
+ return val % candidate_count;
+}
+
+static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
+ struct flowi6 *fl6)
+{
+ struct rt6_info *sibling, *next_sibling;
+ int route_choosen;
+
+ route_choosen = rt6_info_hash_nhsfn(match->rt6i_nsiblings + 1, fl6);
+ /* Don't change the route, if route_choosen == 0
+ * (siblings does not include ourself)
+ */
+ if (route_choosen)
+ list_for_each_entry_safe(sibling, next_sibling,
+ &match->rt6i_siblings, rt6i_siblings) {
+ route_choosen--;
+ if (route_choosen == 0) {
+ match = sibling;
+ break;
+ }
+ }
+ return match;
+}
+
/*
* Route lookup. Any table->tb6_lock is implied.
*/
@@ -702,6 +768,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
restart:
rt = fn->leaf;
rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
+ if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
+ rt = rt6_multipath_select(rt, fl6);
BACKTRACK(net, &fl6->saddr);
out:
dst_use(&rt->dst, jiffies);
@@ -863,7 +931,8 @@ restart_2:
restart:
rt = rt6_select(fn, oif, strict | reachable);
-
+ if (rt->rt6i_nsiblings && oif == 0)
+ rt = rt6_multipath_select(rt, fl6);
BACKTRACK(net, &fl6->saddr);
if (rt == net->ipv6.ip6_null_entry ||
rt->rt6i_flags & RTF_CACHE)
@@ -2249,6 +2318,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_IIF] = { .type = NLA_U32 },
[RTA_PRIORITY] = { .type = NLA_U32 },
[RTA_METRICS] = { .type = NLA_NESTED },
+ [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
};
static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -2326,11 +2396,65 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
if (tb[RTA_TABLE])
cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
+ if (tb[RTA_MULTIPATH]) {
+ cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
+ cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
+ }
+
err = 0;
errout:
return err;
}
+static int ip6_route_multipath(struct fib6_config *cfg, int add)
+{
+ struct fib6_config r_cfg;
+ struct rtnexthop *rtnh;
+ int remaining;
+ int attrlen;
+ int err = 0, last_err = 0;
+
+beginning:
+ rtnh = (struct rtnexthop *)cfg->fc_mp;
+ remaining = cfg->fc_mp_len;
+
+ /* Parse a Multipath Entry */
+ while (rtnh_ok(rtnh, remaining)) {
+ memcpy(&r_cfg, cfg, sizeof(*cfg));
+ if (rtnh->rtnh_ifindex)
+ r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
+
+ attrlen = rtnh_attrlen(rtnh);
+ if (attrlen > 0) {
+ struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
+
+ nla = nla_find(attrs, attrlen, RTA_GATEWAY);
+ if (nla) {
+ nla_memcpy(&r_cfg.fc_gateway, nla, 16);
+ r_cfg.fc_flags |= RTF_GATEWAY;
+ }
+ }
+ err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg);
+ if (err) {
+ last_err = err;
+ /* If we are trying to remove a route, do not stop the
+ * loop when ip6_route_del() fails (because next hop is
+ * already gone), we should try to remove all next hops.
+ */
+ if (add) {
+ /* If add fails, we should try to delete all
+ * next hops that have been already added.
+ */
+ add = 0;
+ goto beginning;
+ }
+ }
+ rtnh = rtnh_next(rtnh, &remaining);
+ }
+
+ return last_err;
+}
+
static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
struct fib6_config cfg;
@@ -2340,7 +2464,10 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
if (err < 0)
return err;
- return ip6_route_del(&cfg);
+ if (cfg.fc_mp)
+ return ip6_route_multipath(&cfg, 0);
+ else
+ return ip6_route_del(&cfg);
}
static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -2352,7 +2479,10 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
if (err < 0)
return err;
- return ip6_route_add(&cfg);
+ if (cfg.fc_mp)
+ return ip6_route_multipath(&cfg, 1);
+ else
+ return ip6_route_add(&cfg);
}
static inline size_t rt6_nlmsg_size(void)
--
1.7.12
^ 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