* [PATCH 1/6] Staging: Octeon: Fix compile error in drivers/staging/octeon/ethernet-mdio.c
From: Ralf Baechle @ 2009-11-05 15:25 UTC (permalink / raw)
To: Linus Torvalds
Cc: David Daney, Greg Kroah-Hartman, devel, linux-kernel, linux-mips,
netdev
In-Reply-To: <20091105152555.227009519@linux-mips.org>
[-- Attachment #1: 0002.patch --]
[-- Type: text/plain, Size: 960 bytes --]
From: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: devel@driverdev.osuosl.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
drivers/staging/octeon/ethernet-mdio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: upstream-linus/drivers/staging/octeon/ethernet-mdio.c
===================================================================
--- upstream-linus.orig/drivers/staging/octeon/ethernet-mdio.c
+++ upstream-linus/drivers/staging/octeon/ethernet-mdio.c
@@ -170,7 +170,7 @@ static u32 cvm_oct_get_link(struct net_d
return ret;
}
-struct const ethtool_ops cvm_oct_ethtool_ops = {
+const struct ethtool_ops cvm_oct_ethtool_ops = {
.get_drvinfo = cvm_oct_get_drvinfo,
.get_settings = cvm_oct_get_settings,
.set_settings = cvm_oct_set_settings,
^ permalink raw reply
* [PATCH 2/6] Staging: Octeon: Use symbolic values for irq numbers.
From: Ralf Baechle @ 2009-11-05 15:25 UTC (permalink / raw)
To: Linus Torvalds
Cc: David Daney, Greg Kroah-Hartman, devel, linux-kernel, linux-mips,
netdev
In-Reply-To: <20091105152555.227009519@linux-mips.org>
[-- Attachment #1: 0003.patch --]
[-- Type: text/plain, Size: 1062 bytes --]
From: David Daney <ddaney@caviumnetworks.com>
In addition to being magic numbers, the irq number passed to free_irq
is incorrect. We need to use the correct symbolic value instead.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: devel@driverdev.osuosl.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
drivers/staging/octeon/ethernet-spi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: upstream-linus/drivers/staging/octeon/ethernet-spi.c
===================================================================
--- upstream-linus.orig/drivers/staging/octeon/ethernet-spi.c
+++ upstream-linus/drivers/staging/octeon/ethernet-spi.c
@@ -317,6 +317,6 @@ void cvm_oct_spi_uninit(struct net_devic
cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0);
cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0);
}
- free_irq(8 + 46, &number_spi_ports);
+ free_irq(OCTEON_IRQ_RML, &number_spi_ports);
}
}
^ permalink raw reply
* [PATCH 3/6] Staging: octeon-ethernet: Assign proper MAC addresses.
From: Ralf Baechle @ 2009-11-05 15:25 UTC (permalink / raw)
To: Linus Torvalds
Cc: David Daney, Greg Kroah-Hartman, devel, linux-kernel, linux-mips,
netdev
In-Reply-To: <20091105152555.227009519@linux-mips.org>
[-- Attachment #1: 0004.patch --]
[-- Type: text/plain, Size: 4018 bytes --]
From: David Daney <ddaney@caviumnetworks.com>
Allocate MAC addresses using the same method as the bootloader. This
avoids changing the MAC between bootloader and kernel operation as
well as avoiding duplicates and use of addresses outside of the
assigned range.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: devel@driverdev.osuosl.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
drivers/staging/octeon/ethernet.c | 53 +++++++++++++++++++++++++++++---------
1 file changed, 41 insertions(+), 12 deletions(-)
Index: upstream-linus/drivers/staging/octeon/ethernet.c
===================================================================
--- upstream-linus.orig/drivers/staging/octeon/ethernet.c
+++ upstream-linus/drivers/staging/octeon/ethernet.c
@@ -111,6 +111,16 @@ MODULE_PARM_DESC(disable_core_queueing,
"\tallows packets to be sent without lock contention in the packet\n"
"\tscheduler resulting in some cases in improved throughput.\n");
+
+/*
+ * The offset from mac_addr_base that should be used for the next port
+ * that is configured. By convention, if any mgmt ports exist on the
+ * chip, they get the first mac addresses, The ports controlled by
+ * this driver are numbered sequencially following any mgmt addresses
+ * that may exist.
+ */
+static unsigned int cvm_oct_mac_addr_offset;
+
/**
* Periodic timer to check auto negotiation
*/
@@ -474,16 +484,30 @@ static int cvm_oct_common_set_mac_addres
*/
int cvm_oct_common_init(struct net_device *dev)
{
- static int count;
- char mac[8] = { 0x00, 0x00,
- octeon_bootinfo->mac_addr_base[0],
- octeon_bootinfo->mac_addr_base[1],
- octeon_bootinfo->mac_addr_base[2],
- octeon_bootinfo->mac_addr_base[3],
- octeon_bootinfo->mac_addr_base[4],
- octeon_bootinfo->mac_addr_base[5] + count
- };
struct octeon_ethernet *priv = netdev_priv(dev);
+ struct sockaddr sa;
+ u64 mac = ((u64)(octeon_bootinfo->mac_addr_base[0] & 0xff) << 40) |
+ ((u64)(octeon_bootinfo->mac_addr_base[1] & 0xff) << 32) |
+ ((u64)(octeon_bootinfo->mac_addr_base[2] & 0xff) << 24) |
+ ((u64)(octeon_bootinfo->mac_addr_base[3] & 0xff) << 16) |
+ ((u64)(octeon_bootinfo->mac_addr_base[4] & 0xff) << 8) |
+ (u64)(octeon_bootinfo->mac_addr_base[5] & 0xff);
+
+ mac += cvm_oct_mac_addr_offset;
+ sa.sa_data[0] = (mac >> 40) & 0xff;
+ sa.sa_data[1] = (mac >> 32) & 0xff;
+ sa.sa_data[2] = (mac >> 24) & 0xff;
+ sa.sa_data[3] = (mac >> 16) & 0xff;
+ sa.sa_data[4] = (mac >> 8) & 0xff;
+ sa.sa_data[5] = mac & 0xff;
+
+ if (cvm_oct_mac_addr_offset >= octeon_bootinfo->mac_addr_count)
+ printk(KERN_DEBUG "%s: Using MAC outside of the assigned range:"
+ " %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
+ sa.sa_data[0] & 0xff, sa.sa_data[1] & 0xff,
+ sa.sa_data[2] & 0xff, sa.sa_data[3] & 0xff,
+ sa.sa_data[4] & 0xff, sa.sa_data[5] & 0xff);
+ cvm_oct_mac_addr_offset++;
/*
* Force the interface to use the POW send if always_use_pow
@@ -496,14 +520,12 @@ int cvm_oct_common_init(struct net_devic
if (priv->queue != -1 && USE_HW_TCPUDP_CHECKSUM)
dev->features |= NETIF_F_IP_CSUM;
- count++;
-
/* We do our own locking, Linux doesn't need to */
dev->features |= NETIF_F_LLTX;
SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops);
cvm_oct_mdio_setup_device(dev);
- dev->netdev_ops->ndo_set_mac_address(dev, mac);
+ dev->netdev_ops->ndo_set_mac_address(dev, &sa);
dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);
/*
@@ -620,6 +642,13 @@ static int __init cvm_oct_init_module(vo
pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
+ if (OCTEON_IS_MODEL(OCTEON_CN52XX))
+ cvm_oct_mac_addr_offset = 2; /* First two are the mgmt ports. */
+ else if (OCTEON_IS_MODEL(OCTEON_CN56XX))
+ cvm_oct_mac_addr_offset = 1; /* First one is the mgmt port. */
+ else
+ cvm_oct_mac_addr_offset = 0;
+
cvm_oct_proc_initialize();
cvm_oct_rx_initialize();
cvm_oct_configure_common_hw();
^ permalink raw reply
* Re: [PATCH RFC] gianfar: Make polling safe with IRQs disabled
From: Jon Loeliger @ 2009-11-05 15:43 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev, Jason Wessel, Andy Fleming, David Miller, netdev
In-Reply-To: <E1N63WM-0003xK-PN@jdl.com>
> >
> > If it's easily reproducible, could you replace the printk() with
> > WARN_ON(1) and post the backtrace? Or I can try to reproduce the
> > issue if you tell me how.
> >
> > Thanks!
>
> Yeah, I can reproduce it. I'll try and get that for you.
>
> jdl
This is with essentially a stock 2.6.31 kernel for an 8315.
I've seen the problem for both task 'insmod' and 'iptables'.
Um, conn_track is a module being loaded here. Our brief analysis
runs like this:
This is an issue with the gianfar driver. In gfar_poll(), irqs are
disabled for the handling of gfar_clean_tx_ring(dev) (line 1928).
In this call, skbs can call skb_recycle_check, which can release
head state (net/core/skbuff.c@506), which can cause conntrack
cleanup (net/core/skbuff.c@402->include/linux/skbuff.h@1923), which
cannot be done with IRQs disabled...that is the badness.
HTH,
jdl
[ 34.775619] nf_conntrack version 0.5.0 (1008 buckets, 4032 max)
[ 34.963135] ------------[ cut here ]------------
[ 34.967804] Badness at kernel/softirq.c:143
[ 34.972016] NIP: c003e3c4 LR: c423a528 CTR: c003e344
[ 34.977018] REGS: c15d1ab0 TRAP: 0700 Not tainted (2.6.31-xeno)
[ 34.983236] MSR: 00021032 <ME,CE,IR,DR> CR: 24000284 XER: 20000000
[ 34.989689] TASK = c343a060[977] 'insmod' THREAD: c15d0000
[ 34.995032] GPR00: 00000001 c15d1b60 c343a060 00000001 000000a4 00000052 00000001 00000000
[ 35.003501] GPR08: 00000101 c0450000 c3572d20 c003e344 24000282 100c5288 00000001 00000040
[ 35.011971] GPR16: c2e5c2f0 00009032 c2e5c2c0 c2e5c000 00000100 00000000 c2e5c340 00000098
[ 35.020440] GPR24: 00000260 c2428760 00000800 c153b800 00000000 c1018c98 c15d0000 c15d1b60
[ 35.029120] NIP [c003e3c4] local_bh_enable+0x80/0xc4
[ 35.034174] LR [c423a528] destroy_conntrack+0xd4/0x13c [nf_conntrack]
[ 35.040652] Call Trace:
[ 35.043128] [c15d1b60] [c003e32c] local_bh_disable+0x1c/0x34 (unreliable)
[ 35.050001] [c15d1b70] [c423a528] destroy_conntrack+0xd4/0x13c [nf_conntrack]
[ 35.057205] [c15d1b80] [c02c6370] nf_conntrack_destroy+0x3c/0x70
[ 35.063263] --- Exception: c428168c at 0xc15d1c50
[ 35.063272] LR = 0xc15d1c40
[ 35.071165] [c15d1ba0] [c0286f3c] skb_release_head_state+0x100/0x104 (unreliable)
[ 35.078718] [c15d1bb0] [c0288340] skb_recycle_check+0x8c/0x10c
[ 35.084611] [c15d1bc0] [c01e1688] gfar_poll+0x190/0x384
[ 35.089887] [c15d1c10] [c02935ac] net_rx_action+0xec/0x22c
[ 35.095432] [c15d1c50] [c003dd8c] __do_softirq+0xe8/0x224
[ 35.100885] [c15d1ca0] [c000624c] do_softirq+0x78/0x80
[ 35.106071] [c15d1cb0] [c003d868] irq_exit+0x60/0x78
[ 35.111082] [c15d1cc0] [c0006714] do_IRQ+0x98/0xb0
[ 35.115921] [c15d1ce0] [c0014af8] ret_from_except+0x0/0x14
[ 35.121474] --- Exception: 501 at strcmp+0xc/0x24
[ 35.121483] LR = find_symbol_in_section+0x38/0xc0
[ 35.131285] [c15d1da0] [00000000] (null) (unreliable)
[ 35.136390] [c15d1dc0] [c0064e08] each_symbol_in_section+0x7c/0xb4
[ 35.142623] [c15d1df0] [c0065340] each_symbol+0x34/0x148
[ 35.147983] [c15d1e70] [c0065488] find_symbol+0x34/0x78
[ 35.153257] [c15d1ea0] [c00681d8] load_module+0x8e4/0x12ec
[ 35.158792] [c15d1f20] [c0068c60] sys_init_module+0x80/0x208
[ 35.164501] [c15d1f40] [c0014460] ret_from_syscall+0x0/0x38
[ 35.170124] --- Exception: c01 at 0xfea6a8c
[ 35.170132] LR = 0x10016dcc
[ 35.177485] Instruction dump:
[ 35.180477] 70090004 40820068 81610000 800b0004 bbcbfff8 7d615b78 7c0803a6 4e800020
[ 35.188332] 3d20c045 8009b3c0 7c000034 5400d97e <0f000000> 2f800000 419effa8 38000001
^ permalink raw reply
* Re: [PATCH 16/25] mlx4_core: boot sriov
From: Roland Dreier @ 2009-11-05 15:57 UTC (permalink / raw)
To: Liran Liss
Cc: Yevgeny Petrilin, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Tziporet Koren
In-Reply-To: <2ED289D4E09FBD4D92D911E869B97FDD0166CA13-ia22CT07NJfiMCgWhms8HQC/G2K4zDHf@public.gmane.org>
> LL: I think that this won't pass -Wall when compiling against a kernel
> with sriov compiled out.
Why not? The sriov code provides stubs like:
static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
{
return -ENODEV;
}
if CONFIG_PCI_IOV is not enabled.
- R.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 19/25] mlx4: Randomizing mac addresses for slaves
From: Roland Dreier @ 2009-11-05 15:58 UTC (permalink / raw)
To: Liran Liss
Cc: Or Gerlitz, Yevgeny Petrilin, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Tziporet Koren
In-Reply-To: <2ED289D4E09FBD4D92D911E869B97FDD0166CA59-ia22CT07NJfiMCgWhms8HQC/G2K4zDHf@public.gmane.org>
> This approach seems to be common practice now (e.g., drivers/net/igb/igb_main.c:1332).
> In any case, the user can change the randomized mac.
igb uses the full output of random_ether_addr(). I'd be fine with
that. However setting the OUI means you only get 24 bits of randomness
which makes a collision a lot more likely.
- R.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* RE: [PATCH 16/25] mlx4_core: boot sriov
From: Liran Liss @ 2009-11-05 16:21 UTC (permalink / raw)
To: Roland Dreier; +Cc: Yevgeny Petrilin, linux-rdma, netdev, Tziporet Koren
In-Reply-To: <adafx8tc6cu.fsf@roland-alpha.cisco.com>
I was also thinking about backports to older kernels without sriov at
all, which will probably be in our VMs in the near future.
For these kernels, we still want to the code to operate in slave mode...
Anyway, we can push the pci_enable_sriov() stub to the OFED backport
system as well, so I am fine.
10x,
--Liran
-----Original Message-----
From: Roland Dreier [mailto:rdreier@cisco.com]
Sent: Thursday, November 05, 2009 5:57 PM
To: Liran Liss
Cc: Yevgeny Petrilin; linux-rdma@vger.kernel.org;
netdev@vger.kernel.org; Tziporet Koren
Subject: Re: [PATCH 16/25] mlx4_core: boot sriov
> LL: I think that this won't pass -Wall when compiling against a
kernel > with sriov compiled out.
Why not? The sriov code provides stubs like:
static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) {
return -ENODEV;
}
if CONFIG_PCI_IOV is not enabled.
- R.
^ permalink raw reply
* Re: [RFC] [PATCH] udp: optimize lookup of UDP sockets to by including destination address in the hash key
From: Octavian Purdila @ 2009-11-05 16:25 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Lucian Adrian Grijincu, netdev
In-Reply-To: <4AF20F02.7000601@gmail.com>
On Thursday 05 November 2009 01:32:18 you wrote:
> >
> > Very true, the benchmark itself shows a significant overhead increase on
> > the TX side and indeed this case is not very common. But for us its an
> > important usecase.
> >
> > Maybe there is a more clever way of fixing this specific use-case without
> > hurting the common case?
>
> Clever way ? Well, we will see :)
>
> I now understand previous Lucian patch (best match) :)
>
> Could you please describe your usecase ? I guess something is possible,
> not necessarly hurting performance of regular usecases :)
>
IIRC, we first saw this issue in VoIP tests with up to 16000 sockets bound on a
certain port and IP addresses (each IP address is assigned to a particular
interface). We need this setup in order to emulate lots of VoIP users each
with a different IP address and possible a different L2 encapsulation.
Now, as a general note I should say that our usecases can seem absurd if you
take them out of the network testing field :) but my _personal_ opinion is that
a better integration between our code base and upstream code may benefit both
upstream and us:
- for us it gives the ability to stay close to upstream and get all of the new
shiny features without painful upgrades
- for upstream, even if most systems don't run into these scalability issues
now, I see that some people are moving in that direction (see the recent PPP
problems); also, stressing Linux in that regard can only make the code better
- as long as the approach taken is clean and sound
- we (or our customers) use a plethora of networking devices for testing so
exposing Linux early to those devices can only help catching issues earlier
In short: expect more absurd patches from us :)
> I have struct reorderings in progress to reduce number of cache lines read
> per socket from two to one. So this would reduce by 50% time to find
> a particular socket in the chain.
>
> But if you *really* want/need 512 sockets bound to _same_ port, we probably
> can use secondary hash tables (or rbtree), as soon as we stack more than
> XX sockets on a particular slot.
>
> At lookup, we check if extended hash table exists before doing
> normal rcu lookup.
>
> Probably can be done under 300 lines of code.
> On normal machines, these extra tables/trees would not be used/allocated
>
Yep, that should work. Will respin the patch based on this idea and see what
we get, but it will take a while.
Thanks,
tavi
^ permalink raw reply
* Re: [RFC] [PATCH] udp: optimize lookup of UDP sockets to by including destination address in the hash key
From: Eric Dumazet @ 2009-11-05 16:36 UTC (permalink / raw)
To: Octavian Purdila; +Cc: Lucian Adrian Grijincu, netdev
In-Reply-To: <200911051825.45749.opurdila@ixiacom.com>
Octavian Purdila a écrit :
> IIRC, we first saw this issue in VoIP tests with up to 16000 sockets bound on a
> certain port and IP addresses (each IP address is assigned to a particular
> interface). We need this setup in order to emulate lots of VoIP users each
> with a different IP address and possible a different L2 encapsulation.
Interesting case indeed, is it SIP 5060 port or RTP ports ?
(I want to know how many messages per second you want to receive)
An rbtree with 16000 elements has 15 levels, its a lot, but OK
for small trafic.
>
> Now, as a general note I should say that our usecases can seem absurd if you
> take them out of the network testing field :) but my _personal_ opinion is that
> a better integration between our code base and upstream code may benefit both
> upstream and us:
>
> - for us it gives the ability to stay close to upstream and get all of the new
> shiny features without painful upgrades
>
> - for upstream, even if most systems don't run into these scalability issues
> now, I see that some people are moving in that direction (see the recent PPP
> problems); also, stressing Linux in that regard can only make the code better
> - as long as the approach taken is clean and sound
>
> - we (or our customers) use a plethora of networking devices for testing so
> exposing Linux early to those devices can only help catching issues earlier
>
> In short: expect more absurd patches from us :)
I might cook something too :)
^ permalink raw reply
* [PATCH RFC] gianfar: Do not call skb recycling with disabled IRQs
From: Anton Vorontsov @ 2009-11-05 16:57 UTC (permalink / raw)
To: Jon Loeliger
Cc: linuxppc-dev, Jason Wessel, Andy Fleming, David Miller, netdev,
Lennert Buytenhek, Stephen Hemminger
In-Reply-To: <E1N64UY-00049g-Hb@jdl.com>
Before calling gfar_clean_tx_ring() we grab an irqsave spinlock, and
then try to recycle an skb, which requires IRQs to be enabled. This
leads to the following badness:
nf_conntrack version 0.5.0 (1008 buckets, 4032 max)
------------[ cut here ]------------
Badness at kernel/softirq.c:143
NIP: c003e3c4 LR: c423a528 CTR: c003e344
...
NIP [c003e3c4] local_bh_enable+0x80/0xc4
LR [c423a528] destroy_conntrack+0xd4/0x13c [nf_conntrack]
Call Trace:
[c15d1b60] [c003e32c] local_bh_disable+0x1c/0x34 (unreliable)
[c15d1b70] [c423a528] destroy_conntrack+0xd4/0x13c [nf_conntrack]
[c15d1b80] [c02c6370] nf_conntrack_destroy+0x3c/0x70
--- Exception: c428168c at 0xc15d1c50
LR = 0xc15d1c40
[c15d1ba0] [c0286f3c] skb_release_head_state+0x100/0x104 (unreliable)
[c15d1bb0] [c0288340] skb_recycle_check+0x8c/0x10c
[c15d1bc0] [c01e1688] gfar_poll+0x190/0x384
[c15d1c10] [c02935ac] net_rx_action+0xec/0x22c
[c15d1c50] [c003dd8c] __do_softirq+0xe8/0x224
[c15d1ca0] [c000624c] do_softirq+0x78/0x80
[c15d1cb0] [c003d868] irq_exit+0x60/0x78
...
We can't easily get rid of the irqsave spinlock, because we must
guard ourselves from start_xmit.
So, fix this by dropping the irqsave spinlock from both xmit_start
and clean_tx_ring routines. Instead, lock the whole tx queue via
netif_tx_lock_bh() in clean_tx_ring().
Reported-by: Jon Loeliger <jdl@jdl.com>
Not-yet-Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
On Thu, Nov 05, 2009 at 09:43:18AM -0600, Jon Loeliger wrote:
[...]
> This is with essentially a stock 2.6.31 kernel for an 8315.
> I've seen the problem for both task 'insmod' and 'iptables'.
> Um, conn_track is a module being loaded here. Our brief analysis
> runs like this:
>
> This is an issue with the gianfar driver. In gfar_poll(), irqs are
> disabled for the handling of gfar_clean_tx_ring(dev) (line 1928).
> In this call, skbs can call skb_recycle_check, which can release
> head state (net/core/skbuff.c@506), which can cause conntrack
> cleanup (net/core/skbuff.c@402->include/linux/skbuff.h@1923), which
> cannot be done with IRQs disabled...that is the badness.
Ugh.
We may try to call netif_tx_lock_bh() in gfar_clean_tx_ring() and
drop the irqsave spinlock start_xmit (sky2-like scheme).
But that basically means that with skb recycling we can't safely
use KGDBoE, though we can add something like this:
| diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
| index a00ec63..4d82bd7 100644
| --- a/drivers/net/gianfar.c
| +++ b/drivers/net/gianfar.c
| @@ -1619,7 +1619,8 @@ static int gfar_clean_tx_ring(struct net_device *dev)
| * If there's room in the queue (limit it to rx_buffer_size)
| * we add this skb back into the pool, if it's the right size
| */
| - if (skb_queue_len(&priv->rx_recycle) < priv->rx_ring_size &&
| + if (!irqs_disabled() &&
| + skb_queue_len(&priv->rx_recycle) < priv->rx_ring_size &&
| skb_recycle_check(skb, priv->rx_buffer_size +
| RXBUF_ALIGNMENT))
| __skb_queue_head(&priv->rx_recycle, skb);
So we won't recycle skbs with irqs disabled.
Anyway, apart from KGDBoE, the following patch might fix the conntrack
issue, can you try it?
With this patch the kernel boots via NFS, and survives netperf, though
I'd like to audit changes a little more and run some netperf tests, I
might also put the netif_tx_lock_bh() stuff out of the loop.
So this patch isn't for the merge.
drivers/net/gianfar.c | 19 +++----------------
1 files changed, 3 insertions(+), 16 deletions(-)
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 197b358..a0ae604 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1899,10 +1899,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 lstatus;
int i, rq = 0;
u32 bufaddr;
- unsigned long flags;
unsigned int nr_frags, length;
-
rq = skb->queue_mapping;
tx_queue = priv->tx_queue[rq];
txq = netdev_get_tx_queue(dev, rq);
@@ -1928,14 +1926,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* total number of fragments in the SKB */
nr_frags = skb_shinfo(skb)->nr_frags;
- spin_lock_irqsave(&tx_queue->txlock, flags);
-
/* check if there is space to queue this packet */
if ((nr_frags+1) > tx_queue->num_txbdfree) {
/* no space, stop the queue */
netif_tx_stop_queue(txq);
dev->stats.tx_fifo_errors++;
- spin_unlock_irqrestore(&tx_queue->txlock, flags);
return NETDEV_TX_BUSY;
}
@@ -2033,9 +2028,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Tell the DMA to go go go */
gfar_write(®s->tstat, TSTAT_CLEAR_THALT >> tx_queue->qindex);
- /* Unlock priv */
- spin_unlock_irqrestore(&tx_queue->txlock, flags);
-
return NETDEV_TX_OK;
}
@@ -2550,7 +2542,6 @@ static int gfar_poll(struct napi_struct *napi, int budget)
int tx_cleaned = 0, i, left_over_budget = budget;
unsigned long serviced_queues = 0;
int num_queues = 0;
- unsigned long flags;
num_queues = gfargrp->num_rx_queues;
budget_per_queue = budget/num_queues;
@@ -2570,13 +2561,9 @@ static int gfar_poll(struct napi_struct *napi, int budget)
rx_queue = priv->rx_queue[i];
tx_queue = priv->tx_queue[rx_queue->qindex];
- /* If we fail to get the lock,
- * don't bother with the TX BDs */
- if (spin_trylock_irqsave(&tx_queue->txlock, flags)) {
- tx_cleaned += gfar_clean_tx_ring(tx_queue);
- spin_unlock_irqrestore(&tx_queue->txlock,
- flags);
- }
+ netif_tx_lock_bh(priv->ndev);
+ tx_cleaned += gfar_clean_tx_ring(tx_queue);
+ netif_tx_unlock_bh(priv->ndev);
rx_cleaned_per_queue = gfar_clean_rx_ring(rx_queue,
budget_per_queue);
--
1.6.3.3
^ permalink raw reply related
* Re: [RFC] [PATCH] udp: optimize lookup of UDP sockets to by including destination address in the hash key
From: Octavian Purdila @ 2009-11-05 17:03 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Lucian Adrian Grijincu, netdev
In-Reply-To: <4AF2FF22.2000805@gmail.com>
On Thursday 05 November 2009 18:36:50 you wrote:
> Octavian Purdila a écrit :
> > IIRC, we first saw this issue in VoIP tests with up to 16000 sockets
> > bound on a certain port and IP addresses (each IP address is assigned to
> > a particular interface). We need this setup in order to emulate lots of
> > VoIP users each with a different IP address and possible a different L2
> > encapsulation.
>
> Interesting case indeed, is it SIP 5060 port or RTP ports ?
> (I want to know how many messages per second you want to receive)
>
> An rbtree with 16000 elements has 15 levels, its a lot, but OK
> for small trafic.
>
Yep the signaling port not the RTP port, and yes I think there is a fairly
small amount of traffic and rbtree might work.
BTW, there is another side of this problem, the time to bind() those 16K
sockets before starting the test - at least on 2.6.7 we didn't yet get to look
at this issue on a recent kernel.
Thanks,
tavi
^ permalink raw reply
* RE: [PATCH RFC] gianfar: Do not call skb recycling with disabled IRQs
From: Kumar Gopalpet-B05799 @ 2009-11-05 17:23 UTC (permalink / raw)
To: avorontsov, Jon Loeliger
Cc: linuxppc-dev, Jason Wessel, Fleming Andy-AFLEMING, David Miller,
netdev, Lennert Buytenhek, Stephen Hemminger
In-Reply-To: <20091105165738.GA31923@oksana.dev.rtsoft.ru>
[.....]
> drivers/net/gianfar.c | 19 +++----------------
> 1 files changed, 3 insertions(+), 16 deletions(-)
>
>diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
>index 197b358..a0ae604 100644
>--- a/drivers/net/gianfar.c
>+++ b/drivers/net/gianfar.c
>@@ -1899,10 +1899,8 @@ static int gfar_start_xmit(struct
>sk_buff *skb, struct net_device *dev)
> u32 lstatus;
> int i, rq = 0;
> u32 bufaddr;
>- unsigned long flags;
> unsigned int nr_frags, length;
>
>-
> rq = skb->queue_mapping;
> tx_queue = priv->tx_queue[rq];
> txq = netdev_get_tx_queue(dev, rq);
>@@ -1928,14 +1926,11 @@ static int gfar_start_xmit(struct
>sk_buff *skb, struct net_device *dev)
> /* total number of fragments in the SKB */
> nr_frags = skb_shinfo(skb)->nr_frags;
>
>- spin_lock_irqsave(&tx_queue->txlock, flags);
>-
> /* check if there is space to queue this packet */
> if ((nr_frags+1) > tx_queue->num_txbdfree) {
> /* no space, stop the queue */
> netif_tx_stop_queue(txq);
> dev->stats.tx_fifo_errors++;
>- spin_unlock_irqrestore(&tx_queue->txlock, flags);
> return NETDEV_TX_BUSY;
> }
>
>@@ -2033,9 +2028,6 @@ static int gfar_start_xmit(struct
>sk_buff *skb, struct net_device *dev)
> /* Tell the DMA to go go go */
> gfar_write(®s->tstat, TSTAT_CLEAR_THALT >> tx_queue->qindex);
>
>- /* Unlock priv */
>- spin_unlock_irqrestore(&tx_queue->txlock, flags);
>-
> return NETDEV_TX_OK;
> }
>
>@@ -2550,7 +2542,6 @@ static int gfar_poll(struct napi_struct
>*napi, int budget)
> int tx_cleaned = 0, i, left_over_budget = budget;
> unsigned long serviced_queues = 0;
> int num_queues = 0;
>- unsigned long flags;
>
> num_queues = gfargrp->num_rx_queues;
> budget_per_queue = budget/num_queues;
>@@ -2570,13 +2561,9 @@ static int gfar_poll(struct napi_struct
>*napi, int budget)
> rx_queue = priv->rx_queue[i];
> tx_queue = priv->tx_queue[rx_queue->qindex];
>
>- /* If we fail to get the lock,
>- * don't bother with the TX BDs */
>- if
>(spin_trylock_irqsave(&tx_queue->txlock, flags)) {
>- tx_cleaned +=
>gfar_clean_tx_ring(tx_queue);
>-
>spin_unlock_irqrestore(&tx_queue->txlock,
>- flags);
>- }
>+ netif_tx_lock_bh(priv->ndev);
Will this not lead to locking all the tx queues even though at this
point we are working on a "particular queue" ?
>+ tx_cleaned += gfar_clean_tx_ring(tx_queue);
>+ netif_tx_unlock_bh(priv->ndev);
>
> rx_cleaned_per_queue =
>gfar_clean_rx_ring(rx_queue,
>
>budget_per_queue);
>--
--
Thanks
Sandeep
^ permalink raw reply
* Re: [PATCH RFC] gianfar: Do not call skb recycling with disabled IRQs
From: Anton Vorontsov @ 2009-11-05 17:34 UTC (permalink / raw)
To: Kumar Gopalpet-B05799
Cc: Jon Loeliger, linuxppc-dev, Jason Wessel, Fleming Andy-AFLEMING,
David Miller, netdev, Lennert Buytenhek, Stephen Hemminger
In-Reply-To: <9F4C7D19E8361D4C94921B95BE08B81B950713@zin33exm22.fsl.freescale.net>
On Thu, Nov 05, 2009 at 10:53:08PM +0530, Kumar Gopalpet-B05799 wrote:
[...]
> >(spin_trylock_irqsave(&tx_queue->txlock, flags)) {
> >- tx_cleaned +=
> >gfar_clean_tx_ring(tx_queue);
> >-
> >spin_unlock_irqrestore(&tx_queue->txlock,
> >- flags);
> >- }
> >+ netif_tx_lock_bh(priv->ndev);
>
> Will this not lead to locking all the tx queues even though at this
> point we are working on a "particular queue" ?
Yeah, per-txq locking would be better (or not.. I need to netperf
it).
Thanks,
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [RFC] [PATCH] udp: optimize lookup of UDP sockets to by including destination address in the hash key
From: Eric Dumazet @ 2009-11-05 17:39 UTC (permalink / raw)
To: Octavian Purdila; +Cc: Lucian Adrian Grijincu, netdev
In-Reply-To: <200911051903.02859.opurdila@ixiacom.com>
Octavian Purdila a écrit :
> On Thursday 05 November 2009 18:36:50 you wrote:
>> Octavian Purdila a écrit :
>>> IIRC, we first saw this issue in VoIP tests with up to 16000 sockets
>>> bound on a certain port and IP addresses (each IP address is assigned to
>>> a particular interface). We need this setup in order to emulate lots of
>>> VoIP users each with a different IP address and possible a different L2
>>> encapsulation.
>> Interesting case indeed, is it SIP 5060 port or RTP ports ?
>> (I want to know how many messages per second you want to receive)
>>
>> An rbtree with 16000 elements has 15 levels, its a lot, but OK
>> for small trafic.
>>
>
> Yep the signaling port not the RTP port, and yes I think there is a fairly
> small amount of traffic and rbtree might work.
>
> BTW, there is another side of this problem, the time to bind() those 16K
> sockets before starting the test - at least on 2.6.7 we didn't yet get to look
> at this issue on a recent kernel.
>
Yes, this is O(N^2) algo :
0.3 seconds to bind 8000 UDP sockets on same port (different IPs)
1.5 secs / 12000 sockets
5.3 secs / 16000 sockets
18 secs / 24000 sockets
36 secs / 32000 sockets
^ permalink raw reply
* Re: [PATCH RFC] gianfar: Do not call skb recycling with disabled IRQs
From: Jon Loeliger @ 2009-11-05 17:40 UTC (permalink / raw)
To: Kumar Gopalpet-B05799
Cc: netdev, linuxppc-dev, Fleming Andy-AFLEMING, Jason Wessel,
Stephen Hemminger, David Miller, Lennert Buytenhek
In-Reply-To: <9F4C7D19E8361D4C94921B95BE08B81B950713@zin33exm22.fsl.freescale.net>
>
> [.....]
> > drivers/net/gianfar.c | 19 +++----------------
> > 1 files changed, 3 insertions(+), 16 deletions(-)
> >
> >diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c=20
> >index 197b358..a0ae604 100644
> >--- a/drivers/net/gianfar.c
> >+++ b/drivers/net/gianfar.c
> >@@ -1899,10 +1899,8 @@ static int gfar_start_xmit(struct=20
> >sk_buff *skb, struct net_device *dev)
> > u32 lstatus;
> > int i, rq = 0;
> > u32 bufaddr;
> >- unsigned long flags;
> > unsigned int nr_frags, length;
> >
> >-
> > rq = skb->queue_mapping;
> > tx_queue = priv->tx_queue[rq];
> > txq = netdev_get_tx_queue(dev, rq);
> >@@ -1928,14 +1926,11 @@ static int gfar_start_xmit(struct
> >sk_buff *skb, struct net_device *dev)
> > /* total number of fragments in the SKB */
> > nr_frags = skb_shinfo(skb)->nr_frags;
> >
> >- spin_lock_irqsave(&tx_queue->txlock, flags);
> >-
> > /* check if there is space to queue this packet */
> > if ((nr_frags+1) > tx_queue->num_txbdfree) {
> > /* no space, stop the queue */
> > netif_tx_stop_queue(txq);
> > dev->stats.tx_fifo_errors++;
> >- spin_unlock_irqrestore(&tx_queue->txlock, flags);
> > return NETDEV_TX_BUSY;
> > }
> >
> >@@ -2033,9 +2028,6 @@ static int gfar_start_xmit(struct
> >sk_buff *skb, struct net_device *dev)
> > /* Tell the DMA to go go go */
> > gfar_write(®s->tstat, TSTAT_CLEAR_THALT >> tx_queue->qindex);
> >
> >- /* Unlock priv */
> >- spin_unlock_irqrestore(&tx_queue->txlock, flags);
> >-
> > return NETDEV_TX_OK;
> > }
> >
> >@@ -2550,7 +2542,6 @@ static int gfar_poll(struct napi_struct
> >*napi, int budget)
> > int tx_cleaned = 0, i, left_over_budget = budget;
> > unsigned long serviced_queues = 0;
> > int num_queues = 0;
> >- unsigned long flags;
> >
> > num_queues = gfargrp->num_rx_queues;
> > budget_per_queue = budget/num_queues;
> >@@ -2570,13 +2561,9 @@ static int gfar_poll(struct napi_struct
> >*napi, int budget)
> > rx_queue = priv->rx_queue[i];
> > tx_queue = priv->tx_queue[rx_queue->qindex];
> >
> >- /* If we fail to get the lock,
> >- * don't bother with the TX BDs */
> >- if
> >(spin_trylock_irqsave(&tx_queue->txlock, flags)) {
> >- tx_cleaned +=
> >gfar_clean_tx_ring(tx_queue);
> >- =09
> >spin_unlock_irqrestore(&tx_queue->txlock,
> >- flags);
> >- }
> >+ netif_tx_lock_bh(priv->ndev);
>
> Will this not lead to locking all the tx queues even though at this
> point we are working on a "particular queue" ?
Similar but different question: What version is this patch based upon?
I can't find:
> >index 197b358..a0ae604 100644
My search of 2.6.31 up through current linux head (v2.6.32-rc6-26-g91d3f9b)
and benh's current head (94a8d5caba74211ec76dac80fc6e2d5c391530df) do not
have a version of this code with separate txqueues.
I confess I'm not too familiar with the history here, so I don't know
if that feature is in flux, or came, or went, or what.
That boils down to: I can't directly apply your patch, but I could
hand-fudge its intent, but only on a single tx queue variant.
jdl
^ permalink raw reply
* Re: [PATCH RFC] gianfar: Do not call skb recycling with disabled IRQs
From: Anton Vorontsov @ 2009-11-05 17:53 UTC (permalink / raw)
To: Jon Loeliger
Cc: Kumar Gopalpet-B05799, netdev, linuxppc-dev,
Fleming Andy-AFLEMING, Jason Wessel, Stephen Hemminger,
David Miller, Lennert Buytenhek
In-Reply-To: <E1N66Jp-0004Y0-8Q@jdl.com>
On Thu, Nov 05, 2009 at 11:40:21AM -0600, Jon Loeliger wrote:
[...]
> > >+ netif_tx_lock_bh(priv->ndev);
> >
> > Will this not lead to locking all the tx queues even though at this
> > point we are working on a "particular queue" ?
>
> Similar but different question: What version is this patch based upon?
> I can't find:
>
> > >index 197b358..a0ae604 100644
>
> My search of 2.6.31 up through current linux head (v2.6.32-rc6-26-g91d3f9b)
> and benh's current head (94a8d5caba74211ec76dac80fc6e2d5c391530df) do not
> have a version of this code with separate txqueues.
>
> I confess I'm not too familiar with the history here, so I don't know
> if that feature is in flux, or came, or went, or what.
Sorry for not mentioning, it's based on
git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6.git
+ compiler/sparse warnings fixes that I sent yesterday.
> That boils down to: I can't directly apply your patch, but I could
> hand-fudge its intent, but only on a single tx queue variant.
Here is the patch on top of the Linus' git tree, if you haven't
already 'back-ported' the previous patch.
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 5bf31f1..5dca99c 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -1274,7 +1274,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
u32 lstatus;
int i;
u32 bufaddr;
- unsigned long flags;
unsigned int nr_frags, length;
base = priv->tx_bd_base;
@@ -1298,14 +1297,11 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* total number of fragments in the SKB */
nr_frags = skb_shinfo(skb)->nr_frags;
- spin_lock_irqsave(&priv->txlock, flags);
-
/* check if there is space to queue this packet */
if ((nr_frags+1) > priv->num_txbdfree) {
/* no space, stop the queue */
netif_stop_queue(dev);
dev->stats.tx_fifo_errors++;
- spin_unlock_irqrestore(&priv->txlock, flags);
return NETDEV_TX_BUSY;
}
@@ -1403,9 +1399,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Tell the DMA to go go go */
gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
- /* Unlock priv */
- spin_unlock_irqrestore(&priv->txlock, flags);
-
return NETDEV_TX_OK;
}
@@ -1915,17 +1908,14 @@ static int gfar_poll(struct napi_struct *napi, int budget)
struct net_device *dev = priv->ndev;
int tx_cleaned = 0;
int rx_cleaned = 0;
- unsigned long flags;
/* Clear IEVENT, so interrupts aren't called again
* because of the packets that have already arrived */
gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK);
- /* If we fail to get the lock, don't bother with the TX BDs */
- if (spin_trylock_irqsave(&priv->txlock, flags)) {
- tx_cleaned = gfar_clean_tx_ring(dev);
- spin_unlock_irqrestore(&priv->txlock, flags);
- }
+ netif_tx_lock_bh(priv->ndev);
+ tx_cleaned = gfar_clean_tx_ring(dev);
+ netif_tx_unlock_bh(priv->ndev);
rx_cleaned = gfar_clean_rx_ring(dev, budget);
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply related
* RE: [PATCH RFC] gianfar: Do not call skb recycling with disabled IRQs
From: Kumar Gopalpet-B05799 @ 2009-11-05 17:53 UTC (permalink / raw)
To: Jon Loeliger
Cc: avorontsov, linuxppc-dev, Jason Wessel, Fleming Andy-AFLEMING,
David Miller, netdev, Lennert Buytenhek, Stephen Hemminger
In-Reply-To: <E1N66Jp-0004Y0-8Q@jdl.com>
>
>Similar but different question: What version is this patch based upon?
>I can't find:
>
> > >index 197b358..a0ae604 100644
>
>My search of 2.6.31 up through current linux head
>(v2.6.32-rc6-26-g91d3f9b) and benh's current head
>(94a8d5caba74211ec76dac80fc6e2d5c391530df) do not have a
>version of this code with separate txqueues.
>
>I confess I'm not too familiar with the history here, so I
>don't know if that feature is in flux, or came, or went, or what.
>
>That boils down to: I can't directly apply your patch, but I
>could hand-fudge its intent, but only on a single tx queue variant.
>
You might want to get the code base from the top of davem/net-next-2.6
tree
git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6.git
The multi queue is a feature available in etsec2.0 version. On older
versions you might want to
work in a single queue mode itself.
--
Thanks
Sandeep
^ permalink raw reply
* [PATCH 0/6] Misc driver fixes for 2.6.32
From: Ralf Baechle @ 2009-11-05 15:25 UTC (permalink / raw)
To: Linus Torvalds
Cc: David Daney, Atsushi Nemoto, Julia Lawall, Greg Kroah-Hartman,
devel, David Brownell, spi-devel-general, linux-kernel,
linux-mips, netdev
This is a series of patches which
o 1/6, 2/6, 3/6: Fixes for the Octeon ethernet driver in drivers/staging.
The Octeon is a MIPS-based SOC so with permisson from Greg I'm merging
these via the MIPS tree.
o 4/6: A fix to a MIPS-specific SPI driver. Posted before, no comments
were received.
o 5/6: A fix to the resource allocation to the framebuffer of the MIPS-
based SGI O2 and i686-based Visual Workstation. Also posted before, no
comments were received.
o 6/6: A fix to the serial driver for the BCM63xx which is a MIPS-based
SOC.
Ralf
^ permalink raw reply
* Re: [PATCH 03/25] mlx4_core: add multi-function communicationchannel
From: Roland Dreier @ 2009-11-05 18:01 UTC (permalink / raw)
To: Liran Liss
Cc: Yevgeny Petrilin, linux-rdma-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Tziporet Koren
In-Reply-To: <2ED289D4E09FBD4D92D911E869B97FDD0166C9B7-ia22CT07NJfiMCgWhms8HQC/G2K4zDHf@public.gmane.org>
> > And HZ/1000 is going to be 0 if HZ is less than 1000 ... so this is just
> > going to run continuously in the polling case.
> This is what we want as long as there are more pending commands.
So then instead of HZ/1000 just use 0 always? I don't see a reason why
you would want to wait if HZ >= 1000 and not wait if HZ is < 1000.
- R.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [RFC] TCP Multicast Extension
From: Michael Chan @ 2009-11-05 18:12 UTC (permalink / raw)
To: netdev
Hi,
I am planning to implement a TCP extension named "Single-source
multicast optimization", proposed in
S. Liang and D. Cheriton "TCP-SMO: Extending TCP to Support
Medium-Scale Multicast Applications", Proc. IEEE Infocom 2002.
A sample use case of this extension would be a single data source
doing bulk transfer to a number of replication sites. In this case,
TCP-SMO provides for multicast of the bulk transfer and the
optimization of transport-level retransmissions using the conventional
and well-tested TCP implementation.
In a nutshell, a TCP multicast session with a single source (server)
consists of two parts: (1) an IP multicast session, and (2) a set of
ordinary TCP connections, one between the server and each multicast
client. Data is sent via IP multicast, while the individual TCP
connections are for retransmissions and client-to-server
communication.
The required changes to the kernel TCP implementation are as follows:
Server side:
1) Creating a TCP-SMO "master socket" that keeps track of statistics
of the unchanged, per-client TCP socket
2) Modifying connection establishment so when a new client connects,
the socket created is associated to the master socket
3) Modifying the ACK path so that clients' ACKs are delivered to
master socket for processing
4) Creating a multicast group associated with the master socket
Client side:
1) Add in ability to associate multicast traffic (from server) to the
TCP connection with server
2) Joining and leaving multicast groups with the TCP socket
Before any coding, I stumbled on the following issues and thought it'd
be best to learn from the experts:
1) Is someone already doing something similar in the kernel space?
2) The original implementation was for the 2.2 kernel and had a lot of
"#ifdef CONFIG_TCP_MULTICAST strewn across the different tcp-related
constructs, including the accept, init, recvmsg, sendmsg functions and
significant additions to struct sock. The 2.6 kernel put the
tcp-specific stuff into struct tcp_sock. Given that the kernel coding
style asked for reducing number of #ifdef's in non-header code, is it
considered acceptable practice to modify this struct and the numerous
tcp functions, or should a new struct tcp_smo_sock containing a
tcp_sock as the first member be a better alternative? From a design
perspective, it seems like defining a new struct is "cleaner". But
SMO, when enabled, really re-uses / modifies existing TCP behavior. It
isn't clear to me how code reuse can be achieved without some amount
of #ifdef's in the existing implementation.
3) My goal is to make as little changes as possible to the
implementation and to provide an easy way to enable SMO from
userspace. Therefore, I'm thinking of adding TCP-level socket options
for SMO-related operations. The alternative of a different
tcp_smo_sock struct (as explained above) seems to indicate changes to
the socket() system call as well, because I will need to change the
sock being allocated. So I really doubt that approach from the
viewpoint of easy user adoption.
4) Is this in fact a fool's errand since such an extension does not
conform to the networking subsystem's development practices and hence
won't ever get accepted?
Any comments are greatly appreciated!
Thanks,
Michael
^ permalink raw reply
* RE: [PATCH 03/25] mlx4_core: add multi-functioncommunicationchannel
From: Liran Liss @ 2009-11-05 18:16 UTC (permalink / raw)
To: Roland Dreier; +Cc: Yevgeny Petrilin, linux-rdma, netdev, Tziporet Koren
In-Reply-To: <adatyx8c0lu.fsf@roland-alpha.cisco.com>
Right - will fix.
10x,
--Liran
-----Original Message-----
From: Roland Dreier [mailto:rdreier@cisco.com]
Sent: Thursday, November 05, 2009 8:01 PM
To: Liran Liss
Cc: Yevgeny Petrilin; linux-rdma@vger.kernel.org;
netdev@vger.kernel.org; Tziporet Koren
Subject: Re: [PATCH 03/25] mlx4_core: add
multi-functioncommunicationchannel
> > And HZ/1000 is going to be 0 if HZ is less than 1000 ... so this is
just > > going to run continuously in the polling case.
> This is what we want as long as there are more pending commands.
So then instead of HZ/1000 just use 0 always? I don't see a reason why
you would want to wait if HZ >= 1000 and not wait if HZ is < 1000.
- R.
^ permalink raw reply
* Re: [PATCH 2.6.33/1 00/12] WiMAX patches for 2.6.33 (batch #1)
From: Inaky Perez-Gonzalez @ 2009-11-05 18:17 UTC (permalink / raw)
To: David Miller; +Cc: netdev, wimax
In-Reply-To: <20091104.222450.149379897.davem@davemloft.net>
On Wed, 2009-11-04 at 22:24 -0800, David Miller wrote:
> From: Inaky Perez-Gonzalez <inaky@linux.intel.com>
> Date: Wed, 4 Nov 2009 13:39:36 -0800
>
> > Please pull from:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/inaky/wimax.git
>
> Well you screwed up the patch posting and you screwed up the
> GIT tree too :-/
>
> This git tree is not based upon a clone of net-next-2.6, instead
> it's a mish-mash of net-next-2.6 and some by-hand net-2.6
> pulls you've done yourself.
Yes I did -- I didn't give you the linux-2.6.33.y branch; my apologies.
The master branch is my testing tree and yes, that is not for merging.
So this pull should be against:
REPO git://git.kernel.org/pub/scm/linux/kernel/git/inaky/wimax.git
BRANCH linux-2.6.33.y
which is purely based off net-next-2.6
$ git merge-base net-next-2.6/master linux-2.6.33.y
eb2ff967a587a4a784fd2390f38e324a5bec01ec
$ git log -1 eb2ff967a587a4a784fd2390f38e324a5bec01ec
eb2ff967a587a4a784fd2390f38e324a5bec01ec xfrm: remove skb_icv_walk
> Do NOT do this.
>
> I even saw a random kbuild: change in there as well, which
> also shouldn't have been there.
>
> Fix up your tree and make it pull cleanly before submitting this
> work again.
>
> Also, when you give ma GIT URL you have to give me the branch to pull
> from at the end of the URL, if I just give that URL without the branch
> specifier to GIT for the pull it's going to fail.
This was my mistake too -- request-pull fails to detect the branch
properly when it is not given an end argument that matches HEAD and I
failed to realize that I was generating cover letter messages without
the branch.
This happened because I was breaking up the whole list of commits in
smaller chunks. Another item for the checklist.
It's maddening that I always manage to screw up somewhere :( My
apologies again.
^ permalink raw reply
* netfilter 02/02: xt_connlimit: fix regression caused by zero family value
From: Patrick McHardy @ 2009-11-05 18:23 UTC (permalink / raw)
To: David S. Miller; +Cc: Netfilter Development Mailinglist, Linux Netdev List
[-- Attachment #1: Type: text/plain, Size: 0 bytes --]
[-- Attachment #2: 02.diff --]
[-- Type: text/x-patch, Size: 2010 bytes --]
commit 0b3645af59740e4da29a18b96d8eaf68ddd2cea4
Author: Jan Engelhardt <jengelh@medozas.de>
Date: Thu Nov 5 15:02:25 2009 +0100
netfilter: xt_connlimit: fix regression caused by zero family value
Commit v2.6.28-rc1~7172~1092~2 was slightly incomplete; not all
instances of par->match->family were changed to par->family.
Netfilter bugzilla #610.
Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 6809809..38f03f7 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -103,7 +103,7 @@ static int count_them(struct xt_connlimit_data *data,
const struct nf_conntrack_tuple *tuple,
const union nf_inet_addr *addr,
const union nf_inet_addr *mask,
- const struct xt_match *match)
+ u_int8_t family)
{
const struct nf_conntrack_tuple_hash *found;
struct xt_connlimit_conn *conn;
@@ -113,8 +113,7 @@ static int count_them(struct xt_connlimit_data *data,
bool addit = true;
int matches = 0;
-
- if (match->family == NFPROTO_IPV6)
+ if (family == NFPROTO_IPV6)
hash = &data->iphash[connlimit_iphash6(addr, mask)];
else
hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)];
@@ -157,8 +156,7 @@ static int count_them(struct xt_connlimit_data *data,
continue;
}
- if (same_source_net(addr, mask, &conn->tuple.src.u3,
- match->family))
+ if (same_source_net(addr, mask, &conn->tuple.src.u3, family))
/* same source network -> be counted! */
++matches;
nf_ct_put(found_ct);
@@ -207,7 +205,7 @@ connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
spin_lock_bh(&info->data->lock);
connections = count_them(info->data, tuple_ptr, &addr,
- &info->mask, par->match);
+ &info->mask, par->family);
spin_unlock_bh(&info->data->lock);
if (connections < 0) {
^ permalink raw reply related
* netfilter 01/02: nf_nat: fix NAT issue in 2.6.30.4+
From: Patrick McHardy @ 2009-11-05 18:23 UTC (permalink / raw)
To: David S. Miller; +Cc: Netfilter Development Mailinglist, Linux Netdev List
[-- Attachment #1: Type: text/plain, Size: 468 bytes --]
Hi Dave,
the following two patches fix two netfilter bugs:
- incorrect sequence number tracking in TCP conntrack in combination
with NAT helpers that enlarge the packet, causing incorrectly
detected out of window packets
- a regression in the connlimit match
The first patch is quite large for this late in the release cycle, so
if you prefer, I'll queue it up for net-next instead.
I'll pass on both to -stable once they hit upstream.
Please apply, thanks!
[-- Attachment #2: 01.diff --]
[-- Type: text/x-patch, Size: 10269 bytes --]
commit 0132f9835c1c19a369954e1eb56dca80a1382369
Author: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Date: Thu Sep 17 13:05:15 2009 +0200
netfilter: nf_nat: fix NAT issue in 2.6.30.4+
Vitezslav Samel discovered that since 2.6.30.4+ active FTP can not work
over NAT. The "cause" of the problem was a fix of unacknowledged data
detection with NAT (commit a3a9f79e361e864f0e9d75ebe2a0cb43d17c4272).
However, actually, that fix uncovered a long standing bug in TCP conntrack:
when NAT was enabled, we simply updated the max of the right edge of
the segments we have seen (td_end), by the offset NAT produced with
changing IP/port in the data. However, we did not update the other parameter
(td_maxend) which is affected by the NAT offset. Thus that could drift
away from the correct value and thus resulted breaking active FTP.
The patch below fixes the issue by *not* updating the conntrack parameters
from NAT, but instead taking into account the NAT offsets in conntrack in a
consistent way. (Updating from NAT would be more harder and expensive because
it'd need to re-calculate parameters we already calculated in conntrack.)
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index cbdd628..5cf7270 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -255,11 +255,9 @@ static inline bool nf_ct_kill(struct nf_conn *ct)
}
/* These are for NAT. Icky. */
-/* Update TCP window tracking data when NAT mangles the packet */
-extern void nf_conntrack_tcp_update(const struct sk_buff *skb,
- unsigned int dataoff,
- struct nf_conn *ct, int dir,
- s16 offset);
+extern s16 (*nf_ct_nat_offset)(const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ u32 seq);
/* Fake conntrack entry for untracked connections */
extern struct nf_conn nf_conntrack_untracked;
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h
index 237a961..4222220 100644
--- a/include/net/netfilter/nf_nat_helper.h
+++ b/include/net/netfilter/nf_nat_helper.h
@@ -32,4 +32,8 @@ extern int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
* to port ct->master->saved_proto. */
extern void nf_nat_follow_master(struct nf_conn *ct,
struct nf_conntrack_expect *this);
+
+extern s16 nf_nat_get_offset(const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ u32 seq);
#endif
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 68afc6e..fe1a644 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -750,6 +750,8 @@ static int __init nf_nat_init(void)
BUG_ON(nfnetlink_parse_nat_setup_hook != NULL);
rcu_assign_pointer(nfnetlink_parse_nat_setup_hook,
nfnetlink_parse_nat_setup);
+ BUG_ON(nf_ct_nat_offset != NULL);
+ rcu_assign_pointer(nf_ct_nat_offset, nf_nat_get_offset);
return 0;
cleanup_extend:
@@ -764,6 +766,7 @@ static void __exit nf_nat_cleanup(void)
nf_ct_extend_unregister(&nat_extend);
rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL);
rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL);
+ rcu_assign_pointer(nf_ct_nat_offset, NULL);
synchronize_net();
}
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 09172a6..f9520fa 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -73,6 +73,28 @@ adjust_tcp_sequence(u32 seq,
DUMP_OFFSET(this_way);
}
+/* Get the offset value, for conntrack */
+s16 nf_nat_get_offset(const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ u32 seq)
+{
+ struct nf_conn_nat *nat = nfct_nat(ct);
+ struct nf_nat_seq *this_way;
+ s16 offset;
+
+ if (!nat)
+ return 0;
+
+ this_way = &nat->seq[dir];
+ spin_lock_bh(&nf_nat_seqofs_lock);
+ offset = after(seq, this_way->correction_pos)
+ ? this_way->offset_after : this_way->offset_before;
+ spin_unlock_bh(&nf_nat_seqofs_lock);
+
+ return offset;
+}
+EXPORT_SYMBOL_GPL(nf_nat_get_offset);
+
/* Frobs data inside this packet, which is linear. */
static void mangle_contents(struct sk_buff *skb,
unsigned int dataoff,
@@ -189,11 +211,6 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb,
adjust_tcp_sequence(ntohl(tcph->seq),
(int)rep_len - (int)match_len,
ct, ctinfo);
- /* Tell TCP window tracking about seq change */
- nf_conntrack_tcp_update(skb, ip_hdrlen(skb),
- ct, CTINFO2DIR(ctinfo),
- (int)rep_len - (int)match_len);
-
nf_conntrack_event_cache(IPCT_NATSEQADJ, ct);
}
return 1;
@@ -415,12 +432,7 @@ nf_nat_seq_adjust(struct sk_buff *skb,
tcph->seq = newseq;
tcph->ack_seq = newack;
- if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo))
- return 0;
-
- nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir, seqoff);
-
- return 1;
+ return nf_nat_sack_adjust(skb, tcph, ct, ctinfo);
}
/* Setup NAT on this expected conntrack so it follows master. */
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index b371098..805b6a9 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1350,6 +1350,11 @@ err_stat:
return ret;
}
+s16 (*nf_ct_nat_offset)(const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ u32 seq);
+EXPORT_SYMBOL_GPL(nf_ct_nat_offset);
+
int nf_conntrack_init(struct net *net)
{
int ret;
@@ -1367,6 +1372,9 @@ int nf_conntrack_init(struct net *net)
/* For use by REJECT target */
rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
+
+ /* Howto get NAT offsets */
+ rcu_assign_pointer(nf_ct_nat_offset, NULL);
}
return 0;
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 97a82ba..ba2b769 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -492,6 +492,21 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff,
}
}
+#ifdef CONFIG_NF_NAT_NEEDED
+static inline s16 nat_offset(const struct nf_conn *ct,
+ enum ip_conntrack_dir dir,
+ u32 seq)
+{
+ typeof(nf_ct_nat_offset) get_offset = rcu_dereference(nf_ct_nat_offset);
+
+ return get_offset != NULL ? get_offset(ct, dir, seq) : 0;
+}
+#define NAT_OFFSET(pf, ct, dir, seq) \
+ (pf == NFPROTO_IPV4 ? nat_offset(ct, dir, seq) : 0)
+#else
+#define NAT_OFFSET(pf, ct, dir, seq) 0
+#endif
+
static bool tcp_in_window(const struct nf_conn *ct,
struct ip_ct_tcp *state,
enum ip_conntrack_dir dir,
@@ -506,6 +521,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
struct ip_ct_tcp_state *receiver = &state->seen[!dir];
const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
__u32 seq, ack, sack, end, win, swin;
+ s16 receiver_offset;
bool res;
/*
@@ -519,11 +535,16 @@ static bool tcp_in_window(const struct nf_conn *ct,
if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
tcp_sack(skb, dataoff, tcph, &sack);
+ /* Take into account NAT sequence number mangling */
+ receiver_offset = NAT_OFFSET(pf, ct, !dir, ack - 1);
+ ack -= receiver_offset;
+ sack -= receiver_offset;
+
pr_debug("tcp_in_window: START\n");
pr_debug("tcp_in_window: ");
nf_ct_dump_tuple(tuple);
- pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n",
- seq, ack, sack, win, end);
+ pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n",
+ seq, ack, receiver_offset, sack, receiver_offset, win, end);
pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
"receiver end=%u maxend=%u maxwin=%u scale=%i\n",
sender->td_end, sender->td_maxend, sender->td_maxwin,
@@ -613,8 +634,8 @@ static bool tcp_in_window(const struct nf_conn *ct,
pr_debug("tcp_in_window: ");
nf_ct_dump_tuple(tuple);
- pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n",
- seq, ack, sack, win, end);
+ pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n",
+ seq, ack, receiver_offset, sack, receiver_offset, win, end);
pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
"receiver end=%u maxend=%u maxwin=%u scale=%i\n",
sender->td_end, sender->td_maxend, sender->td_maxwin,
@@ -700,7 +721,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
before(seq, sender->td_maxend + 1) ?
after(end, sender->td_end - receiver->td_maxwin - 1) ?
before(sack, receiver->td_end + 1) ?
- after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
+ after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG"
: "ACK is under the lower bound (possible overly delayed ACK)"
: "ACK is over the upper bound (ACKed data not seen yet)"
: "SEQ is under the lower bound (already ACKed data retransmitted)"
@@ -715,39 +736,6 @@ static bool tcp_in_window(const struct nf_conn *ct,
return res;
}
-#ifdef CONFIG_NF_NAT_NEEDED
-/* Update sender->td_end after NAT successfully mangled the packet */
-/* Caller must linearize skb at tcp header. */
-void nf_conntrack_tcp_update(const struct sk_buff *skb,
- unsigned int dataoff,
- struct nf_conn *ct, int dir,
- s16 offset)
-{
- const struct tcphdr *tcph = (const void *)skb->data + dataoff;
- const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir];
- const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[!dir];
- __u32 end;
-
- end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph);
-
- spin_lock_bh(&ct->lock);
- /*
- * We have to worry for the ack in the reply packet only...
- */
- if (ct->proto.tcp.seen[dir].td_end + offset == end)
- ct->proto.tcp.seen[dir].td_end = end;
- ct->proto.tcp.last_end = end;
- spin_unlock_bh(&ct->lock);
- pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
- "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
- sender->td_end, sender->td_maxend, sender->td_maxwin,
- sender->td_scale,
- receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
- receiver->td_scale);
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update);
-#endif
-
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
^ permalink raw reply related
* [PATCH 1/2] udp: cleanup __udp4_lib_mcast_deliver
From: Lucian Adrian Grijincu @ 2009-11-05 18:33 UTC (permalink / raw)
To: netdev; +Cc: opurdila
[-- Attachment #1: Type: text/plain, Size: 371 bytes --]
__udp4_lib_mcast_deliver always returned 0.
It's caller can return 0 explicitly to make things clearer.
Also, we don't need the spin_lock() on the hslot to free the skb.
Signed-off-by: Lucian Adrian Grijincu <lgrijincu@ixiacom.com>
---
net/ipv4/udp.c | 57 +++++++++++++++++++++++++++++--------------------------
1 files changed, 30 insertions(+), 27 deletions(-)
[-- Attachment #2: 0001-udp-cleanup-__udp4_lib_mcast_deliver.patch --]
[-- Type: text/plain, Size: 2479 bytes --]
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 4274c1c..425b2d4 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1198,12 +1198,12 @@ drop:
* Note: called only from the BH handler context,
* so we don't need to lock the hashes.
*/
-static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
+static void __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
struct udphdr *uh,
__be32 saddr, __be32 daddr,
struct udp_table *udptable)
{
- struct sock *sk;
+ struct sock *sk, *sknext;
struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest));
int dif;
@@ -1211,31 +1211,32 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
sk = sk_nulls_head(&hslot->head);
dif = skb->dev->ifindex;
sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif);
- if (sk) {
- struct sock *sknext = NULL;
-
- do {
- struct sk_buff *skb1 = skb;
-
- sknext = udp_v4_mcast_next(net, sk_nulls_next(sk), uh->dest,
- daddr, uh->source, saddr,
- dif);
- if (sknext)
- skb1 = skb_clone(skb, GFP_ATOMIC);
-
- if (skb1) {
- int ret = udp_queue_rcv_skb(sk, skb1);
- if (ret > 0)
- /* we should probably re-process instead
- * of dropping packets here. */
- kfree_skb(skb1);
- }
- sk = sknext;
- } while (sknext);
- } else
+ if (!sk) {
+ spin_unlock(&hslot->lock);
consume_skb(skb);
+ return;
+ }
+
+ do {
+ struct sk_buff *skb1 = skb;
+
+ sknext = udp_v4_mcast_next(net, sk_nulls_next(sk), uh->dest,
+ daddr, uh->source, saddr,
+ dif);
+ if (sknext)
+ skb1 = skb_clone(skb, GFP_ATOMIC);
+
+ if (skb1) {
+ int ret = udp_queue_rcv_skb(sk, skb1);
+ if (ret > 0)
+ /* we should probably re-process instead
+ * of dropping packets here. */
+ kfree_skb(skb1);
+ }
+ sk = sknext;
+ } while (sknext);
spin_unlock(&hslot->lock);
- return 0;
+ return;
}
/* Initialize UDP checksum. If exited with zero value (success),
@@ -1314,9 +1315,11 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
saddr = ip_hdr(skb)->saddr;
daddr = ip_hdr(skb)->daddr;
- if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
- return __udp4_lib_mcast_deliver(net, skb, uh,
+ if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) {
+ __udp4_lib_mcast_deliver(net, skb, uh,
saddr, daddr, udptable);
+ return 0;
+ }
sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
^ 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