From: Dan Kegel <dank@kegel.com>
To: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: [PATCH] tcp_v4_get_port() and ephemeral ports
Date: Sun, 30 Sep 2001 11:04:36 -0700 [thread overview]
Message-ID: <3BB75EB4.3268D3FC@kegel.com> (raw)
I'm doing ftp server benchmarking, doing lots of connect()'s.
Since ports aren't supposed to be reused for 2MSL (theoretically 120 seconds),
the absolute limit on connections per second is 64K/120 = 500.
This actually could pose a problem for me. (Yeah, 2MSL is
set to 30 seconds in linux, so the problem isn't as severe
as the standard says, but it's still a problem.)
Using ip address aliasing seems like a way around this.
By creating 9 more aliases for eth0 should raise this limit
to 5000 connections per second, which should do nicely.
So far, I've found an implementation of getifaddrs() that makes it
easy to retrieve the list of local IP addresses, and modified my
benchmark to assign a different local ip address to each user;
the users use bind() with that address and a zero port number,
and expect the system to assign a port.
Sadly, this doesn't have the desired effect, since
tcp_v4_get_port() in /usr/src/linux/net/tcp_v4.c skips over
a port if there are *any* sockets on that port.
It's tempting to patch tcp_v4_get_port() to check
sk->rcv_saddr, and if it's nonzero, allow the
same ephemeral port number to be reused on different interfaces.
Kinda like this (untested):
--- net/ipv4/tcp_ipv4.c.orig Sun Sep 30 10:28:23 2001
+++ net/ipv4/tcp_ipv4.c Sun Sep 30 10:52:41 2001
@@ -162,6 +162,33 @@
local_bh_enable();
}
+/* Return nonzero if the given sock can't bind to the given port */
+static int port_used(struct tcp_bind_bucket *tb, struct sock *sk)
+{
+ struct sock *sk2;
+ int sk_reuse;
+
+ if (!tb || !tb->owners)
+ return 0;
+
+ sk2 = tb->owners;
+ sk_reuse = sk->reuse;
+ for( ; sk2 != NULL; sk2 = sk2->bind_next) {
+ if (sk != sk2 &&
+ sk->bound_dev_if == sk2->bound_dev_if) {
+ if (!sk_reuse ||
+ !sk2->reuse ||
+ sk2->state == TCP_LISTEN) {
+ if (!sk2->rcv_saddr ||
+ !sk->rcv_saddr ||
+ (sk2->rcv_saddr == sk->rcv_saddr))
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
/* Obtain a reference to a local port for the given sock,
* if snum is zero it means select any available local port.
*/
@@ -186,8 +213,10 @@
head = &tcp_bhash[tcp_bhashfn(rover)];
spin_lock(&head->lock);
for (tb = head->chain; tb; tb = tb->next)
- if (tb->port == rover)
- goto next;
+ if (tb->port == rover) {
+ if (!sk->rcv_saddr || port_used(tb, sk))
+ goto next;
+ }
break;
next:
spin_unlock(&head->lock);
@@ -216,25 +245,9 @@
if (tb->fastreuse != 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) {
goto success;
} else {
- struct sock *sk2 = tb->owners;
- int sk_reuse = sk->reuse;
-
- for( ; sk2 != NULL; sk2 = sk2->bind_next) {
- if (sk != sk2 &&
- sk->bound_dev_if == sk2->bound_dev_if) {
- if (!sk_reuse ||
- !sk2->reuse ||
- sk2->state == TCP_LISTEN) {
- if (!sk2->rcv_saddr ||
- !sk->rcv_saddr ||
- (sk2->rcv_saddr == sk->rcv_saddr))
- break;
- }
- }
- }
- /* If we found a conflict, fail. */
+ /* If we find a conflict, fail. */
ret = 1;
- if (sk2 != NULL)
+ if (port_used(tb, sk))
goto fail_unlock;
}
}
===============
Can anyone comment on the wisdom of such a change?
Thanks,
Dan
next reply other threads:[~2001-09-30 18:03 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-09-30 18:04 Dan Kegel [this message]
2001-09-30 18:16 ` [PATCH] tcp_v4_get_port() and ephemeral ports Davide Libenzi
2001-09-30 18:29 ` Dan Kegel
2001-09-30 18:41 ` Mika Liljeberg
2001-09-30 20:37 ` Dan Kegel
2001-09-30 21:45 ` Mika Liljeberg
2001-09-30 20:53 ` Chris Wedgwood
-- strict thread matches above, loose matches on Subject: below --
2001-09-30 21:15 Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3BB75EB4.3268D3FC@kegel.com \
--to=dank@kegel.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox