* Re: e1000 full-duplex TCP performance well below wire speed
From: Kok, Auke @ 2008-01-31 18:08 UTC (permalink / raw)
To: Bruce Allen
Cc: Brandeburg, Jesse, netdev, Carsten Aulbert, Henning Fehrmann,
Bruce Allen
In-Reply-To: <Pine.LNX.4.63.0801310213010.3240@trinity.phys.uwm.edu>
Bruce Allen wrote:
> Hi Jesse,
>
>>> It's good to be talking directly to one of the e1000 developers and
>>> maintainers. Although at this point I am starting to think that the
>>> issue may be TCP stack related and nothing to do with the NIC. Am I
>>> correct that these are quite distinct parts of the kernel?
>>
>> Yes, quite.
>
> OK. I hope that there is also someone knowledgable about the TCP stack
> who is following this thread. (Perhaps you also know this part of the
> kernel, but I am assuming that your expertise is on the e1000/NIC bits.)
>
>>> Important note: we ARE able to get full duplex wire speed (over 900
>>> Mb/s simulaneously in both directions) using UDP. The problems occur
>>> only with TCP connections.
>>
>> That eliminates bus bandwidth issues, probably, but small packets take
>> up a lot of extra descriptors, bus bandwidth, CPU, and cache resources.
>
> I see. Your concern is the extra ACK packets associated with TCP. Even
> those these represent a small volume of data (around 5% with MTU=1500,
> and less at larger MTU) they double the number of packets that must be
> handled by the system compared to UDP transmission at the same data
> rate. Is that correct?
A lot of people tend to forget that the pci-express bus has enough bandwidth on
first glance - 2.5gbit/sec for 1gbit of traffix, but apart from data going over it
there is significant overhead going on: each packet requires transmit, cleanup and
buffer transactions, and there are many irq register clears per second (slow
ioread/writes). The transactions double for TCP ack processing, and this all
accumulates and starts to introduce latency, higher cpu utilization etc...
Auke
^ permalink raw reply
* running aggregate netperf TCP_RR Re: e1000 full-duplex TCP performance well below wire speed
From: Rick Jones @ 2008-01-31 18:11 UTC (permalink / raw)
To: Carsten Aulbert
Cc: Brandeburg, Jesse, Bruce Allen, netdev, Henning Fehrmann,
Bruce Allen
In-Reply-To: <47A204E5.7060406@aei.mpg.de>
> PS: Am I right that the TCP_RR tests should only be run on a single node
> at a time, not on both ends simultaneously?
It depends on what you want to measure. In this specific case since the
goal is to saturate the link in both directions it is unlikely you
should need a second instance running, and if you do, going to a
TCP_STREAM+TCP_MAERTS pair might be indicated.
If one is measuring aggregate small transaction (perhaps packet)
performance, then there can be times when running multiple, concurrent,
aggregate TCP_RR tests is indicated.
Also, from time to time you may want to experiment with the value you
use with -b - the value necessary to get to saturation may not always be
the same - particularly as you switch from link to link and from LAN to
WAN and all those familiar bandwidthXdelay considerations.
happy benchmarking,
rick jones
^ permalink raw reply
* Re: e1000 full-duplex TCP performance well below wire speed
From: Kok, Auke @ 2008-01-31 18:15 UTC (permalink / raw)
To: Carsten Aulbert
Cc: Andi Kleen, Bruce Allen, Brandeburg, Jesse, netdev,
Henning Fehrmann, Bruce Allen
In-Reply-To: <47A1F2D5.5070709@aei.mpg.de>
Carsten Aulbert wrote:
> Hi Andi,
>
> Andi Kleen wrote:
>> Another issue with full duplex TCP not mentioned yet is that if TSO is
>> used the output will be somewhat bursty and might cause problems with
>> the TCP ACK clock of the other direction because the ACKs would need
>> to squeeze in between full TSO bursts.
>>
>> You could try disabling TSO with ethtool.
>
> I just tried that:
>
> https://n0.aei.uni-hannover.de/wiki/index.php/NetworkTestNetperf3
>
> It seems that the numbers do get better (sweet-spot seems to be MTU6000
> with 914 MBit/s and 927 MBit/s), however for other settings the results
> vary a lot so I'm not sure how large the statistical fluctuations are.
>
> Next test I'll try if it makes sense to enlarge the ring buffers.
sometimes it may help if the system (cpu) is laggy or busy a lot so that the card
has more buffers available (and thus can go longer without servicing)
Usually (if your system responds quickly) it's better to use *smaller* ring sizes
as this reduces cache. Hence the small default value.
so, unless the ethtool -S ethX output indicates that your system is too busy
(rx_no_buffer_count increases) I would not recommend increasing the ring size.
Auke
^ permalink raw reply
* Re: [PATCH] Disable TSO for non standard qdiscs
From: Andi Kleen @ 2008-01-31 18:53 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Andi Kleen, Patrick McHardy, netdev
In-Reply-To: <20080131100846.00934e25@extreme>
> Then change TBF to use skb_gso_segment? Be careful, the fact that
That doesn't help because it wants to interleave packets
from different streams to get everything fair and smooth. The only
good way to handle that is to split it up and the simplest way to do
this is to just tell TCP to not do GSO in the first place.
-Andi
^ permalink raw reply
* Re: [PATCH] Disable TSO for non standard qdiscs
From: Patrick McHardy @ 2008-01-31 18:21 UTC (permalink / raw)
To: Andi Kleen; +Cc: Stephen Hemminger, netdev
In-Reply-To: <20080131185328.GD4671@one.firstfloor.org>
Andi Kleen wrote:
>> Then change TBF to use skb_gso_segment? Be careful, the fact that
>
> That doesn't help because it wants to interleave packets
> from different streams to get everything fair and smooth. The only
> good way to handle that is to split it up and the simplest way to do
> this is to just tell TCP to not do GSO in the first place.
Thats not correct, TBF keeps packets strictly ordered unless
an inner qdisc does reordering. But even then (let say you use
SFQ) packets of a single flow will stay ordered. Segmenting
TSO packets is no different than having them arrive independantly
for other reasons.
^ permalink raw reply
* Re: [PATCH] Disable TSO for non standard qdiscs
From: Rick Jones @ 2008-01-31 18:26 UTC (permalink / raw)
To: Andi Kleen; +Cc: netdev, davem
In-Reply-To: <20080131124632.GA25299@basil.nowhere.org>
Andi Kleen wrote:
> TSO interacts badly with many queueing disciplines because they rely on
> reordering packets from different streams and the large TSO packets can
> make this difficult. This patch disables TSO for sockets that send over
> devices with non standard queueing disciplines. That's anything but noop
> or pfifo_fast and pfifo right now.
Does this also imply that JumboFrames interacts badly with these qdiscs?
Or IPoIB with its 65000ish byte MTU?
rick jones
^ permalink raw reply
* Re: [PATCH] Disable TSO for non standard qdiscs
From: Andi Kleen @ 2008-01-31 19:01 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Andi Kleen, Stephen Hemminger, netdev
In-Reply-To: <47A211A0.1040502@trash.net>
On Thu, Jan 31, 2008 at 07:21:20PM +0100, Patrick McHardy wrote:
> Andi Kleen wrote:
> >>Then change TBF to use skb_gso_segment? Be careful, the fact that
> >
> >That doesn't help because it wants to interleave packets
> >from different streams to get everything fair and smooth. The only
> >good way to handle that is to split it up and the simplest way to do
> >this is to just tell TCP to not do GSO in the first place.
>
>
> Thats not correct, TBF keeps packets strictly ordered unless
My point was that without TSO different submitters will interleave
their streams (because they compete about the qdisc submission)
and then you end up with a smooth rate over time for all of them.
If you submit in large chunks only (as TSO does) it will always
be more bursty and that works against the TBF goal.
For a single submitter you would be correct.
-Andi
^ permalink raw reply
* RE: e1000 full-duplex TCP performance well below wire speed
From: Brandeburg, Jesse @ 2008-01-31 18:26 UTC (permalink / raw)
To: Bill Fink, SANGTAE HA
Cc: Bruce Allen, Linux Kernel Mailing List, netdev, Stephen Hemminger
In-Reply-To: <20080131064533.ef0ae932.billfink@mindspring.com>
Bill Fink wrote:
> a 2.6.15.4 kernel. The GigE NICs are Intel PRO/1000
> 82546EB_QUAD_COPPER,
> on a 64-bit/133-MHz PCI-X bus, using version 6.1.16-k2 of the e1000
> driver, and running with 9000-byte jumbo frames. The TCP congestion
> control is BIC.
Bill, FYI, there was a known issue with e1000 (fixed in 7.0.38-k2) and
socket charge due to truesize that kept one end or the other from
opening its window. The result is not so great performance, and you
must upgrade the driver at both ends to fix it.
it was fixed in commit
9e2feace1acd38d7a3b1275f7f9f8a397d09040e
That commit itself needed a couple of follow on bug fixes, but the point
is that you could download 7.3.20 from sourceforge (which would compile
on your kernel) and compare the performance with it if you were
interested in a further experiment.
Jesse
^ permalink raw reply
* Re: [PATCH] Disable TSO for non standard qdiscs
From: Andi Kleen @ 2008-01-31 19:03 UTC (permalink / raw)
To: Rick Jones; +Cc: Andi Kleen, netdev, davem
In-Reply-To: <47A212CB.1060403@hp.com>
On Thu, Jan 31, 2008 at 10:26:19AM -0800, Rick Jones wrote:
> Andi Kleen wrote:
> >TSO interacts badly with many queueing disciplines because they rely on
> >reordering packets from different streams and the large TSO packets can
> >make this difficult. This patch disables TSO for sockets that send over
> >devices with non standard queueing disciplines. That's anything but noop
> >or pfifo_fast and pfifo right now.
>
> Does this also imply that JumboFrames interacts badly with these qdiscs?
> Or IPoIB with its 65000ish byte MTU?
Correct. Of course it is always relative to the link speed. So if your
link is 10x faster and your packets 10x bigger you can get similarly
smooth shaping.
-Andi
^ permalink raw reply
* [PATCH 3/6] [DCCP]: Reorganize struct dccp_sock to save 8 bytes
From: Arnaldo Carvalho de Melo @ 2008-01-31 18:31 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo
In-Reply-To: <1201804304-28777-3-git-send-email-acme@redhat.com>
/home/acme/git/net-2.6/net/dccp/ipv6.c:
struct dccp_sock | -8
struct dccp6_sock | -8
2 structs changed
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
include/linux/dccp.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 484e45c..aa07370 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -525,6 +525,7 @@ struct dccp_sock {
__u64 dccps_gsr;
__u64 dccps_gar;
__be32 dccps_service;
+ __u32 dccps_mss_cache;
struct dccp_service_list *dccps_service_list;
__u32 dccps_timestamp_echo;
__u32 dccps_timestamp_time;
@@ -533,7 +534,6 @@ struct dccp_sock {
__u16 dccps_pcslen;
__u16 dccps_pcrlen;
unsigned long dccps_ndp_count;
- __u32 dccps_mss_cache;
unsigned long dccps_rate_last;
struct dccp_minisock dccps_minisock;
struct dccp_ackvec *dccps_hc_rx_ackvec;
--
1.5.3.8
^ permalink raw reply related
* [PATCH 1/6] [SOCK] proto: Add hashinfo member to struct proto
From: Arnaldo Carvalho de Melo @ 2008-01-31 18:31 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo
In-Reply-To: <1201804304-28777-1-git-send-email-acme@redhat.com>
This way we can remove TCP and DCCP specific versions of
sk->sk_prot->get_port: both v4 and v6 use inet_csk_get_port
sk->sk_prot->hash: inet_hash is directly used, only v6 need
a specific version to deal with mapped sockets
sk->sk_prot->unhash: both v4 and v6 use inet_hash directly
struct inet_connection_sock_af_ops also gets a new member, bind_conflict,
so that inet_csk_get_port can find the per family routine.
Now only the lookup routines receive as a parameter a struct inet_hashtable.
With this we further reuse code, reducing the difference among INET transport
protocols.
Eventually work has to be done on UDP and SCTP to make them share this
infrastructure and get as a bonus inet_diag interfaces so that iproute can be
used with these protocols.
vmlinux:
add/remove: 2/4 grow/shrink: 13/6 up/down: 539/-508 (31)
function old new delta
inet_hash - 237 +237
inet_unhash - 190 +190
inet_csk_get_port 558 573 +15
tcp_sendmsg 2768 2777 +9
unix_proto 344 352 +8
udplite_prot 344 352 +8
udp_prot 344 352 +8
tcp_prot 344 352 +8
raw_prot 344 352 +8
packet_proto 344 352 +8
netlink_proto 344 352 +8
ipv4_specific 96 104 +8
inet_put_port 137 145 +8
__inet_hash_nolisten 310 318 +8
__inet6_hash 352 360 +8
tcp_v4_syn_recv_sock 666 664 -2
superblock_doinit 587 582 -5
tcp_v4_destroy_sock 557 550 -7
tcp_set_state 420 413 -7
__inet_hash_connect 673 665 -8
__inet_lookup_listener 333 313 -20
tcp_v4_get_port 31 - -31
tcp_v4_hash 48 - -48
tcp_unhash 179 - -179
__inet_hash 201 - -201
ipv6.ko:
add/remove: 0/1 grow/shrink: 6/2 up/down: 48/-42 (6)
function old new delta
udpv6_prot 344 352 +8
udplitev6_prot 344 352 +8
tcpv6_prot 344 352 +8
rawv6_prot 344 352 +8
ipv6_specific 96 104 +8
ipv6_mapped 96 104 +8
tcp_v6_syn_recv_sock 1633 1629 -4
tcp_v6_hash 70 63 -7
tcp_v6_get_port 31 - -31
dccp.ko:
add/remove: 0/2 grow/shrink: 1/4 up/down: 2/-243 (-241)
function old new delta
dccp_feat_change_recv 1050 1052 +2
init_module 961 960 -1
dccp_init 961 960 -1
dccp_set_state 474 467 -7
dccp_destroy_sock 191 184 -7
dccp_hash 48 - -48
dccp_unhash 179 - -179
dccp_ipv4.ko:
add/remove: 0/1 grow/shrink: 2/1 up/down: 16/-33 (-17)
function old new delta
dccp_v4_prot 344 352 +8
dccp_ipv4_af_ops 96 104 +8
dccp_v4_request_recv_sock 522 520 -2
dccp_v4_get_port 31 - -31
dccp_ipv6.ko:
add/remove: 0/1 grow/shrink: 4/1 up/down: 29/-38 (-9)
function old new delta
dccp_v6_prot 344 352 +8
dccp_ipv6_mapped 96 104 +8
dccp_ipv6_af_ops 96 104 +8
dccp_v6_request_recv_sock 1514 1519 +5
dccp_v6_hash 68 61 -7
dccp_v6_get_port 31 - -31
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
include/net/inet6_hashtables.h | 2 +-
include/net/inet_connection_sock.h | 8 ++---
include/net/inet_hashtables.h | 51 +++++--------------------------
include/net/sock.h | 3 ++
net/dccp/dccp.h | 2 -
net/dccp/ipv4.c | 18 ++++-------
net/dccp/ipv6.c | 20 +++++-------
net/dccp/proto.c | 18 +----------
net/ipv4/inet_connection_sock.c | 8 ++---
net/ipv4/inet_hashtables.c | 58 +++++++++++++++++++++++++++++------
net/ipv4/tcp.c | 2 +-
net/ipv4/tcp_ipv4.c | 31 +++++--------------
net/ipv6/inet6_hashtables.c | 4 +-
net/ipv6/tcp_ipv6.c | 19 +++++-------
14 files changed, 103 insertions(+), 141 deletions(-)
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index fdff630..62a5b69 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -49,7 +49,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
return inet6_ehashfn(laddr, lport, faddr, fport);
}
-extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
+extern void __inet6_hash(struct sock *sk);
/*
* Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 133cf30..f00f057 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -29,7 +29,6 @@
#undef INET_CSK_CLEAR_TIMERS
struct inet_bind_bucket;
-struct inet_hashinfo;
struct tcp_congestion_ops;
/*
@@ -59,6 +58,8 @@ struct inet_connection_sock_af_ops {
int level, int optname,
char __user *optval, int __user *optlen);
void (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
+ int (*bind_conflict)(const struct sock *sk,
+ const struct inet_bind_bucket *tb);
};
/** inet_connection_sock - INET connection oriented sock
@@ -244,10 +245,7 @@ extern struct request_sock *inet_csk_search_req(const struct sock *sk,
const __be32 laddr);
extern int inet_csk_bind_conflict(const struct sock *sk,
const struct inet_bind_bucket *tb);
-extern int inet_csk_get_port(struct inet_hashinfo *hashinfo,
- struct sock *sk, unsigned short snum,
- int (*bind_conflict)(const struct sock *sk,
- const struct inet_bind_bucket *tb));
+extern int inet_csk_get_port(struct sock *sk, unsigned short snum);
extern struct dst_entry* inet_csk_route_req(struct sock *sk,
const struct request_sock *req);
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index c23c4ed..48ac620 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -221,9 +221,9 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
}
/* Caller must disable local BH processing. */
-static inline void __inet_inherit_port(struct inet_hashinfo *table,
- struct sock *sk, struct sock *child)
+static inline void __inet_inherit_port(struct sock *sk, struct sock *child)
{
+ struct inet_hashinfo *table = sk->sk_prot->hashinfo;
const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
struct inet_bind_hashbucket *head = &table->bhash[bhash];
struct inet_bind_bucket *tb;
@@ -235,15 +235,14 @@ static inline void __inet_inherit_port(struct inet_hashinfo *table,
spin_unlock(&head->lock);
}
-static inline void inet_inherit_port(struct inet_hashinfo *table,
- struct sock *sk, struct sock *child)
+static inline void inet_inherit_port(struct sock *sk, struct sock *child)
{
local_bh_disable();
- __inet_inherit_port(table, sk, child);
+ __inet_inherit_port(sk, child);
local_bh_enable();
}
-extern void inet_put_port(struct inet_hashinfo *table, struct sock *sk);
+extern void inet_put_port(struct sock *sk);
extern void inet_listen_wlock(struct inet_hashinfo *hashinfo);
@@ -266,41 +265,9 @@ static inline void inet_listen_unlock(struct inet_hashinfo *hashinfo)
wake_up(&hashinfo->lhash_wait);
}
-extern void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
-extern void __inet_hash_nolisten(struct inet_hashinfo *hinfo, struct sock *sk);
-
-static inline void inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
-{
- if (sk->sk_state != TCP_CLOSE) {
- local_bh_disable();
- __inet_hash(hashinfo, sk);
- local_bh_enable();
- }
-}
-
-static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk)
-{
- rwlock_t *lock;
-
- if (sk_unhashed(sk))
- goto out;
-
- if (sk->sk_state == TCP_LISTEN) {
- local_bh_disable();
- inet_listen_wlock(hashinfo);
- lock = &hashinfo->lhash_lock;
- } else {
- lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
- write_lock_bh(lock);
- }
-
- if (__sk_del_node_init(sk))
- sock_prot_inuse_add(sk->sk_prot, -1);
- write_unlock_bh(lock);
-out:
- if (sk->sk_state == TCP_LISTEN)
- wake_up(&hashinfo->lhash_wait);
-}
+extern void __inet_hash_nolisten(struct sock *sk);
+extern void inet_hash(struct sock *sk);
+extern void inet_unhash(struct sock *sk);
extern struct sock *__inet_lookup_listener(struct net *net,
struct inet_hashinfo *hashinfo,
@@ -425,7 +392,7 @@ extern int __inet_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk,
int (*check_established)(struct inet_timewait_death_row *,
struct sock *, __u16, struct inet_timewait_sock **),
- void (*hash)(struct inet_hashinfo *, struct sock *));
+ void (*hash)(struct sock *sk));
extern int inet_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk);
#endif /* _INET_HASHTABLES_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index e3fb4c0..8a7889b 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -496,6 +496,7 @@ extern int sk_wait_data(struct sock *sk, long *timeo);
struct request_sock_ops;
struct timewait_sock_ops;
+struct inet_hashinfo;
/* Networking protocol blocks we attach to sockets.
* socket layer -> transport layer interface
@@ -578,6 +579,8 @@ struct proto {
struct request_sock_ops *rsk_prot;
struct timewait_sock_ops *twsk_prot;
+ struct inet_hashinfo *hashinfo;
+
struct module *owner;
char name[32];
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index ebe59d9..287a62b 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -271,8 +271,6 @@ extern struct sk_buff *dccp_make_response(struct sock *sk,
extern int dccp_connect(struct sock *sk);
extern int dccp_disconnect(struct sock *sk, int flags);
-extern void dccp_hash(struct sock *sk);
-extern void dccp_unhash(struct sock *sk);
extern int dccp_getsockopt(struct sock *sk, int level, int optname,
char __user *optval, int __user *optlen);
extern int dccp_setsockopt(struct sock *sk, int level, int optname,
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index c982ad8..474075a 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -38,12 +38,6 @@
*/
static struct socket *dccp_v4_ctl_socket;
-static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
-{
- return inet_csk_get_port(&dccp_hashinfo, sk, snum,
- inet_csk_bind_conflict);
-}
-
int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct inet_sock *inet = inet_sk(sk);
@@ -408,8 +402,8 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
dccp_sync_mss(newsk, dst_mtu(dst));
- __inet_hash_nolisten(&dccp_hashinfo, newsk);
- __inet_inherit_port(&dccp_hashinfo, sk, newsk);
+ __inet_hash_nolisten(newsk);
+ __inet_inherit_port(sk, newsk);
return newsk;
@@ -898,6 +892,7 @@ static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
.getsockopt = ip_getsockopt,
.addr2sockaddr = inet_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in),
+ .bind_conflict = inet_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ip_setsockopt,
.compat_getsockopt = compat_ip_getsockopt,
@@ -937,10 +932,10 @@ static struct proto dccp_v4_prot = {
.sendmsg = dccp_sendmsg,
.recvmsg = dccp_recvmsg,
.backlog_rcv = dccp_v4_do_rcv,
- .hash = dccp_hash,
- .unhash = dccp_unhash,
+ .hash = inet_hash,
+ .unhash = inet_unhash,
.accept = inet_csk_accept,
- .get_port = dccp_v4_get_port,
+ .get_port = inet_csk_get_port,
.shutdown = dccp_shutdown,
.destroy = dccp_destroy_sock,
.orphan_count = &dccp_orphan_count,
@@ -948,6 +943,7 @@ static struct proto dccp_v4_prot = {
.obj_size = sizeof(struct dccp_sock),
.rsk_prot = &dccp_request_sock_ops,
.twsk_prot = &dccp_timewait_sock_ops,
+ .hashinfo = &dccp_hashinfo,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_dccp_setsockopt,
.compat_getsockopt = compat_dccp_getsockopt,
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index ed0a005..490333d 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -39,21 +39,15 @@ static struct socket *dccp_v6_ctl_socket;
static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
-static int dccp_v6_get_port(struct sock *sk, unsigned short snum)
-{
- return inet_csk_get_port(&dccp_hashinfo, sk, snum,
- inet6_csk_bind_conflict);
-}
-
static void dccp_v6_hash(struct sock *sk)
{
if (sk->sk_state != DCCP_CLOSED) {
if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
- dccp_hash(sk);
+ inet_hash(sk);
return;
}
local_bh_disable();
- __inet6_hash(&dccp_hashinfo, sk);
+ __inet6_hash(sk);
local_bh_enable();
}
}
@@ -630,8 +624,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
- __inet6_hash(&dccp_hashinfo, newsk);
- inet_inherit_port(&dccp_hashinfo, sk, newsk);
+ __inet6_hash(newsk);
+ inet_inherit_port(sk, newsk);
return newsk;
@@ -1054,6 +1048,7 @@ static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
.getsockopt = ipv6_getsockopt,
.addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6),
+ .bind_conflict = inet6_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
@@ -1123,9 +1118,9 @@ static struct proto dccp_v6_prot = {
.recvmsg = dccp_recvmsg,
.backlog_rcv = dccp_v6_do_rcv,
.hash = dccp_v6_hash,
- .unhash = dccp_unhash,
+ .unhash = inet_unhash,
.accept = inet_csk_accept,
- .get_port = dccp_v6_get_port,
+ .get_port = inet_csk_get_port,
.shutdown = dccp_shutdown,
.destroy = dccp_v6_destroy_sock,
.orphan_count = &dccp_orphan_count,
@@ -1133,6 +1128,7 @@ static struct proto dccp_v6_prot = {
.obj_size = sizeof(struct dccp6_sock),
.rsk_prot = &dccp6_request_sock_ops,
.twsk_prot = &dccp6_timewait_sock_ops,
+ .hashinfo = &dccp_hashinfo,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_dccp_setsockopt,
.compat_getsockopt = compat_dccp_getsockopt,
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 0bed4a6..e3f5d37 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -78,7 +78,7 @@ void dccp_set_state(struct sock *sk, const int state)
sk->sk_prot->unhash(sk);
if (inet_csk(sk)->icsk_bind_hash != NULL &&
!(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
- inet_put_port(&dccp_hashinfo, sk);
+ inet_put_port(sk);
/* fall through */
default:
if (oldstate == DCCP_OPEN)
@@ -173,20 +173,6 @@ const char *dccp_state_name(const int state)
EXPORT_SYMBOL_GPL(dccp_state_name);
-void dccp_hash(struct sock *sk)
-{
- inet_hash(&dccp_hashinfo, sk);
-}
-
-EXPORT_SYMBOL_GPL(dccp_hash);
-
-void dccp_unhash(struct sock *sk)
-{
- inet_unhash(&dccp_hashinfo, sk);
-}
-
-EXPORT_SYMBOL_GPL(dccp_unhash);
-
int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
{
struct dccp_sock *dp = dccp_sk(sk);
@@ -268,7 +254,7 @@ int dccp_destroy_sock(struct sock *sk)
/* Clean up a referenced DCCP bind bucket. */
if (inet_csk(sk)->icsk_bind_hash != NULL)
- inet_put_port(&dccp_hashinfo, sk);
+ inet_put_port(sk);
kfree(dp->dccps_service_list);
dp->dccps_service_list = NULL;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index de5a41d..b189278 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -78,11 +78,9 @@ EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
/* Obtain a reference to a local port for the given sock,
* if snum is zero it means select any available local port.
*/
-int inet_csk_get_port(struct inet_hashinfo *hashinfo,
- struct sock *sk, unsigned short snum,
- int (*bind_conflict)(const struct sock *sk,
- const struct inet_bind_bucket *tb))
+int inet_csk_get_port(struct sock *sk, unsigned short snum)
{
+ struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
struct inet_bind_hashbucket *head;
struct hlist_node *node;
struct inet_bind_bucket *tb;
@@ -142,7 +140,7 @@ tb_found:
goto success;
} else {
ret = 1;
- if (bind_conflict(sk, tb))
+ if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb))
goto fail_unlock;
}
}
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 48d4500..90f422c 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -66,8 +66,9 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
/*
* Get rid of any references to a local port held by the given sock.
*/
-static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
+static void __inet_put_port(struct sock *sk)
{
+ struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
struct inet_bind_bucket *tb;
@@ -81,10 +82,10 @@ static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
spin_unlock(&head->lock);
}
-void inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
+void inet_put_port(struct sock *sk)
{
local_bh_disable();
- __inet_put_port(hashinfo, sk);
+ __inet_put_port(sk);
local_bh_enable();
}
@@ -317,8 +318,9 @@ static inline u32 inet_sk_port_offset(const struct sock *sk)
inet->dport);
}
-void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk)
+void __inet_hash_nolisten(struct sock *sk)
{
+ struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
struct hlist_head *list;
rwlock_t *lock;
struct inet_ehash_bucket *head;
@@ -337,13 +339,14 @@ void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk)
}
EXPORT_SYMBOL_GPL(__inet_hash_nolisten);
-void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
+static void __inet_hash(struct sock *sk)
{
+ struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
struct hlist_head *list;
rwlock_t *lock;
if (sk->sk_state != TCP_LISTEN) {
- __inet_hash_nolisten(hashinfo, sk);
+ __inet_hash_nolisten(sk);
return;
}
@@ -357,13 +360,48 @@ void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
write_unlock(lock);
wake_up(&hashinfo->lhash_wait);
}
-EXPORT_SYMBOL_GPL(__inet_hash);
+
+void inet_hash(struct sock *sk)
+{
+ if (sk->sk_state != TCP_CLOSE) {
+ local_bh_disable();
+ __inet_hash(sk);
+ local_bh_enable();
+ }
+}
+EXPORT_SYMBOL_GPL(inet_hash);
+
+void inet_unhash(struct sock *sk)
+{
+ rwlock_t *lock;
+ struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
+
+ if (sk_unhashed(sk))
+ goto out;
+
+ if (sk->sk_state == TCP_LISTEN) {
+ local_bh_disable();
+ inet_listen_wlock(hashinfo);
+ lock = &hashinfo->lhash_lock;
+ } else {
+ lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
+ write_lock_bh(lock);
+ }
+
+ if (__sk_del_node_init(sk))
+ sock_prot_inuse_add(sk->sk_prot, -1);
+ write_unlock_bh(lock);
+out:
+ if (sk->sk_state == TCP_LISTEN)
+ wake_up(&hashinfo->lhash_wait);
+}
+EXPORT_SYMBOL_GPL(inet_unhash);
int __inet_hash_connect(struct inet_timewait_death_row *death_row,
struct sock *sk,
int (*check_established)(struct inet_timewait_death_row *,
struct sock *, __u16, struct inet_timewait_sock **),
- void (*hash)(struct inet_hashinfo *, struct sock *))
+ void (*hash)(struct sock *sk))
{
struct inet_hashinfo *hinfo = death_row->hashinfo;
const unsigned short snum = inet_sk(sk)->num;
@@ -427,7 +465,7 @@ ok:
inet_bind_hash(sk, tb, port);
if (sk_unhashed(sk)) {
inet_sk(sk)->sport = htons(port);
- hash(hinfo, sk);
+ hash(sk);
}
spin_unlock(&head->lock);
@@ -444,7 +482,7 @@ ok:
tb = inet_csk(sk)->icsk_bind_hash;
spin_lock_bh(&head->lock);
if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
- hash(hinfo, sk);
+ hash(sk);
spin_unlock_bh(&head->lock);
return 0;
} else {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index a0d373b..071e83a 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1669,7 +1669,7 @@ void tcp_set_state(struct sock *sk, int state)
sk->sk_prot->unhash(sk);
if (inet_csk(sk)->icsk_bind_hash &&
!(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
- inet_put_port(&tcp_hashinfo, sk);
+ inet_put_port(sk);
/* fall through */
default:
if (oldstate==TCP_ESTABLISHED)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 77c1939..63414ea 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -108,22 +108,6 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
.lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
};
-static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
-{
- return inet_csk_get_port(&tcp_hashinfo, sk, snum,
- inet_csk_bind_conflict);
-}
-
-static void tcp_v4_hash(struct sock *sk)
-{
- inet_hash(&tcp_hashinfo, sk);
-}
-
-void tcp_unhash(struct sock *sk)
-{
- inet_unhash(&tcp_hashinfo, sk);
-}
-
static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
{
return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
@@ -1478,8 +1462,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
}
#endif
- __inet_hash_nolisten(&tcp_hashinfo, newsk);
- __inet_inherit_port(&tcp_hashinfo, sk, newsk);
+ __inet_hash_nolisten(newsk);
+ __inet_inherit_port(sk, newsk);
return newsk;
@@ -1827,6 +1811,7 @@ struct inet_connection_sock_af_ops ipv4_specific = {
.getsockopt = ip_getsockopt,
.addr2sockaddr = inet_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in),
+ .bind_conflict = inet_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ip_setsockopt,
.compat_getsockopt = compat_ip_getsockopt,
@@ -1926,7 +1911,7 @@ int tcp_v4_destroy_sock(struct sock *sk)
/* Clean up a referenced TCP bind bucket. */
if (inet_csk(sk)->icsk_bind_hash)
- inet_put_port(&tcp_hashinfo, sk);
+ inet_put_port(sk);
/*
* If sendmsg cached page exists, toss it.
@@ -2435,9 +2420,9 @@ struct proto tcp_prot = {
.getsockopt = tcp_getsockopt,
.recvmsg = tcp_recvmsg,
.backlog_rcv = tcp_v4_do_rcv,
- .hash = tcp_v4_hash,
- .unhash = tcp_unhash,
- .get_port = tcp_v4_get_port,
+ .hash = inet_hash,
+ .unhash = inet_unhash,
+ .get_port = inet_csk_get_port,
.enter_memory_pressure = tcp_enter_memory_pressure,
.sockets_allocated = &tcp_sockets_allocated,
.orphan_count = &tcp_orphan_count,
@@ -2450,6 +2435,7 @@ struct proto tcp_prot = {
.obj_size = sizeof(struct tcp_sock),
.twsk_prot = &tcp_timewait_sock_ops,
.rsk_prot = &tcp_request_sock_ops,
+ .hashinfo = &tcp_hashinfo,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_tcp_setsockopt,
.compat_getsockopt = compat_tcp_getsockopt,
@@ -2467,7 +2453,6 @@ void __init tcp_v4_init(struct net_proto_family *ops)
EXPORT_SYMBOL(ipv4_specific);
EXPORT_SYMBOL(tcp_hashinfo);
EXPORT_SYMBOL(tcp_prot);
-EXPORT_SYMBOL(tcp_unhash);
EXPORT_SYMBOL(tcp_v4_conn_request);
EXPORT_SYMBOL(tcp_v4_connect);
EXPORT_SYMBOL(tcp_v4_do_rcv);
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index d325a99..43f3993 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -22,9 +22,9 @@
#include <net/inet6_hashtables.h>
#include <net/ip.h>
-void __inet6_hash(struct inet_hashinfo *hashinfo,
- struct sock *sk)
+void __inet6_hash(struct sock *sk)
{
+ struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
struct hlist_head *list;
rwlock_t *lock;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 59d0029..12750f2 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -86,12 +86,6 @@ static struct tcp_sock_af_ops tcp_sock_ipv6_specific;
static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
#endif
-static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
-{
- return inet_csk_get_port(&tcp_hashinfo, sk, snum,
- inet6_csk_bind_conflict);
-}
-
static void tcp_v6_hash(struct sock *sk)
{
if (sk->sk_state != TCP_CLOSE) {
@@ -100,7 +94,7 @@ static void tcp_v6_hash(struct sock *sk)
return;
}
local_bh_disable();
- __inet6_hash(&tcp_hashinfo, sk);
+ __inet6_hash(sk);
local_bh_enable();
}
}
@@ -1504,8 +1498,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
}
#endif
- __inet6_hash(&tcp_hashinfo, newsk);
- inet_inherit_port(&tcp_hashinfo, sk, newsk);
+ __inet6_hash(newsk);
+ inet_inherit_port(sk, newsk);
return newsk;
@@ -1833,6 +1827,7 @@ static struct inet_connection_sock_af_ops ipv6_specific = {
.getsockopt = ipv6_getsockopt,
.addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6),
+ .bind_conflict = inet6_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
@@ -1864,6 +1859,7 @@ static struct inet_connection_sock_af_ops ipv6_mapped = {
.getsockopt = ipv6_getsockopt,
.addr2sockaddr = inet6_csk_addr2sockaddr,
.sockaddr_len = sizeof(struct sockaddr_in6),
+ .bind_conflict = inet6_csk_bind_conflict,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_ipv6_setsockopt,
.compat_getsockopt = compat_ipv6_getsockopt,
@@ -2127,8 +2123,8 @@ struct proto tcpv6_prot = {
.recvmsg = tcp_recvmsg,
.backlog_rcv = tcp_v6_do_rcv,
.hash = tcp_v6_hash,
- .unhash = tcp_unhash,
- .get_port = tcp_v6_get_port,
+ .unhash = inet_unhash,
+ .get_port = inet_csk_get_port,
.enter_memory_pressure = tcp_enter_memory_pressure,
.sockets_allocated = &tcp_sockets_allocated,
.memory_allocated = &tcp_memory_allocated,
@@ -2141,6 +2137,7 @@ struct proto tcpv6_prot = {
.obj_size = sizeof(struct tcp6_sock),
.twsk_prot = &tcp6_timewait_sock_ops,
.rsk_prot = &tcp6_request_sock_ops,
+ .hashinfo = &tcp_hashinfo,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_tcp_setsockopt,
.compat_getsockopt = compat_tcp_getsockopt,
--
1.5.3.8
^ permalink raw reply related
* [PATCH 6/6] [TCP]: Reorganize struct tcp_sock to save 16 bytes on 64-bit arch
From: Arnaldo Carvalho de Melo @ 2008-01-31 18:31 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo
In-Reply-To: <1201804304-28777-6-git-send-email-acme@redhat.com>
/home/acme/git/net-2.6/net/ipv6/tcp_ipv6.c:
struct tcp_sock | -16
struct tcp6_sock | -16
2 structs changed
Now it is at:
/* size: 1552, cachelines: 25 */
/* paddings: 2, sum paddings: 8 */
/* last cacheline: 16 bytes */
As soon as we stop using skb_queue_list we'll get it down to 24 cachelines.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
include/linux/tcp.h | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 08027f1..f48644d 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -304,7 +304,6 @@ struct tcp_sock {
u32 rtt_seq; /* sequence number to update rttvar */
u32 packets_out; /* Packets which are "in flight" */
- u32 retrans_out; /* Retransmitted packets out */
/*
* Options received (usually on last packet, some only on SYN packets).
*/
@@ -332,6 +331,8 @@ struct tcp_sock {
struct tcp_sack_block recv_sack_cache[4];
+ u32 retrans_out; /* Retransmitted packets out */
+
struct sk_buff *highest_sack; /* highest skb with SACK received
* (validity guaranteed only if
* sacked_out > 0)
@@ -372,7 +373,6 @@ struct tcp_sock {
unsigned int keepalive_time; /* time before keep alive takes place */
unsigned int keepalive_intvl; /* time interval between keep alive probes */
- int linger2;
unsigned long last_synq_overflow;
@@ -398,6 +398,8 @@ struct tcp_sock {
u32 probe_seq_end;
} mtu_probe;
+ int linger2;
+
#ifdef CONFIG_TCP_MD5SIG
/* TCP AF-Specific parts; only used by MD5 Signature support so far */
struct tcp_sock_af_ops *af_specific;
--
1.5.3.8
^ permalink raw reply related
* [PATCH 2/6] [INET6]: Reorganize struct inet6_dev to save 8 bytes
From: Arnaldo Carvalho de Melo @ 2008-01-31 18:31 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo
In-Reply-To: <1201804304-28777-2-git-send-email-acme@redhat.com>
And make it a multiple of a 64 bytes, reducing cacheline trashing:
Before:
[acme@doppio net-2.6]$ pahole -C inet6_dev net/dccp/ipv6.o
struct inet6_dev {
<SNIP>
long unsigned int mc_maxdelay; /* 48 8 */
unsigned char mc_qrv; /* 56 1 */
unsigned char mc_gq_running; /* 57 1 */
unsigned char mc_ifc_count; /* 58 1 */
/* XXX 5 bytes hole, try to pack */
/* --- cacheline 1 boundary (64 bytes) --- */
struct timer_list mc_gq_timer; /* 64 48 */
<SNIP>
__u32 if_flags; /* 180 4 */
int dead; /* 184 4 */
u8 rndid[8]; /* 188 8 */
/* XXX 4 bytes hole, try to pack */
/* --- cacheline 3 boundary (192 bytes) was 8 bytes ago --- */
struct timer_list regen_timer; /* 200 48 */
<SNIP>
/* size: 456, cachelines: 8 */
/* sum members: 447, holes: 2, sum holes: 9 */
/* last cacheline: 8 bytes */
};
After:
[acme@doppio net-2.6]$ codiff net/dccp/ipv6.o.old net/dccp/ipv6.o
/home/acme/git/net-2.6/net/dccp/ipv6.c:
struct inet6_dev | -8
1 struct changed
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
include/net/if_inet6.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index b24508a..b0b882e 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -171,6 +171,7 @@ struct inet6_dev
unsigned char mc_qrv;
unsigned char mc_gq_running;
unsigned char mc_ifc_count;
+ int dead;
struct timer_list mc_gq_timer; /* general query timer */
struct timer_list mc_ifc_timer; /* interface change timer */
@@ -178,7 +179,6 @@ struct inet6_dev
rwlock_t lock;
atomic_t refcnt;
__u32 if_flags;
- int dead;
#ifdef CONFIG_IPV6_PRIVACY
u8 rndid[8];
--
1.5.3.8
^ permalink raw reply related
* [PATCHES 0/6]: Move hashinfo to sk_prot and struct reorgs
From: Arnaldo Carvalho de Melo @ 2008-01-31 18:31 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp
Hi David,
Please consider pulling from:
master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6
Best Regards,
- Arnaldo
include/linux/dccp.h | 2 -
include/linux/tcp.h | 6 ++-
include/net/if_inet6.h | 4 +-
include/net/inet6_hashtables.h | 2 -
include/net/inet_connection_sock.h | 8 +----
include/net/inet_hashtables.h | 51 +++++---------------------------
include/net/inet_timewait_sock.h | 3 -
include/net/sock.h | 3 +
net/dccp/dccp.h | 2 -
net/dccp/ipv4.c | 18 ++++-------
net/dccp/ipv6.c | 20 +++++-------
net/dccp/proto.c | 18 +----------
net/ipv4/inet_connection_sock.c | 8 +----
net/ipv4/inet_hashtables.c | 58 ++++++++++++++++++++++++++++++-------
net/ipv4/tcp.c | 2 -
net/ipv4/tcp_ipv4.c | 31 +++++--------------
net/ipv6/inet6_hashtables.c | 4 +-
net/ipv6/tcp_ipv6.c | 19 +++++-------
18 files changed, 111 insertions(+), 148 deletions(-)
^ permalink raw reply
* [PATCH 4/6] [IPV6]: Reorganize strut ipv6_mc_socklist to save 8 bytes
From: Arnaldo Carvalho de Melo @ 2008-01-31 18:31 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo
In-Reply-To: <1201804304-28777-4-git-send-email-acme@redhat.com>
/home/acme/git/net-2.6/net/dccp/ipv6.c:
struct ipv6_mc_socklist | -8
1 struct changed
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
include/net/if_inet6.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index b0b882e..b2509d4 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -82,9 +82,9 @@ struct ipv6_mc_socklist
{
struct in6_addr addr;
int ifindex;
+ unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */
struct ipv6_mc_socklist *next;
rwlock_t sflock;
- unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */
struct ip6_sf_socklist *sflist;
};
--
1.5.3.8
^ permalink raw reply related
* [PATCH 5/6] [INET_TIMEWAIT_SOCK]: Reorganize struct inet_timewait_sock to save some bytes
From: Arnaldo Carvalho de Melo @ 2008-01-31 18:31 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, dccp, Arnaldo Carvalho de Melo
In-Reply-To: <1201804304-28777-5-git-send-email-acme@redhat.com>
/home/acme/git/net-2.6/net/ipv6/tcp_ipv6.c:
struct inet_timewait_sock | -8
struct tcp_timewait_sock | -8
2 structs changed
tcp_v6_rcv | -6
1 function changed, 6 bytes removed, diff: -6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
include/net/inet_timewait_sock.h | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 67e9250..faead52 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -116,8 +116,8 @@ struct inet_timewait_sock {
#define tw_hash __tw_common.skc_hash
#define tw_prot __tw_common.skc_prot
#define tw_net __tw_common.skc_net
+ int tw_timeout;
volatile unsigned char tw_substate;
- /* 3 bits hole, try to pack */
unsigned char tw_rcv_wscale;
/* Socket demultiplex comparisons on incoming packets. */
/* these five are in inet_sock */
@@ -130,7 +130,6 @@ struct inet_timewait_sock {
__u8 tw_ipv6only:1;
/* 15 bits hole, try to pack */
__u16 tw_ipv6_offset;
- int tw_timeout;
unsigned long tw_ttd;
struct inet_bind_bucket *tw_tb;
struct hlist_node tw_death_node;
--
1.5.3.8
^ permalink raw reply related
* Re: [PATCH] Disable TSO for non standard qdiscs
From: Rick Jones @ 2008-01-31 18:35 UTC (permalink / raw)
To: Andi Kleen; +Cc: netdev, davem
In-Reply-To: <20080131190326.GF4671@one.firstfloor.org>
Andi Kleen wrote:
> On Thu, Jan 31, 2008 at 10:26:19AM -0800, Rick Jones wrote:
>
>>Andi Kleen wrote:
>>
>>>TSO interacts badly with many queueing disciplines because they rely on
>>>reordering packets from different streams and the large TSO packets can
>>>make this difficult. This patch disables TSO for sockets that send over
>>>devices with non standard queueing disciplines. That's anything but noop
>>>or pfifo_fast and pfifo right now.
>>
>>Does this also imply that JumboFrames interacts badly with these qdiscs?
>> Or IPoIB with its 65000ish byte MTU?
>
>
> Correct. Of course it is always relative to the link speed. So if your
> link is 10x faster and your packets 10x bigger you can get similarly
> smooth shaping.
So, at what timescale do people using these qdiscs expect things to
appear "smooth?" 64KB of data at GbE speeds is something just north of
half a millisecond unless I've botched my units somewhere.
rick jones
^ permalink raw reply
* Re: e1000 full-duplex TCP performance well below wire speed
From: Rick Jones @ 2008-01-31 18:38 UTC (permalink / raw)
To: Kok, Auke
Cc: Bruce Allen, Brandeburg, Jesse, netdev, Carsten Aulbert,
Henning Fehrmann, Bruce Allen
In-Reply-To: <47A20E9E.7070503@intel.com>
> A lot of people tend to forget that the pci-express bus has enough bandwidth on
> first glance - 2.5gbit/sec for 1gbit of traffix, but apart from data going over it
> there is significant overhead going on: each packet requires transmit, cleanup and
> buffer transactions, and there are many irq register clears per second (slow
> ioread/writes). The transactions double for TCP ack processing, and this all
> accumulates and starts to introduce latency, higher cpu utilization etc...
Sounds like tools to show PCI* bus utilization would be helpful...
rick jones
^ permalink raw reply
* Re: hard hang through qdisc
From: Patrick McHardy @ 2008-01-31 18:46 UTC (permalink / raw)
To: Andi Kleen; +Cc: hadi, netdev
In-Reply-To: <47A1E556.3050900@trash.net>
Patrick McHardy wrote:
> Andi Kleen wrote:
>
>> Can you please try with the above config?
>
>
> I'll give it a try later.
I took all options from that config that seemed possibly
related (qdiscs, no hrtimers, no nohz, slab, ...), but
still can't reproduce it.
Does it also crash if you use more reasonable parameters?
^ permalink raw reply
* Re: [PATCH] Disable TSO for non standard qdiscs
From: Patrick McHardy @ 2008-01-31 18:48 UTC (permalink / raw)
To: Andi Kleen; +Cc: Stephen Hemminger, netdev
In-Reply-To: <20080131190125.GE4671@one.firstfloor.org>
Andi Kleen wrote:
> On Thu, Jan 31, 2008 at 07:21:20PM +0100, Patrick McHardy wrote:
>> Andi Kleen wrote:
>>>> Then change TBF to use skb_gso_segment? Be careful, the fact that
>>> That doesn't help because it wants to interleave packets
>> >from different streams to get everything fair and smooth. The only
>>> good way to handle that is to split it up and the simplest way to do
>>> this is to just tell TCP to not do GSO in the first place.
>>
>> Thats not correct, TBF keeps packets strictly ordered unless
>
> My point was that without TSO different submitters will interleave
> their streams (because they compete about the qdisc submission)
> and then you end up with a smooth rate over time for all of them.
>
> If you submit in large chunks only (as TSO does) it will always
> be more bursty and that works against the TBF goal.
>
> For a single submitter you would be correct.
The TBF goal is not really fairness among different flows, but
I agree, avoiding TSO in the first place seems to make more sense.
^ permalink raw reply
* Re: [PATCH] Disable TSO for non standard qdiscs
From: Andi Kleen @ 2008-01-31 19:25 UTC (permalink / raw)
To: Rick Jones; +Cc: Andi Kleen, netdev, davem
In-Reply-To: <47A214FE.3050200@hp.com>
> So, at what timescale do people using these qdiscs expect things to
> appear "smooth?" 64KB of data at GbE speeds is something just north of
> half a millisecond unless I've botched my units somewhere.
One typical use case for TBF is you talking to a DSL bridge that
is connected using a GBit Ethernet switch. For these DSL connections it gives
much better behaviour to shape the traffic to slightly below
your external link speed so that you can e.g. prioritize packets properly.
But the actual external link speed is much lower than GbE.
A lot of GbE NICs enable TSO by default.
-Andi
^ permalink raw reply
* Re: e1000 full-duplex TCP performance well below wire speed
From: Kok, Auke @ 2008-01-31 18:47 UTC (permalink / raw)
To: Rick Jones
Cc: Bruce Allen, Brandeburg, Jesse, netdev, Carsten Aulbert,
Henning Fehrmann, Bruce Allen
In-Reply-To: <47A215A8.2090104@hp.com>
Rick Jones wrote:
>> A lot of people tend to forget that the pci-express bus has enough
>> bandwidth on
>> first glance - 2.5gbit/sec for 1gbit of traffix, but apart from data
>> going over it
>> there is significant overhead going on: each packet requires transmit,
>> cleanup and
>> buffer transactions, and there are many irq register clears per second
>> (slow
>> ioread/writes). The transactions double for TCP ack processing, and
>> this all
>> accumulates and starts to introduce latency, higher cpu utilization
>> etc...
>
> Sounds like tools to show PCI* bus utilization would be helpful...
that would be a hardware profiling thing and highly dependent on the part sticking
out of the slot, vendor bus implementation etc... Perhaps Intel has some tools for
this already but I personally do not know of any :/
Auke
^ permalink raw reply
* RE: [PATCH] Disable TSO for non standard qdiscs
From: Waskiewicz Jr, Peter P @ 2008-01-31 18:47 UTC (permalink / raw)
To: Andi Kleen, Patrick McHardy; +Cc: Stephen Hemminger, netdev
In-Reply-To: <20080131190125.GE4671@one.firstfloor.org>
> My point was that without TSO different submitters will
> interleave their streams (because they compete about the
> qdisc submission) and then you end up with a smooth rate over
> time for all of them.
>
> If you submit in large chunks only (as TSO does) it will
> always be more bursty and that works against the TBF goal.
>
> For a single submitter you would be correct.
>
> -Andi
TSO by nature is bursty. But disabling TSO without the option of having
it on or off to me seems to aggressive. If someone is using a qdisc
that TSO is interfering with the effectiveness of the traffic shaping,
then they should turn off TSO via ethtool on the target device. Some
people may want TSO with certain rate limiter settings. That way (as
Stephen said) you can even allow the stack to GSO, then segment before
calling hard_start_xmit(), which still saves a number of cycles.
I'd rather not see this, but a documented recommendation why TSO could
be bad for some traffic shaping qdiscs. Give the power to the user to
either shoot themselves in the foot or disable TSO when needed.
-PJ Waskiewicz
<peter.p.waskiewicz.jr@intel.com>
^ permalink raw reply
* Re: hard hang through qdisc
From: Andi Kleen @ 2008-01-31 18:55 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Andi Kleen, hadi, netdev
In-Reply-To: <47A2176A.7080606@trash.net>
On Thu, Jan 31, 2008 at 07:46:02PM +0100, Patrick McHardy wrote:
> Patrick McHardy wrote:
>> Andi Kleen wrote:
>>
>>> Can you please try with the above config?
>> I'll give it a try later.
>
>
> I took all options from that config that seemed possibly
> related (qdiscs, no hrtimers, no nohz, slab, ...), but
> still can't reproduce it.
Ok I'll do bisect then later (not today anymore likely)
> Does it also crash if you use more reasonable parameters?
I managed to make it crash with different parameters too,
but with good parameters it did set a qdisc successfully
and appeared to work.
-Andi
^ permalink raw reply
* Re: [PATCH] Disable TSO for non standard qdiscs
From: Andi Kleen @ 2008-01-31 19:34 UTC (permalink / raw)
To: Waskiewicz Jr, Peter P
Cc: Andi Kleen, Patrick McHardy, Stephen Hemminger, netdev
In-Reply-To: <D5C1322C3E673F459512FB59E0DDC32904700E40@orsmsx414.amr.corp.intel.com>
> TSO by nature is bursty. But disabling TSO without the option of having
> it on or off to me seems to aggressive. If someone is using a qdisc
> that TSO is interfering with the effectiveness of the traffic shaping,
> then they should turn off TSO via ethtool on the target device. Some
The philosophical problem I have with this suggestion is that I expect
that the large majority of users will be more happy with disabled TSO
if they use non standard qdiscs and defaults that do not fit
the majority use case are bad.
Basically you're suggesting that nearly everyone using tc should learn about
another obscure command.
-Andi
^ 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