[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20070131103201.726678a7.akpm@osdl.org>
Date: Wed, 31 Jan 2007 10:32:01 -0800
From: Andrew Morton <akpm@...l.org>
To: netdev@...r.kernel.org
Cc: "bugme-daemon@...nel-bugs.osdl.org"
<bugme-daemon@...zilla.kernel.org>, Konstantin.Petrov@...etlabs.ru,
Alexandra.Kossovsky@...etlabs.ru
Subject: Fw: [Bugme-new] [Bug 7909] New: malfunction of udp_get_port() in
wildcard ports assigning
Begin forwarded message:
Date: Wed, 31 Jan 2007 03:50:56 -0800
From: bugme-daemon@...zilla.kernel.org
To: bugme-new@...ts.osdl.org
Subject: [Bugme-new] [Bug 7909] New: malfunction of udp_get_port() in wildcard ports assigning
http://bugzilla.kernel.org/show_bug.cgi?id=7909
Summary: malfunction of udp_get_port() in wildcard ports
assigning
Kernel Version: 2.6.19
Status: NEW
Severity: normal
Owner: shemminger@...l.org
Submitter: Konstantin.Petrov@...etlabs.ru
CC: Alexandra.Kossovsky@...etlabs.ru
Most recent kernel where this bug did *NOT* occur: 2.6.18.4
Distribution: Debian
Hardware Environment: PCs x86-64 and i686
Software Environment:
Problem Description:
repeated binding of datagram sockets to some IP with wildcard
port fails after ~three hundred iterations with errno EADDRINUSE.
List of really assigned ports looks strangely:
...PORT[128-port-numbers-gap]PORT[128-port-numbers-gap]...
Steps to reproduce:
See code:
#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/errno.h>
int
main(int argc, char **argv)
{
int iut_s;
int retval;
struct sockaddr_in servaddr,
cliaddr;
socklen_t namelen;
char addr_buf[16];
int i;
/* Read command line arguments */
if (argc != 2)
{
printf("\nuse pco_iut <local IP>\n");
return -1;
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
servaddr.sin_port = 0;
for (i = 0; i < 1024; i++)
{
if ( (iut_s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
printf("\nFailed to create socket No %d error %d\n", i + 1,
errno);
return -1;
}
if (bind(iut_s,(struct sockaddr *) &servaddr, sizeof(servaddr)) != 0)
{
printf("\nFailed to bind socket No %d error %d\n", i + 1,
errno);
return -1;
}
namelen = sizeof(cliaddr);
if (getsockname(iut_s, (struct sockaddr *)&cliaddr, &namelen) != 0)
{
printf("\ngetsockname() error errno %d\n", errno);
return -1;
}
else
{
inet_ntop(AF_INET, &cliaddr.sin_addr,
addr_buf, 16);
printf("\nBound to %s:%d\n",
addr_buf,
ntohs(cliaddr.sin_port));
}
}
return 0;
}
The reason of this issue is IMHO in udp_get_port() function
which was added in 2.6.19 version to replace udp_v4_get_port()
in older versions.
In ugp_get_port() we see the strange piece of code
.................................................................
size = 0;
sk_for_each(sk2, node, head)
if (++size < best_size_so_far) {
best_size_so_far = size;
best = result;
}
}
result = best;
for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result +=
UDP_HTABLE_SIZE) {
..........................................................................
which means that sk_for_each(...) iteration is repeated only once.
No such problem in older kernels where the similar
piece of code in udp_v4_get_port() looks like
..........................................................................
size = 0;
sk_for_each(sk2, node, list)
if (++size >= best_size_so_far)
goto next;
best_size_so_far = size;
best = result;
next:;
}
result = best;
for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result +=
UDP_HTABLE_SIZE) {
..........................................................................
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists