>> Where I work, all our PC ethernet cards are NE2000 clones of one
>> sort or another. I know NE2000's aren't supposed to be the
>> fastest cards around, but back in the days of 1.2 kernels,
>> `tcpspray' was able to send about 900k/s to an SGI, and about
>> 850k/s to another, identical Linux box. There was some variation
>> between cards from different manufacturers (and versions), with
>> some getting as low as 780k/s (ish).
>> I installed 1.3.small-number (1.3.13, or something like that), and was
>> disappointed to find that with the 900k/s card, the peak data rate was
>> now more like 690k/s to the same machines. It has improved marginally
>> to 700k/s (just now on 1.3.89), but this may be a statistical blip. As
>> I said, phase of the moon, etc.
>> To summarise: 1.2.x kernels -> 900k/s TCP data transmission rate
>> 1.3.x kernels -> 700k/s TCP data transmission rate
>>>>> "Paul" == Paul Gortmaker <gpg109@rsphysse.anu.edu.au> wrote:
Paul> Check your ISA bus speed, and the TCP window as mentioned in
Paul> the performance tuning section of the Ethernet-HowTo.
I've done some tests sending raw ethernet packets using SOCK_PACKET,
with 1.2.13 and 1.3.81 on exactly the same machine. The software
configuration is identical (I simply brought up different kernels).
The program is included at the end of this message so people can see if
the same problem exists with non-NE2000 cards.
I hope SOCK_PACKET has abolutely nothing to with the TCP window. The
ISA bus speed is the same for both kernels, as it's the same machine
within a few minutes.
New summary: 1.2.13 -> ~ 1197k/s raw data transmission rate
1.3.81 -> ~ 745k/s raw data transmission rate
Paul> Don't waste your time. The only thing I changed in the ne
Paul> driver during the 1.3 series was to add PCI support. The last
Paul> change before that was the fix to the hard lockup problems
Paul> that went in 1.2.8 or so.
Ok, maybe it isn't NE2k-specific. In that case, it's even more
important to get it fixed.
Included below are the detailed results and the program.
Enjoy,
-- Jamie Lokier
---cut here---
/* Send ethernet packets as fast as we can to a non-existent address.
Written by Jamie Lokier, 7 May 1996.
You may do whatever you like with this source code.
Results:
Linux 1.2.13:
mustelid:~# ./etherspray
Transmitted 7570000 bytes in 6.321147 seconds (1197.6k/sec).
mustelid:~# ./etherspray
Transmitted 7570000 bytes in 6.321372 seconds (1197.5k/sec).
mustelid:~# ./etherspray
Transmitted 7570000 bytes in 6.320811 seconds (1197.6k/sec).
mustelid:~# ./etherspray
Transmitted 7570000 bytes in 6.319735 seconds (1197.8k/sec).
mustelid:~# ./etherspray
Transmitted 7570000 bytes in 6.320675 seconds (1197.7k/sec).
Linux 1.3.81:
mustelid:~# ./etherspray
Socket destroy delayed (r=0 w=64740)
Transmitted 7570000 bytes in 10.091485 seconds (750.1k/sec).
mustelid:~# ./etherspray
Socket destroy delayed (r=0 w=64740)
Transmitted 7570000 bytes in 10.246718 seconds (738.8k/sec).
mustelid:~# ./etherspray
Socket destroy delayed (r=0 w=64740)
Transmitted 7570000 bytes in 10.221974 seconds (740.6k/sec).
mustelid:~# ./etherspray
Socket destroy delayed (r=0 w=64740)
Transmitted 7570000 bytes in 10.226442 seconds (740.2k/sec).
mustelid:~# ./etherspray
Socket destroy delayed (r=0 w=64740)
Transmitted 7570000 bytes in 10.238824 seconds (739.3k/sec).
Linux 1.3.97 gives similar results to 1.3.81. (I tested it on
a similar, but different machine).
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_ether.h>
/* The type field doesn't really matter because we're supposed to be
sending to a non-existent address. */
static char packet [ETH_FRAME_LEN] =
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Destination: something silly. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Source address: filled in later. */
(char) (ETH_P_ECHO >> 8), (char) ETH_P_ECHO,
};
int
main (int argc, char ** argv)
{
struct timeval tv_before, tv_after;
size_t bytes_written = 0;
int fd, n = 5000;
struct sockaddr sa;
sa.sa_family = AF_INET;
strcpy (sa.sa_data, "eth0");
fd = socket (PF_INET, SOCK_PACKET, htons (ETH_P_ECHO));
if (fd == -1)
{
perror ("socket");
exit (EXIT_FAILURE);
}
/* Get the source address for the packets. */
{
struct ifreq req;
int status;
strcpy (req.ifr_name, "eth0");
status = ioctl (fd, SIOCGIFHWADDR, &req);
if (status == -1)
{
perror ("SIOCGIFHWADDR");
exit (EXIT_FAILURE);
}
memcpy (packet + ETH_ALEN, req.ifr_hwaddr.sa_data, ETH_ALEN);
}
gettimeofday (&tv_before, 0);
while (n > 0)
{
int status;
status = sendto (fd, packet, sizeof (packet), 0, &sa, sizeof (sa));
if (status == -1)
{
if (errno == ENOBUFS)
continue;
perror ("sendto");
exit (EXIT_FAILURE);
}
bytes_written += sizeof (packet);
n--;
}
gettimeofday (&tv_after, 0);
close (fd);
if (tv_after.tv_usec < tv_before.tv_usec)
{
tv_after.tv_usec += 1000000;
tv_after.tv_sec -= 1;
}
tv_after.tv_usec -= tv_before.tv_usec;
tv_after.tv_sec -= tv_before.tv_sec;
{
double seconds = tv_after.tv_sec + tv_after.tv_usec / 1000000.0;
printf ("Transmitted %lu bytes in %f seconds (%.1fk/sec).\n",
bytes_written, seconds, bytes_written / 1000.0 / seconds);
}
return EXIT_SUCCESS;
}