* Re: Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Herbert Xu @ 2005-05-27 0:11 UTC (permalink / raw)
To: Ganesh Venkatesan
Cc: Venkatesan, Ganesh, Andrew Morton, Jian Jun He, anton, rende,
Brandeburg, Jesse, jgarzik, wangjs, Ronciak, John, cdlwangl,
linuxppc64-dev, netdev
In-Reply-To: <5fc59ff30505261608541b74fb@mail.gmail.com>
On Thu, May 26, 2005 at 04:08:17PM -0700, Ganesh Venkatesan wrote:
>
> I do not get it. Bear with my ignorance.
>
> e100_tx_timeout does not call e100_down.
>
> It is called from e100_tx_timeout_task which is invoked as a result of
> schedule_work. Are you saying that it would still not have the right
> context to call netif_disable_poll()?
Sorry, I was not aware that you've already added the sched work
in the driver. With that it should work correctly.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH 2.6.12-rc4] IPv4/IPv6: UDP Large Send Offload feature
From: David S. Miller @ 2005-05-26 23:42 UTC (permalink / raw)
To: ravinandan.arakali
Cc: jgarzik, netdev, raghavendra.koushik, leonid.grossman,
ananda.raju, rapuru.sriram
In-Reply-To: <20050526232006.60E6365005@linux.site>
sock_append_data() seems like a lot of wasted work.
We already pass around the fragmented SKB as a list chained by
skb_shinfo(skb)->fraglist, just pass this thing to the device and in
this way you'll avoid all of that work sock_append_data() does
entirely.
Or is there a reason you did not implement it this
way?
This is one of the uses the skb_shinfo(skb)->fraglist was intended
for.
IN FACT, this fragmentation offload you are implementing here is what
the feature bit NETIF_F_FRAGLIST was meant to indicate.
^ permalink raw reply
* Re: [PATCH 2.6.12-rc4] IPv4/IPv6: UDP Large Send Offload feature
From: David S. Miller @ 2005-05-26 23:37 UTC (permalink / raw)
To: ravinandan.arakali
Cc: jgarzik, netdev, raghavendra.koushik, leonid.grossman,
ananda.raju, rapuru.sriram
In-Reply-To: <20050526232006.60E6365005@linux.site>
From: ravinandan.arakali@neterion.com
Date: Thu, 26 May 2005 16:20:06 -0700 (PDT)
> Attached below is a kernel patch to provide UDP LSO(Large Send Offload)
> feature.
Interesting patch, thanks a lot. Some quick review:
1) I think you can use skb_shinfo(skb)->tso_size, and UDP packet
with this non-zero will never be sent unless the driver
indicates the capability.
2) I think NETIF_F_USO is a nicer name and consistent with
the existing NETIF_F_TSO macro name. Please change it.
3) Make NETIF_F_USO require both NETIF_F_SG and checksumming
capability. Check this at device registry, and ethtool operation
time, so that you need not verify it during packet send.
For #3, it should be a simple change to net/core/dev.c and
net/core/ethtool.c, for example see this test we have in
net/core/dev.c:register_netdevice()
/* TSO requires that SG is present as well. */
if ((dev->features & NETIF_F_TSO) &&
!(dev->features & NETIF_F_SG)) {
printk("%s: Dropping NETIF_F_TSO since no SG feature.\n",
dev->name);
dev->features &= ~NETIF_F_TSO;
}
Just make the same exact check for NETIF_F_USO.
Similarly, you'll need to add the necessary ethtool machinery
(missing from your patch, but really needed) then do something
similar to net/core/ethtool.c:ethtool_set_tso() for ethtool setting
of NETIF_F_USO. Probably you'll name this function ethtool_set_uso()
:-)
^ permalink raw reply
* [PATCH 2.6.12-rc4] IPv4/IPv6: UDP Large Send Offload feature
From: ravinandan.arakali @ 2005-05-26 23:20 UTC (permalink / raw)
To: davem, jgarzik, netdev
Cc: raghavendra.koushik, ravinandan.arakali, leonid.grossman,
ananda.raju, rapuru.sriram
Hi,
Attached below is a kernel patch to provide UDP LSO(Large Send Offload)
feature.
This is the UDP counterpart of TSO. Basically, an oversized packet
(less than or equal to 65535) is handed to the NIC. The adapter then
produces IP fragments in conformance with RFC791(IPv4) or RFC2460(IPv6).
Very much like TCP TSO, UDP LSO provides significant reduction in CPU
utilization, especially with 1500 MTU frames. For 10GbE traffic,
these extra CPU cycles translate into significant throughput increase
on most server platforms.
Reasonable amount of testing has been done on the patch using Neterion's
10G Xframe-II adapter to ensure code stability.
Please review the patch.
Also, below is a "how-to" on changes required in network drivers to use
the UDP LSO interface.
UDP Large Send Offload (ULSO) Interface:
----------------------------------------
ULSO is a feature wherein the Linux kernel network stack will offload
the IP fragmentation functionality of large UDP datagram to hardware. This
will reduce the overhead of stack in fragmenting the large UDP datagram to
MTU sized packets.
1) Drivers indicate their capability of ULSO using
dev->features |= NETIF_F_UDP_LSO | NETIF_F_HW_CSUM
NETIF_F_HW_CSUM is required for ULSO over ipv6.
2) ULSO packet will be submitted for transmission using driver xmit
routine. ULSO packet will have a non zero value for
"skb_shinfo(skb)->ulso_size"
skb_shinfo(skb)->ulso_size will indicate the length of data in each IP
fragment going out of the adapter after IP fragmentation by hardware.
skb->data will contain MAC/IP/UDP header and skb_shinfo(skb)->frags[]
contains the data payload. The skb->ip_summed will be set to CHECKSUM_HW
indicating that hardware has to perform checksum calculation. Hardware
should compute the UDP checksum of complete UDP datagram and also the IP
header checksum of each fragmented IP packet.
For IPV6 the ULSO provides the fragment identification id in
skb_shinfo(skb)->ip6_id. The adapter should use this ID for generating IPv6
fragments.
Signed-off-by: Ananda Raju <ananda.raju@neterion.com>
Signed-off-by: Ravinandan Arakali <ravinandan.arakali@neterion.com>
---
diff -uNr linux-2.6.12-rc4.org/include/linux/netdevice.h linux-2.6.12-rc4/include/linux/netdevice.h
--- linux-2.6.12-rc4.org/include/linux/netdevice.h 2005-05-25 17:18:11.000000000 +0545
+++ linux-2.6.12-rc4/include/linux/netdevice.h 2005-05-25 20:28:25.000000000 +0545
@@ -414,6 +414,7 @@
#define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN packets */
#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */
#define NETIF_F_LLTX 4096 /* LockLess TX */
+#define NETIF_F_UDP_LSO 8192 /* Can offload UDP Large Send*/
/* Called after device is detached from network. */
void (*uninit)(struct net_device *dev);
diff -uNr linux-2.6.12-rc4.org/include/linux/skbuff.h linux-2.6.12-rc4/include/linux/skbuff.h
--- linux-2.6.12-rc4.org/include/linux/skbuff.h 2005-05-25 17:18:20.000000000 +0545
+++ linux-2.6.12-rc4/include/linux/skbuff.h 2005-05-26 17:04:50.000000000 +0545
@@ -135,6 +135,8 @@
atomic_t dataref;
unsigned int nr_frags;
unsigned short tso_size;
+ unsigned short ulso_size;
+ unsigned int ip6_id;
unsigned short tso_segs;
struct sk_buff *frag_list;
skb_frag_t frags[MAX_SKB_FRAGS];
diff -uNr linux-2.6.12-rc4.org/include/net/sock.h linux-2.6.12-rc4/include/net/sock.h
--- linux-2.6.12-rc4.org/include/net/sock.h 2005-05-25 17:18:44.000000000 +0545
+++ linux-2.6.12-rc4/include/net/sock.h 2005-05-25 20:28:14.000000000 +0545
@@ -1296,5 +1296,11 @@
return -ENODEV;
}
#endif
+struct sk_buff *sock_append_data(struct sock *sk,
+ int getfrag(void *from, char *to, int offset, int len,
+ int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen,
+ int hh_len, int fragheaderlen,
+ unsigned int flags,int *err);
#endif /* _SOCK_H */
diff -uNr linux-2.6.12-rc4.org/net/core/skbuff.c linux-2.6.12-rc4/net/core/skbuff.c
--- linux-2.6.12-rc4.org/net/core/skbuff.c 2005-05-25 20:25:35.000000000 +0545
+++ linux-2.6.12-rc4/net/core/skbuff.c 2005-05-25 20:46:04.000000000 +0545
@@ -159,6 +159,8 @@
skb_shinfo(skb)->tso_size = 0;
skb_shinfo(skb)->tso_segs = 0;
skb_shinfo(skb)->frag_list = NULL;
+ skb_shinfo(skb)->ulso_size = 0;
+ skb_shinfo(skb)->ip6_id = 0;
out:
return skb;
nodata:
diff -uNr linux-2.6.12-rc4.org/net/core/sock.c linux-2.6.12-rc4/net/core/sock.c
--- linux-2.6.12-rc4.org/net/core/sock.c 2005-05-25 20:25:47.000000000 +0545
+++ linux-2.6.12-rc4/net/core/sock.c 2005-05-26 17:19:39.000000000 +0545
@@ -1401,6 +1401,107 @@
EXPORT_SYMBOL(proto_unregister);
+/*
+ * sock_append_data - append the user data to a skb,
+ * sk - sock structure which contains skbs for transmission
+ * getfrag - The function to be called to get the data from the user.
+ * from - pointer to user message iov
+ * length - length of the iov message
+ * transhdrlen - transport header length
+ * hh_len - hardware header length
+ * fragheaderlen - length of the IP header
+ * flags - iov message flags
+ * err - Error code returned
+ *
+ * This procedure will allocate a skb enough to hold protocol headers and
+ * append the user data in the fragment part of the skb and add the skb to
+ * socket write queue
+ */
+struct sk_buff *sock_append_data(struct sock *sk,
+ int getfrag(void *from, char *to, int offset, int len,
+ int odd, struct sk_buff *skb),
+ void *from, int length, int transhdrlen,
+ int hh_len, int fragheaderlen,
+ unsigned int flags,int *err)
+{
+ struct sk_buff *skb;
+ int frg_cnt = 0;
+ skb_frag_t *frag = NULL;
+ struct page *page = NULL;
+ int copy, left;
+ int offset = 0;
+
+ if (!((sk->sk_route_caps & NETIF_F_SG) &&
+ (sk->sk_route_caps & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)))) {
+ *err = -EOPNOTSUPP;
+ return NULL;
+ }
+ if (skb_queue_len(&sk->sk_write_queue)) {
+ *err = -EOPNOTSUPP;
+ return NULL;
+ }
+
+ skb = sock_alloc_send_skb(sk,
+ hh_len + fragheaderlen + transhdrlen + 20,
+ (flags & MSG_DONTWAIT), err);
+ if (skb == NULL) {
+ *err = -ENOMEM;
+ return NULL;
+ }
+ /* reserve space for Hardware header */
+ skb_reserve(skb, hh_len);
+ /* create space for UDP/IP header */
+ skb_put(skb,fragheaderlen + transhdrlen);
+ /* initialize network header pointer */
+ skb->nh.raw = skb->data;
+ /* initialize protocol header pointer */
+ skb->h.raw = skb->data + fragheaderlen;
+ skb->ip_summed = CHECKSUM_HW;
+ skb->csum = 0;
+ do {
+ copy = length;
+ if (frg_cnt >= MAX_SKB_FRAGS) {
+ *err = -EFAULT;
+ kfree_skb(skb);
+ return NULL;
+ }
+ page = alloc_pages(sk->sk_allocation, 0);
+ if (page == NULL) {
+ *err = -ENOMEM;
+ kfree_skb(skb);
+ return NULL;
+ }
+ sk->sk_sndmsg_page = page;
+ sk->sk_sndmsg_off = 0;
+ skb_fill_page_desc(skb, frg_cnt, page, 0, 0);
+ skb->truesize += PAGE_SIZE;
+ atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc);
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+ frag = &skb_shinfo(skb)->frags[frg_cnt - 1];
+ left = PAGE_SIZE - frag->page_offset;
+ if (copy > left)
+ copy = left;
+ if (getfrag(from, page_address(frag->page)+
+ frag->page_offset+frag->size,
+ offset, copy, 0, skb) < 0) {
+ *err = -EFAULT;
+ kfree_skb(skb);
+ return NULL;
+ }
+ sk->sk_sndmsg_off += copy;
+ frag->size += copy;
+ skb->len += copy;
+ skb->data_len += copy;
+ offset += copy;
+ length -= copy;
+ page = NULL;
+ } while (length > 0);
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+ *err = 0;
+ return skb;
+}
+EXPORT_SYMBOL(sock_append_data);
+
#ifdef CONFIG_PROC_FS
static inline struct proto *__proto_head(void)
{
diff -uNr linux-2.6.12-rc4.org/net/ipv4/ip_output.c linux-2.6.12-rc4/net/ipv4/ip_output.c
--- linux-2.6.12-rc4.org/net/ipv4/ip_output.c 2005-05-25 20:26:07.000000000 +0545
+++ linux-2.6.12-rc4/net/ipv4/ip_output.c 2005-05-25 20:27:20.000000000 +0545
@@ -291,7 +291,8 @@
{
IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
- if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size)
+ if (skb->len > dst_mtu(skb->dst) &&
+ !(skb_shinfo(skb)->ulso_size || skb_shinfo(skb)->tso_size))
return ip_fragment(skb, ip_finish_output);
else
return ip_finish_output(skb);
@@ -789,6 +790,29 @@
inet->cork.length += length;
+ sk->sk_route_caps |= rt->u.dst.dev->features;
+ if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+ (sk->sk_route_caps & NETIF_F_UDP_LSO)) {
+ /* There is support for UDP large send offload by network
+ * device, so create one single skb packet containing complete
+ * udp datagram
+ */
+ skb = sock_append_data(sk, getfrag, from,
+ (length - transhdrlen), transhdrlen,
+ hh_len, fragheaderlen, flags, &err);
+ if (skb != NULL) {
+ /* specify the length of each IP datagram fragment*/
+ skb_shinfo(skb)->ulso_size = (mtu - fragheaderlen);
+ return 0;
+ } else if (err == -EOPNOTSUPP) {
+ /* There is not enough support do UPD LSO,
+ * so follow normal path
+ */
+ err = 0;
+ } else
+ goto error;
+ }
+
/* So, what's going on in the loop below?
*
* We use calculated fragment length to generate chained skb,
diff -uNr linux-2.6.12-rc4.org/net/ipv6/ip6_output.c linux-2.6.12-rc4/net/ipv6/ip6_output.c
--- linux-2.6.12-rc4.org/net/ipv6/ip6_output.c 2005-05-25 20:26:17.000000000 +0545
+++ linux-2.6.12-rc4/net/ipv6/ip6_output.c 2005-05-26 17:05:06.000000000 +0545
@@ -147,7 +147,8 @@
int ip6_output(struct sk_buff *skb)
{
- if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst))
+ if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ulso_size) ||
+ dst_allfrag(skb->dst))
return ip6_fragment(skb, ip6_output2);
else
return ip6_output2(skb);
@@ -898,6 +899,35 @@
*/
inet->cork.length += length;
+ sk->sk_route_caps |= rt->u.dst.dev->features;
+ if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) &&
+ ((sk->sk_route_caps & (NETIF_F_UDP_LSO | NETIF_F_HW_CSUM)) ==
+ (NETIF_F_UDP_LSO | NETIF_F_HW_CSUM))) {
+
+ /* There is support for UDP large send offload by network
+ * device, so create one single skb packet containing complete
+ * udp datagram
+ */
+ skb = sock_append_data(sk, getfrag, from,
+ (length - transhdrlen), transhdrlen,
+ hh_len, fragheaderlen, flags, &err);
+ if (skb != NULL) {
+ struct frag_hdr fhdr;
+
+ /* specify the length of each IP datagram fragment*/
+ skb_shinfo(skb)->ulso_size = (mtu - fragheaderlen -
+ sizeof(struct frag_hdr));
+ ipv6_select_ident(skb, &fhdr);
+ skb_shinfo(skb)->ip6_id = fhdr.identification;
+ return 0;
+ } else if (err == -EOPNOTSUPP){
+ /* There is not enough support for UDP LSO,
+ * so follow normal path
+ */
+ err = 0;
+ } else
+ goto error;
+ }
if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL)
goto alloc_new_skb;
^ permalink raw reply
* Re: Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Ganesh Venkatesan @ 2005-05-26 23:08 UTC (permalink / raw)
To: Herbert Xu
Cc: Venkatesan, Ganesh, Andrew Morton, Jian Jun He, anton, rende,
Brandeburg, Jesse, jgarzik, wangjs, Ronciak, John, cdlwangl,
linuxppc64-dev, netdev
In-Reply-To: <20050526213421.GA8077@gondor.apana.org.au>
Herbert:
I do not get it. Bear with my ignorance.
e100_tx_timeout does not call e100_down.
It is called from e100_tx_timeout_task which is invoked as a result of
schedule_work. Are you saying that it would still not have the right
context to call netif_disable_poll()?
thanks,
ganesh.
On 5/26/05, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Thu, May 26, 2005 at 01:41:53PM -0700, Venkatesan, Ganesh wrote:
> >
> > I already responded to this analysis before. In any case, here it is:
> >
> > Later versions of e100 (3.4.8 for instance) includes a call to
> > netif_poll_disable in e100_down. This is supposed to wait and when it
>
> As I said last time, this is broken since the code path in question
> starts from tx_timeout which is called in softirq context. You'll
> need to schedule a work struct at least.
>
> Cheers,
> --
> Visit Openswan at http://www.openswan.org/
> Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
>
^ permalink raw reply
* Re: [NET] 2.6.x build warning
From: David S. Miller @ 2005-05-26 23:06 UTC (permalink / raw)
To: jgarzik; +Cc: netdev
In-Reply-To: <42961EDB.7000407@pobox.com>
From: Jeff Garzik <jgarzik@pobox.com>
Date: Thu, 26 May 2005 15:09:15 -0400
> from current git tree:
>
> net/ipv6/ip6_flowlabel.c: In function `ipv6_flowlabel_opt':
> net/ipv6/ip6_flowlabel.c:540: warning: ignoring return value of
> `copy_to_user', declared with attribute warn_unused_result
I've fixed this warning in my tree, thanks Jeff.
^ permalink raw reply
* Re: [PATCH linux-2.6.12-rc4-mm1] ethtool: Add NETIF_F_HW_CSUM support
From: David S. Miller @ 2005-05-26 23:00 UTC (permalink / raw)
To: shemminger; +Cc: jdmason, netdev
In-Reply-To: <20050523145321.49899042@dxpl.pdx.osdl.net>
From: Stephen Hemminger <shemminger@osdl.org>
Date: Mon, 23 May 2005 14:53:21 -0700
> This patch makes perfect sense because it allows for common code to be
> used by device drivers in their ethtool_ops. So this is the logical way to handle
> this.
You're right, of course. I've applied the patch.
Thanks.
^ permalink raw reply
* Re: [Bridge] Re: [PATCH] (6/6) bridge: receive path optimization
From: David S. Miller @ 2005-05-26 22:54 UTC (permalink / raw)
To: shemminger; +Cc: netdev, bridge
In-Reply-To: <20050526154857.3cb34d11@dxpl.pdx.osdl.net>
From: Stephen Hemminger <shemminger@osdl.org>
Date: Thu, 26 May 2005 15:48:57 -0700
> So the call chain is bounded (ie not related to number of filters)
> but slightly longer.
You're right, thanks for the explanation Stephen.
^ permalink raw reply
* Re: [Bridge] Re: [PATCH] (6/6) bridge: receive path optimization
From: Stephen Hemminger @ 2005-05-26 22:48 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, bridge
In-Reply-To: <20050526.144638.71091166.davem@davemloft.net>
On Thu, 26 May 2005 14:46:38 -0700 (PDT)
"David S. Miller" <davem@davemloft.net> wrote:
> From: Stephen Hemminger <shemminger@osdl.org>
> Date: Thu, 26 May 2005 11:04:25 -0700
>
> > This improves the bridge local receive path by avoiding going
> > through another softirq. The bridge receive path is already being called
> > from a netif_receive_skb() there is no point in going through another
> > receiveq round trip.
> >
> > Recursion is limited because bridge can never be a port of a bridge
> > so handle_bridge() always returns.
>
> I applied all 6 patches, but this one in particular I'd like
> to comment on.
>
> Remember all of those bridge netfilter stack usage issues
> we have a few months ago? This could edge us back into
> those problems again.
no, because the br_frame_finish is called after the netfilter
decision:
netif_receive_skb
handle_bridge
br_handle_frame
br_handle_frame_finish
br_pass_frame_up
br_pass_frame_up_finish
netif_receive_skb <---- change
(normal receive path)
So the call chain is bounded (ie not related to number of filters)
but slightly longer.
^ permalink raw reply
* Re: [PATCH 3/4] [NEIGH] neighbour table configuration and statistics via rtnetlink
From: David S. Miller @ 2005-05-26 22:37 UTC (permalink / raw)
To: tgraf; +Cc: netdev
In-Reply-To: <20050526222656.GD15391@postel.suug.ch>
From: Thomas Graf <tgraf@suug.ch>
Date: Fri, 27 May 2005 00:26:56 +0200
> Sorry, it's what happens if one gets interrupted in the middle
> of writing a longer comment. ;-> Patch edited by hand but
> it should still apply.
Thanks.
^ permalink raw reply
* Re: [PATCH 3/4] [NEIGH] neighbour table configuration and statistics via rtnetlink
From: Thomas Graf @ 2005-05-26 22:26 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev
In-Reply-To: <20050526.151726.85409972.davem@davemloft.net>
* David S. Miller <20050526.151726.85409972.davem@davemloft.net> 2005-05-26 15:17
> From: Thomas Graf <tgraf@suug.ch>
> Date: Thu, 26 May 2005 20:55:26 +0200
>
> > This message is followed by 0..n messages carrying device
> > specific parameter sets. They all share the same value for
> > Although the ordering should be sufficient, NDTA_NAME can be
>
> It seems a sentence is chopped off here mid-stream,
> please provide a fixed changelog so I can apply your
> patches.
Sorry, it's what happens if one gets interrupted in the middle
of writing a longer comment. ;-> Patch edited by hand but
it should still apply.
^ permalink raw reply
* [PATCH 3/4] [NEIGH] neighbour table configuration and statistics via rtnetlink
From: Thomas Graf @ 2005-05-26 22:24 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev
In-Reply-To: <20050526.151726.85409972.davem@davemloft.net>
To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
NLM_F_DUMP flag set. Every neighbour table configuration is
spread over multiple messages to avoid running into message
size limits on systems with many interfaces. The first message
in the sequence transports all not device specific data such as
statistics, configuration, and the default parameter set.
This message is followed by 0..n messages carrying device
specific parameter sets.
Although the ordering should be sufficient, NDTA_NAME can be
used to identify sequences. The initial message can be identified
by checking for NDTA_CONFIG. The device specific messages do
not contain this TLV but have NDTPA_IFINDEX set to the
corresponding interface index.
To change neighbour table attributes, send RTM_SETNEIGHTBL
with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
otherwise. Device specific parameter sets can be changed by
setting NDTPA_IFINDEX to the interface index of the corresponding
device.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
commit 6769b3b0603c632bda062e427178de8986900a52
tree 7e955d0e3c8fdef048336d0d7ba24a0539f28f9b
parent 98c3bc2e6320127cd96ef46d33f89ae127ce48fe
author Thomas Graf <tgraf@suug.ch> Wed, 25 May 2005 20:30:09 +0200
committer Thomas Graf <tgraf@suug.ch> Wed, 25 May 2005 20:30:09 +0200
include/linux/rtnetlink.h | 107 ++++++++++++++
include/net/neighbour.h | 4
net/core/neighbour.c | 317 +++++++++++++++++++++++++++++++++++++++++++-
net/core/rtnetlink.c | 20 +-
security/selinux/nlmsgtab.c | 2
5 files changed, 439 insertions(+), 11 deletions(-)
Index: include/linux/rtnetlink.h
===================================================================
--- 0ad944fa24c79b3eeaf06f85f5dd6d91ae1adbc9/include/linux/rtnetlink.h (mode:100644)
+++ 7e955d0e3c8fdef048336d0d7ba24a0539f28f9b/include/linux/rtnetlink.h (mode:100644)
@@ -89,6 +89,13 @@
RTM_GETANYCAST = 62,
#define RTM_GETANYCAST RTM_GETANYCAST
+ RTM_NEWNEIGHTBL = 64,
+#define RTM_NEWNEIGHTBL RTM_NEWNEIGHTBL
+ RTM_GETNEIGHTBL = 66,
+#define RTM_GETNEIGHTBL RTM_GETNEIGHTBL
+ RTM_SETNEIGHTBL,
+#define RTM_SETNEIGHTBL RTM_SETNEIGHTBL
+
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@@ -493,6 +500,106 @@
__u32 ndm_refcnt;
};
+
+/*****************************************************************
+ * Neighbour tables specific messages.
+ *
+ * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
+ * NLM_F_DUMP flag set. Every neighbour table configuration is
+ * spread over multiple messages to avoid running into message
+ * size limits on systems with many interfaces. The first message
+ * in the sequence transports all not device specific data such as
+ * statistics, configuration, and the default parameter set.
+ * This message is followed by 0..n messages carrying device
+ * specific parameter sets.
+ * Although the ordering should be sufficient, NDTA_NAME can be
+ * used to identify sequences. The initial message can be identified
+ * by checking for NDTA_CONFIG. The device specific messages do
+ * not contain this TLV but have NDTPA_IFINDEX set to the
+ * corresponding interface index.
+ *
+ * To change neighbour table attributes, send RTM_SETNEIGHTBL
+ * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
+ * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
+ * otherwise. Device specific parameter sets can be changed by
+ * setting NDTPA_IFINDEX to the interface index of the corresponding
+ * device.
+ ****/
+
+struct ndt_stats
+{
+ __u64 ndts_allocs;
+ __u64 ndts_destroys;
+ __u64 ndts_hash_grows;
+ __u64 ndts_res_failed;
+ __u64 ndts_lookups;
+ __u64 ndts_hits;
+ __u64 ndts_rcv_probes_mcast;
+ __u64 ndts_rcv_probes_ucast;
+ __u64 ndts_periodic_gc_runs;
+ __u64 ndts_forced_gc_runs;
+};
+
+enum {
+ NDTPA_UNSPEC,
+ NDTPA_IFINDEX, /* u32, unchangeable */
+ NDTPA_REFCNT, /* u32, read-only */
+ NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */
+ NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */
+ NDTPA_RETRANS_TIME, /* u64, msecs */
+ NDTPA_GC_STALETIME, /* u64, msecs */
+ NDTPA_DELAY_PROBE_TIME, /* u64, msecs */
+ NDTPA_QUEUE_LEN, /* u32 */
+ NDTPA_APP_PROBES, /* u32 */
+ NDTPA_UCAST_PROBES, /* u32 */
+ NDTPA_MCAST_PROBES, /* u32 */
+ NDTPA_ANYCAST_DELAY, /* u64, msecs */
+ NDTPA_PROXY_DELAY, /* u64, msecs */
+ NDTPA_PROXY_QLEN, /* u32 */
+ NDTPA_LOCKTIME, /* u64, msecs */
+ __NDTPA_MAX
+};
+#define NDTPA_MAX (__NDTPA_MAX - 1)
+
+struct ndtmsg
+{
+ __u8 ndtm_family;
+ __u8 ndtm_pad1;
+ __u16 ndtm_pad2;
+};
+
+struct ndt_config
+{
+ __u16 ndtc_key_len;
+ __u16 ndtc_entry_size;
+ __u32 ndtc_entries;
+ __u32 ndtc_last_flush; /* delta to now in msecs */
+ __u32 ndtc_last_rand; /* delta to now in msecs */
+ __u32 ndtc_hash_rnd;
+ __u32 ndtc_hash_mask;
+ __u32 ndtc_hash_chain_gc;
+ __u32 ndtc_proxy_qlen;
+};
+
+enum {
+ NDTA_UNSPEC,
+ NDTA_NAME, /* char *, unchangeable */
+ NDTA_THRESH1, /* u32 */
+ NDTA_THRESH2, /* u32 */
+ NDTA_THRESH3, /* u32 */
+ NDTA_CONFIG, /* struct ndt_config, read-only */
+ NDTA_PARMS, /* nested TLV NDTPA_* */
+ NDTA_STATS, /* struct ndt_stats, read-only */
+ NDTA_GC_INTERVAL, /* u64, msecs */
+ __NDTA_MAX
+};
+#define NDTA_MAX (__NDTA_MAX - 1)
+
+#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \
+ NLMSG_ALIGN(sizeof(struct ndtmsg))))
+#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
+
+
/****
* General form of address family dependent message.
****/
Index: include/net/neighbour.h
===================================================================
--- 0ad944fa24c79b3eeaf06f85f5dd6d91ae1adbc9/include/net/neighbour.h (mode:100644)
+++ 7e955d0e3c8fdef048336d0d7ba24a0539f28f9b/include/net/neighbour.h (mode:100644)
@@ -65,6 +65,7 @@
struct neigh_parms
{
+ struct net_device *dev;
struct neigh_parms *next;
int (*neigh_setup)(struct neighbour *);
struct neigh_table *tbl;
@@ -252,6 +253,9 @@
extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern void neigh_app_ns(struct neighbour *n);
+extern int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb);
+extern int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+
extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
Index: net/core/neighbour.c
===================================================================
--- 0ad944fa24c79b3eeaf06f85f5dd6d91ae1adbc9/net/core/neighbour.c (mode:100644)
+++ 7e955d0e3c8fdef048336d0d7ba24a0539f28f9b/net/core/neighbour.c (mode:100644)
@@ -1276,9 +1276,14 @@
INIT_RCU_HEAD(&p->rcu_head);
p->reachable_time =
neigh_rand_reach_time(p->base_reachable_time);
- if (dev && dev->neigh_setup && dev->neigh_setup(dev, p)) {
- kfree(p);
- return NULL;
+ if (dev) {
+ if (dev->neigh_setup && dev->neigh_setup(dev, p)) {
+ kfree(p);
+ return NULL;
+ }
+
+ dev_hold(dev);
+ p->dev = dev;
}
p->sysctl_table = NULL;
write_lock_bh(&tbl->lock);
@@ -1309,6 +1314,8 @@
*p = parms->next;
parms->dead = 1;
write_unlock_bh(&tbl->lock);
+ if (parms->dev)
+ dev_put(parms->dev);
call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
return;
}
@@ -1546,6 +1553,308 @@
return err;
}
+static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
+{
+ struct rtattr *nest = RTA_NEST(skb, NDTA_PARMS);
+
+ if (parms->dev)
+ RTA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex);
+
+ RTA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt));
+ RTA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len);
+ RTA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen);
+ RTA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes);
+ RTA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes);
+ RTA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes);
+ RTA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time);
+ RTA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME,
+ parms->base_reachable_time);
+ RTA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime);
+ RTA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time);
+ RTA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time);
+ RTA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay);
+ RTA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay);
+ RTA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime);
+
+ return RTA_NEST_END(skb, nest);
+
+rtattr_failure:
+ return RTA_NEST_CANCEL(skb, nest);
+}
+
+static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct nlmsghdr *nlh;
+ struct ndtmsg *ndtmsg;
+
+ nlh = NLMSG_PUT_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg));
+ ndtmsg = NLMSG_DATA(nlh);
+
+ NLMSG_SET_MULTIPART(nlh);
+
+ read_lock_bh(&tbl->lock);
+ ndtmsg->ndtm_family = tbl->family;
+
+ RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
+ RTA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval);
+ RTA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1);
+ RTA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2);
+ RTA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3);
+
+ {
+ unsigned long now = jiffies;
+ unsigned int flush_delta = now - tbl->last_flush;
+ unsigned int rand_delta = now - tbl->last_rand;
+
+ struct ndt_config ndc = {
+ .ndtc_key_len = tbl->key_len,
+ .ndtc_entry_size = tbl->entry_size,
+ .ndtc_entries = atomic_read(&tbl->entries),
+ .ndtc_last_flush = jiffies_to_msecs(flush_delta),
+ .ndtc_last_rand = jiffies_to_msecs(rand_delta),
+ .ndtc_hash_rnd = tbl->hash_rnd,
+ .ndtc_hash_mask = tbl->hash_mask,
+ .ndtc_hash_chain_gc = tbl->hash_chain_gc,
+ .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
+ };
+
+ RTA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
+ }
+
+ {
+ int cpu;
+ struct ndt_stats ndst;
+
+ memset(&ndst, 0, sizeof(ndst));
+
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ struct neigh_statistics *st;
+
+ if (!cpu_possible(cpu))
+ continue;
+
+ st = per_cpu_ptr(tbl->stats, cpu);
+ ndst.ndts_allocs += st->allocs;
+ ndst.ndts_destroys += st->destroys;
+ ndst.ndts_hash_grows += st->hash_grows;
+ ndst.ndts_res_failed += st->res_failed;
+ ndst.ndts_lookups += st->lookups;
+ ndst.ndts_hits += st->hits;
+ ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
+ ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
+ ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
+ ndst.ndts_forced_gc_runs += st->forced_gc_runs;
+ }
+
+ RTA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst);
+ }
+
+ BUG_ON(tbl->parms.dev);
+ if (neightbl_fill_parms(skb, &tbl->parms) < 0)
+ goto rtattr_failure;
+
+ read_unlock_bh(&tbl->lock);
+ return NLMSG_END(skb, nlh);
+
+rtattr_failure:
+ read_unlock_bh(&tbl->lock);
+ return NLMSG_CANCEL(skb, nlh);
+
+nlmsg_failure:
+ return -1;
+}
+
+static int neightbl_fill_param_info(struct neigh_table *tbl,
+ struct neigh_parms *parms,
+ struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct ndtmsg *ndtmsg;
+ struct nlmsghdr *nlh;
+
+ nlh = NLMSG_PUT_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg));
+ ndtmsg = NLMSG_DATA(nlh);
+
+ NLMSG_SET_MULTIPART(nlh);
+
+ read_lock_bh(&tbl->lock);
+ ndtmsg->ndtm_family = tbl->family;
+ RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
+
+ if (neightbl_fill_parms(skb, parms) < 0)
+ goto rtattr_failure;
+
+ read_unlock_bh(&tbl->lock);
+ return NLMSG_END(skb, nlh);
+
+rtattr_failure:
+ read_unlock_bh(&tbl->lock);
+ return NLMSG_CANCEL(skb, nlh);
+
+nlmsg_failure:
+ return -1;
+}
+
+static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
+ int ifindex)
+{
+ struct neigh_parms *p;
+
+ for (p = &tbl->parms; p; p = p->next)
+ if ((p->dev && p->dev->ifindex == ifindex) ||
+ (!p->dev && !ifindex))
+ return p;
+
+ return NULL;
+}
+
+int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct neigh_table *tbl;
+ struct ndtmsg *ndtmsg = NLMSG_DATA(nlh);
+ struct rtattr **tb = arg;
+ int err = -EINVAL;
+
+ if (!tb[NDTA_NAME - 1] || !RTA_PAYLOAD(tb[NDTA_NAME - 1]))
+ return -EINVAL;
+
+ read_lock(&neigh_tbl_lock);
+ for (tbl = neigh_tables; tbl; tbl = tbl->next) {
+ if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
+ continue;
+
+ if (!rtattr_strcmp(tb[NDTA_NAME - 1], tbl->id))
+ break;
+ }
+
+ if (tbl == NULL) {
+ err = -ENOENT;
+ goto errout;
+ }
+
+ /*
+ * We acquire tbl->lock to be nice to the periodic timers and
+ * make sure they always see a consistent set of values.
+ */
+ write_lock_bh(&tbl->lock);
+
+ if (tb[NDTA_THRESH1 - 1])
+ tbl->gc_thresh1 = RTA_GET_U32(tb[NDTA_THRESH1 - 1]);
+
+ if (tb[NDTA_THRESH2 - 1])
+ tbl->gc_thresh2 = RTA_GET_U32(tb[NDTA_THRESH2 - 1]);
+
+ if (tb[NDTA_THRESH3 - 1])
+ tbl->gc_thresh3 = RTA_GET_U32(tb[NDTA_THRESH3 - 1]);
+
+ if (tb[NDTA_GC_INTERVAL - 1])
+ tbl->gc_interval = RTA_GET_MSECS(tb[NDTA_GC_INTERVAL - 1]);
+
+ if (tb[NDTA_PARMS - 1]) {
+ struct rtattr *tbp[NDTPA_MAX];
+ struct neigh_parms *p;
+ u32 ifindex = 0;
+
+ if (rtattr_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS - 1]) < 0)
+ goto rtattr_failure;
+
+ if (tbp[NDTPA_IFINDEX - 1])
+ ifindex = RTA_GET_U32(tbp[NDTPA_IFINDEX - 1]);
+
+ p = lookup_neigh_params(tbl, ifindex);
+ if (p == NULL) {
+ err = -ENOENT;
+ goto rtattr_failure;
+ }
+
+ if (tbp[NDTPA_QUEUE_LEN - 1])
+ p->queue_len = RTA_GET_U32(tbp[NDTPA_QUEUE_LEN - 1]);
+
+ if (tbp[NDTPA_PROXY_QLEN - 1])
+ p->proxy_qlen = RTA_GET_U32(tbp[NDTPA_PROXY_QLEN - 1]);
+
+ if (tbp[NDTPA_APP_PROBES - 1])
+ p->app_probes = RTA_GET_U32(tbp[NDTPA_APP_PROBES - 1]);
+
+ if (tbp[NDTPA_UCAST_PROBES - 1])
+ p->ucast_probes =
+ RTA_GET_U32(tbp[NDTPA_UCAST_PROBES - 1]);
+
+ if (tbp[NDTPA_MCAST_PROBES - 1])
+ p->mcast_probes =
+ RTA_GET_U32(tbp[NDTPA_MCAST_PROBES - 1]);
+
+ if (tbp[NDTPA_BASE_REACHABLE_TIME - 1])
+ p->base_reachable_time =
+ RTA_GET_MSECS(tbp[NDTPA_BASE_REACHABLE_TIME - 1]);
+
+ if (tbp[NDTPA_GC_STALETIME - 1])
+ p->gc_staletime =
+ RTA_GET_MSECS(tbp[NDTPA_GC_STALETIME - 1]);
+
+ if (tbp[NDTPA_DELAY_PROBE_TIME - 1])
+ p->delay_probe_time =
+ RTA_GET_MSECS(tbp[NDTPA_DELAY_PROBE_TIME - 1]);
+
+ if (tbp[NDTPA_RETRANS_TIME - 1])
+ p->retrans_time =
+ RTA_GET_MSECS(tbp[NDTPA_RETRANS_TIME - 1]);
+
+ if (tbp[NDTPA_ANYCAST_DELAY - 1])
+ p->anycast_delay =
+ RTA_GET_MSECS(tbp[NDTPA_ANYCAST_DELAY - 1]);
+
+ if (tbp[NDTPA_PROXY_DELAY - 1])
+ p->proxy_delay =
+ RTA_GET_MSECS(tbp[NDTPA_PROXY_DELAY - 1]);
+
+ if (tbp[NDTPA_LOCKTIME - 1])
+ p->locktime = RTA_GET_MSECS(tbp[NDTPA_LOCKTIME - 1]);
+ }
+
+ err = 0;
+
+rtattr_failure:
+ write_unlock_bh(&tbl->lock);
+errout:
+ read_unlock(&neigh_tbl_lock);
+ return err;
+}
+
+int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx, family;
+ int s_idx = cb->args[0];
+ struct neigh_table *tbl;
+
+ family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family;
+
+ read_lock(&neigh_tbl_lock);
+ for (tbl = neigh_tables, idx = 0; tbl; tbl = tbl->next) {
+ struct neigh_parms *p;
+
+ if (idx < s_idx || (family && tbl->family != family))
+ continue;
+
+ if (neightbl_fill_info(tbl, skb, cb) <= 0)
+ break;
+
+ for (++idx, p = tbl->parms.next; p; p = p->next, idx++) {
+ if (idx < s_idx)
+ continue;
+
+ if (neightbl_fill_param_info(tbl, p, skb, cb) <= 0)
+ goto out;
+ }
+
+ }
+out:
+ read_unlock(&neigh_tbl_lock);
+ cb->args[0] = idx;
+
+ return skb->len;
+}
static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
u32 pid, u32 seq, int event)
@@ -2352,6 +2661,8 @@
EXPORT_SYMBOL(neigh_update_hhs);
EXPORT_SYMBOL(pneigh_enqueue);
EXPORT_SYMBOL(pneigh_lookup);
+EXPORT_SYMBOL(neightbl_dump_info);
+EXPORT_SYMBOL(neightbl_set);
#ifdef CONFIG_ARPD
EXPORT_SYMBOL(neigh_app_ns);
Index: net/core/rtnetlink.c
===================================================================
--- 0ad944fa24c79b3eeaf06f85f5dd6d91ae1adbc9/net/core/rtnetlink.c (mode:100644)
+++ 7e955d0e3c8fdef048336d0d7ba24a0539f28f9b/net/core/rtnetlink.c (mode:100644)
@@ -100,6 +100,7 @@
[RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
[RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
[RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
+ [RTM_FAM(RTM_NEWNEIGHTBL)] = NLMSG_LENGTH(sizeof(struct ndtmsg)),
};
static const int rta_max[RTM_NR_FAMILIES] =
@@ -113,6 +114,7 @@
[RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX,
[RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX,
[RTM_FAM(RTM_NEWACTION)] = TCAA_MAX,
+ [RTM_FAM(RTM_NEWNEIGHTBL)] = NDTA_MAX,
};
void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
@@ -649,14 +651,16 @@
static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
{
- [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
- [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
- [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
- [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
- [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add },
- [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete },
- [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info },
- [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
+ [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
+ [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add },
+ [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete },
+ [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info },
+ [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info },
+ [RTM_SETNEIGHTBL - RTM_BASE] = { .doit = neightbl_set },
};
static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
Index: security/selinux/nlmsgtab.c
===================================================================
--- 0ad944fa24c79b3eeaf06f85f5dd6d91ae1adbc9/security/selinux/nlmsgtab.c (mode:100644)
+++ 7e955d0e3c8fdef048336d0d7ba24a0539f28f9b/security/selinux/nlmsgtab.c (mode:100644)
@@ -63,6 +63,8 @@
{ RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
+ { RTM_GETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_READ },
+ { RTM_SETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
};
static struct nlmsg_perm nlmsg_firewall_perms[] =
^ permalink raw reply
* Re: [PATCH 3/4] [NEIGH] neighbour table configuration and statistics via rtnetlink
From: David S. Miller @ 2005-05-26 22:17 UTC (permalink / raw)
To: tgraf; +Cc: netdev
In-Reply-To: <20050526185526.GZ15391@postel.suug.ch>
From: Thomas Graf <tgraf@suug.ch>
Date: Thu, 26 May 2005 20:55:26 +0200
> This message is followed by 0..n messages carrying device
> specific parameter sets. They all share the same value for
> Although the ordering should be sufficient, NDTA_NAME can be
It seems a sentence is chopped off here mid-stream,
please provide a fixed changelog so I can apply your
patches.
Thanks.
^ permalink raw reply
* Re: [PATCH] : bug fix in multipath drr code.
From: David S. Miller @ 2005-05-26 22:13 UTC (permalink / raw)
To: pravins; +Cc: herbert, netdev
In-Reply-To: <4292FA7C.80308@calsoftinc.com>
From: pravin b shelar <pravins@calsoftinc.com>
Date: Tue, 24 May 2005 15:27:16 +0530
> So I think we should ignore MULTIPATHOLDROUTE flag
> in drr and rr multipath algorithms as done in random multipath algorithm.
>
> Attached patch does same thing.
I've applied this patch, thanks.
^ permalink raw reply
* Re: [PATCH 2.6.12-rc5 9/9] tg3: Fix bug in tg3_load_firmware_cpu
From: David S. Miller @ 2005-05-26 22:10 UTC (permalink / raw)
To: mchan; +Cc: jgarzik, netdev
In-Reply-To: <1117130411.3744.61.camel@rh4>
All 9 patches applied, thanks Michael.
^ permalink raw reply
* Re: primary and secondary ip addresses
From: David S. Miller @ 2005-05-26 21:58 UTC (permalink / raw)
To: laforge; +Cc: hasso, netdev
In-Reply-To: <20050526181118.GK13114@sunbeam.de.gnumonks.org>
From: Harald Welte <laforge@gnumonks.org>
Date: Thu, 26 May 2005 20:11:18 +0200
> David, would you consider applying that patch to mainline? I think
> there was concensus on this solution, and it has now received some
> amount of testing by Hasso and me.
Since it retains the default behavior by default, this change
seems fine. I've added it to my tree, thanks.
^ permalink raw reply
* Re: [PATCH] (6/6) bridge: receive path optimization
From: David S. Miller @ 2005-05-26 21:46 UTC (permalink / raw)
To: shemminger; +Cc: bridge, netdev
In-Reply-To: <20050526110425.27590eb8@dxpl.pdx.osdl.net>
From: Stephen Hemminger <shemminger@osdl.org>
Date: Thu, 26 May 2005 11:04:25 -0700
> This improves the bridge local receive path by avoiding going
> through another softirq. The bridge receive path is already being called
> from a netif_receive_skb() there is no point in going through another
> receiveq round trip.
>
> Recursion is limited because bridge can never be a port of a bridge
> so handle_bridge() always returns.
I applied all 6 patches, but this one in particular I'd like
to comment on.
Remember all of those bridge netfilter stack usage issues
we have a few months ago? This could edge us back into
those problems again.
^ permalink raw reply
* Re: [PATCH 2.6] fix deadlock with ip_queue and tcp local input path
From: Herbert Xu @ 2005-05-26 21:38 UTC (permalink / raw)
To: Harald Welte; +Cc: netdev, netfilter-devel
In-Reply-To: <20050526142420.GD13114@sunbeam.de.gnumonks.org>
Harald Welte <laforge@netfilter.org> wrote:
>
> The patch below adds an additional queue for ip_queue verdicts. They
> come up from userspace, are appended to a queue which is then processed
> by a tasklet. The tasklet itself runs in softirq context, so when timer
> hardirq leaves, no tcp_delack_timer() will be executed until
> nf_reinject() has finished.
This seems to be overly complicated if all you want is to do this in
softirq context. What's wrong with simply alling local_bh_disable?
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* RFC: NAPI packet weighting patch
From: Mitch Williams @ 2005-05-26 21:36 UTC (permalink / raw)
To: netdev; +Cc: john.ronciak, ganesh.venkatesan, jesse.brandeburg
The following patch (which applies to 2.6.12rc4) adds a new sysctl
parameter called 'netdev_packet_weight'. This parameter controls how many
backlog work units each RX packet is worth.
With the parameter set to 0 (the default), NAPI polling works exactly as
it does today: each packet is worth one backlog work unit, and the
maximum number of received packets that will be processed in any given
softirq is controlled by the 'netdev_max_backlog' parameter.
By setting the netdev_packet_weight to a nonzero value, we make each
packet worth more than one backlog work unit. Since it's a shift value, a
setting of 1 makes each packet worth 2 work units, a setting of 2 makes
each packet worth 4 units, etc. Under normal circumstances you would
never use a value higher than 3, though 4 might work for Gigabit and 10
Gigabit networks.
By increasing the packet weight, we accomplish two things: first, we
cause the individual NAPI RX loops in each driver to process fewer
packets. This means that they will free up RX resources to the hardware
more often, which reduces the possibility of dropped packets. Second, it
shortens the total time spent in the NAPI softirq, which can free the CPU
to handle other tasks more often, thus reducing overall latency.
Performance tests in our lab have shown that tweaking this parameter,
along with the netdev_max_backlog parameter, can provide significant
performance increase -- greater than 100Mbps improvement -- over default
settings. I tested with both e1000 and tg3 drivers and saw improvement in
both cases. I did not see higher CPU utilization, even with the increased
throughput.
The caveat, of course, is that different systems and network
configurations require different settings. On the other hand, that's
really no different than what we see with the max_backlog parameter today.
On some systems neither parameter makes any difference.
Still, we feel that there is value to having this in the kernel. Please
test and comment as you have time available.
Thanks!
-Mitch Williams
mitch.a.williams@intel.com
diff -urpN -x dontdiff rc4-clean/Documentation/filesystems/proc.txt linux-2.6.12-rc4/Documentation/filesystems/proc.txt
--- rc4-clean/Documentation/filesystems/proc.txt 2005-05-18 16:35:43.000000000 -0700
+++ linux-2.6.12-rc4/Documentation/filesystems/proc.txt 2005-05-19 11:16:10.000000000 -0700
@@ -1378,7 +1378,13 @@ netdev_max_backlog
------------------
Maximum number of packets, queued on the INPUT side, when the interface
-receives packets faster than kernel can process them.
+receives packets faster than kernel can process them. This is also the
+maximum number of packets handled in a single softirq under NAPI.
+
+netdev_packet_weight
+--------------------
+The value, in netdev_max_backlog unit, of each received packet. This is a
+shift value, and should be set no higher than 3.
optmem_max
----------
diff -urpN -x dontdiff rc4-clean/include/linux/sysctl.h linux-2.6.12-rc4/include/linux/sysctl.h
--- rc4-clean/include/linux/sysctl.h 2005-05-18 16:36:06.000000000 -0700
+++ linux-2.6.12-rc4/include/linux/sysctl.h 2005-05-18 16:44:07.000000000 -0700
@@ -242,6 +242,7 @@ enum
NET_CORE_MOD_CONG=16,
NET_CORE_DEV_WEIGHT=17,
NET_CORE_SOMAXCONN=18,
+ NET_CORE_PACKET_WEIGHT=19,
};
/* /proc/sys/net/ethernet */
diff -urpN -x dontdiff rc4-clean/net/core/dev.c linux-2.6.12-rc4/net/core/dev.c
--- rc4-clean/net/core/dev.c 2005-05-18 16:36:07.000000000 -0700
+++ linux-2.6.12-rc4/net/core/dev.c 2005-05-19 11:16:57.000000000 -0700
@@ -1352,6 +1352,7 @@ out:
=======================================================================*/
int netdev_max_backlog = 300;
+int netdev_packet_weight = 0; /* each packet is worth 1 backlog unit */
int weight_p = 64; /* old backlog weight */
/* These numbers are selected based on intuition and some
* experimentatiom, if you have more scientific way of doing this
@@ -1778,6 +1779,7 @@ static void net_rx_action(struct softirq
struct softnet_data *queue = &__get_cpu_var(softnet_data);
unsigned long start_time = jiffies;
int budget = netdev_max_backlog;
+ int budget_temp;
local_irq_disable();
@@ -1793,21 +1795,22 @@ static void net_rx_action(struct softirq
dev = list_entry(queue->poll_list.next,
struct net_device, poll_list);
netpoll_poll_lock(dev);
-
- if (dev->quota <= 0 || dev->poll(dev, &budget)) {
+ budget_temp = budget;
+ if (dev->quota <= 0 || dev->poll(dev, &budget_temp)) {
netpoll_poll_unlock(dev);
local_irq_disable();
list_del(&dev->poll_list);
list_add_tail(&dev->poll_list, &queue->poll_list);
if (dev->quota < 0)
- dev->quota += dev->weight;
+ dev->quota += dev->weight >> netdev_packet_weight;
else
- dev->quota = dev->weight;
+ dev->quota = dev->weight >> netdev_packet_weight;
} else {
netpoll_poll_unlock(dev);
dev_put(dev);
local_irq_disable();
}
+ budget -= (budget - budget_temp) << netdev_packet_weight;
}
out:
local_irq_enable();
diff -urpN -x dontdiff rc4-clean/net/core/sysctl_net_core.c linux-2.6.12-rc4/net/core/sysctl_net_core.c
--- rc4-clean/net/core/sysctl_net_core.c 2005-03-01 23:38:03.000000000 -0800
+++ linux-2.6.12-rc4/net/core/sysctl_net_core.c 2005-05-18 16:44:09.000000000 -0700
@@ -13,6 +13,7 @@
#ifdef CONFIG_SYSCTL
extern int netdev_max_backlog;
+extern int netdev_packet_weight;
extern int weight_p;
extern int no_cong_thresh;
extern int no_cong;
@@ -91,6 +92,14 @@ ctl_table core_table[] = {
.proc_handler = &proc_dointvec
},
{
+ .ctl_name = NET_CORE_PACKET_WEIGHT,
+ .procname = "netdev_packet_weight",
+ .data = &netdev_packet_weight,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+ },
+ {
.ctl_name = NET_CORE_MAX_BACKLOG,
.procname = "netdev_max_backlog",
.data = &netdev_max_backlog,
^ permalink raw reply
* Re: Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Herbert Xu @ 2005-05-26 21:34 UTC (permalink / raw)
To: Venkatesan, Ganesh
Cc: Andrew Morton, Jian Jun He, anton, rende, ganesh.venkatesan,
Brandeburg, Jesse, jgarzik, wangjs, Ronciak, John, cdlwangl,
linuxppc64-dev, netdev
In-Reply-To: <468F3FDA28AA87429AD807992E22D07E056F6B37@orsmsx408>
On Thu, May 26, 2005 at 01:41:53PM -0700, Venkatesan, Ganesh wrote:
>
> I already responded to this analysis before. In any case, here it is:
>
> Later versions of e100 (3.4.8 for instance) includes a call to
> netif_poll_disable in e100_down. This is supposed to wait and when it
As I said last time, this is broken since the code path in question
starts from tx_timeout which is called in softirq context. You'll
need to schedule a work struct at least.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH 2.6] fix deadlock with ip_queue and tcp local input path
From: David S. Miller @ 2005-05-26 21:01 UTC (permalink / raw)
To: laforge; +Cc: netdev, netfilter-devel
In-Reply-To: <20050526205831.GL13114@sunbeam.de.gnumonks.org>
From: Harald Welte <laforge@netfilter.org>
Subject: Re: [PATCH 2.6] fix deadlock with ip_queue and tcp local input path
Date: Thu, 26 May 2005 22:58:31 +0200
> On Thu, May 26, 2005 at 01:52:29PM -0700, David S. Miller wrote:
>
> > > Dave: Please don't apply yet, I want to receive feedback from the
> > > netfilter developers first. I'm just Cc'ing netdev in case somebody
> > > wants an intermediate fix to fix the problem.
> >
> > OK.
>
> Do you have any feedback on why or how bh_lock_sock() might be called in
> the problem I've described? I think it has to be a different skb for
> the same socket.
When we hit a listening socket, and hung off of that listening
socket we find a child socket, we bh_lock_sock() the child socket
then process the SKB against it instead of the listening socket.
Is this the kind of scenerio you are concerned about?
^ permalink raw reply
* Re: [PATCH 2.6] fix deadlock with ip_queue and tcp local input path
From: Harald Welte @ 2005-05-26 20:58 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, netfilter-devel
In-Reply-To: <20050526.135229.111208218.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 937 bytes --]
On Thu, May 26, 2005 at 01:52:29PM -0700, David S. Miller wrote:
> > Dave: Please don't apply yet, I want to receive feedback from the
> > netfilter developers first. I'm just Cc'ing netdev in case somebody
> > wants an intermediate fix to fix the problem.
>
> OK.
Do you have any feedback on why or how bh_lock_sock() might be called in
the problem I've described? I think it has to be a different skb for
the same socket.
Is my general line of thought correct that we shouldn't traverse the
local input path from sysirq context ?
Thanks.
--
- Harald Welte <laforge@netfilter.org> http://netfilter.org/
============================================================================
"Fragmentation is like classful addressing -- an interesting early
architectural error that shows how much experimentation was going
on while IP was being designed." -- Paul Vixie
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 2.6] fix deadlock with ip_queue and tcp local input path
From: David S. Miller @ 2005-05-26 20:52 UTC (permalink / raw)
To: laforge; +Cc: netdev, netfilter-devel
In-Reply-To: <20050526142420.GD13114@sunbeam.de.gnumonks.org>
From: Harald Welte <laforge@netfilter.org>
Date: Thu, 26 May 2005 16:24:21 +0200
> Dave: Please don't apply yet, I want to receive feedback from the
> netfilter developers first. I'm just Cc'ing netdev in case somebody
> wants an intermediate fix to fix the problem.
OK.
^ permalink raw reply
* RE: Fw: [Bugme-new] [Bug 4628] New: Test server hang while running rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
From: Venkatesan, Ganesh @ 2005-05-26 20:41 UTC (permalink / raw)
To: Andrew Morton, Jian Jun He
Cc: anton, rende, ganesh.venkatesan, herbert, Brandeburg, Jesse,
jgarzik, wangjs, Ronciak, John, cdlwangl, linuxppc64-dev, netdev
Andrew:
I already responded to this analysis before. In any case, here it is:
Later versions of e100 (3.4.8 for instance) includes a call to
netif_poll_disable in e100_down. This is supposed to wait and when it
returns we are guaranteed that e100_poll will no longer be called. In
addition, if there happens to be an interrupt, our call to
netif_rx_schedule() will not add our poll routine to the poll-list since
poll is disabled. So this race can never happen.
Ganesh.
>-----Original Message-----
>From: Andrew Morton [mailto:akpm@osdl.org]
>Sent: Thursday, May 26, 2005 1:31 PM
>To: Jian Jun He
>Cc: Venkatesan, Ganesh; anton@samba.org; rende@cn.ibm.com;
>ganesh.venkatesan@gmail.com; herbert@gondor.apana.org.au; Brandeburg,
>Jesse; jgarzik@pobox.com; wangjs@cn.ibm.com; Ronciak, John;
>cdlwangl@cn.ibm.com; linuxppc64-dev@lists.linuxppc.org.sgi.com;
>netdev@oss.sgi.com
>Subject: Re: Fw: [Bugme-new] [Bug 4628] New: Test server hang while
running
>rhr (network) test on RHEL4 with kernel 2.6.12-rc1-mm4
>
>Jian Jun He <hejianj@cn.ibm.com> wrote:
>>
>> 2. Download rhr2-rhel4-1.0-14a.noarch.rpm from rhn.redhat.com and
>install
>> it on
>> the test machine.
>> 3. Configure and run the rhr test via invoking redhat-ready.
>
>This is the problematic bit.
>
>- Please provide a full URL which can be used to obtain rhr.
> rhn.redhat.com is subscription-based.
>
>- Please describe the hardware setup - surely the test requires at
least
> two machines. How are they configured?
>
>- Provide an exact transcript of the commands which are to be used. Is
> it just
>
> redhat-ready
>
> with no arguments?
>
>
>
>All that begin said, we already have a quite specific diagnosis via
code
>inspection, from Herbert:
>
>
>Herbert Xu <herbert@gondor.apana.org.au> wrote:
>>
>> Andrew Morton <akpm@osdl.org> wrote:
>> >
>> > Might be a bug in the e100 driver, might not be.
>> >
>> > I assume this is the
>> >
>> > BUG_ON(skb->list != NULL);
>>
>> It certainly is a bug in e100.
>>
>> e100_tx_timeout -> e100_down -> e100_rx_clean_list
>>
>> is racing against
>>
>> e100_poll -> e100_rx_clean -> e100_rx_indicate
>>
>> e100_rx_clean/e100_rx_indicate takes an skb off the RX ring and
>> while it's being processed e100_rx_clean_list comes along and
>> frees it.
>>
>> From a quick check similar problems may exist in other drivers that
>> have lockless ->poll() functions with RX rings.
>
>Do the e100 maintainers agree with this diagnosis? If so then more
testing
>isn't required at this stage - the next step is to fix the above bug,
no?
^ permalink raw reply
* Re: LC-trie FIB major rework
From: David S. Miller @ 2005-05-26 20:38 UTC (permalink / raw)
To: Robert.Olsson; +Cc: netdev
In-Reply-To: <17045.56331.653873.256686@robur.slu.se>
From: Robert Olsson <Robert.Olsson@data.slu.se>
Date: Thu, 26 May 2005 16:24:11 +0200
> Below much reworked version of the LC-trie for FIB lookup's. Much closer
> to current FIB anatomy and locking. Parent pointers in the trie to avoid
> own stacks etc. The option to merge tables has been removed and much things
> to keep things as simple and clean as possible. Although it's somewhat
> complex.
>
> Performance. We now perform about 25-30% better than current FIB in
> heavy lookup situations (we test with full rDoS) The test below illustrates
> this 123 kroutes in the routing table and rDoS is injected into eth0 at
> 720 kpps routed traffic on eth1/eth3. route hash is not used and both
> dst and src are looked up. LC-trie should work fine any size of routing table..
Very nice work Robert. Once TSO becomes less of a time sink I
intend to help you out a bit.
^ permalink raw reply
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