Updated: October 31, 2011
You have reached this article because you face the following problem: you have just recently installed Linux on your machine, most likely one of the Ubuntu family. The machine already has Windows installed, so this makes it a dual-boot setup. In Windows, network performance is quite good, everything seems to work well, within the limits of what your ISP can offer you. However, in Ubuntu, things are very slow; you experience huge latency in opening websites, the throughput is a fraction of what it ought to be, both on the local network and the Internet. What do you do?
After installing Kubuntu on my latest and greatest machine, I faced this very problem. In Windows, I would manage 10-11Mbps download without problems, local shares, including Samba, would open instantly. Kubuntu was a different story altogether. Slow, oh so very slow. I was able to get maybe 2Mbps download max, but the biggest problem was the terrible latency; seconds for websites to open, ages for network shares to load. Now, let me tell you how you go about understanding you have a problem, isolating it, diagnosing, and then solving it.
Understand you have a problem
One might say - Linux sucks, this is how it's supposed to be. That's an answer, but then, in that case, you need not ever boot your Linux distro when the GRUB menu shows up on the screen.
What you need is a reference, a control group, something that works well. In this case, it can be another machine on the network, another operating system on the same box, something that is not the operating system you suspect might be faulty. This is very important, because it will help you isolate the problem to a specific part in your operational setup. It's called component search in statistical engineering.
If you go about the Interwebs, you will find a junk of unhelpful and misleading hints and tips that could sidetrack you from your problem. People will tell you about router firmware and ISP throttling Linux and all kinds of nonsense. So keep it together and proceed with caution.
Do other machines and/or operating systems on your network exhibit normal, expected performance? Yes? Then, the problem is NOT with your router, your configuration, your ISP, or the Bermuda Triangle. We narrow down the search to the specific instance of the operating system, in our case, Kubuntu 11.04.
Isolating the problem
Next, can you troubleshoot different network adapters on your box? Most people happen to have a single network interface on their machines, which is not recommended. I always go for two at the very least, both for redundancy in the case of a failure, but also because it gives me an extra angle when troubleshooting network-related issues.
In my Antec box, I have two Ethernet cards, one Intel and one Realtek, and one Wireless card, TP-Link N-band, which comes with Atheros firmware. To see what kind of hardware you have, you can run the lspci command, as sudo or root:
We want the network configuration, so here we go:
All right, so ask yourself, does the problem happen with other two cards? No? No. Then you know the problem is with the Realtek card for some reason. Or rather, the way the card is used in Linux, because it works fine in Windows.
Diagnose the problem
Now, you need to understand what causes the card to misbehave. One of the most basic checks is to issue the ifconfig command and see if you have any RX/TX dropped packets or errors. Indeed, doing this shows an abundance of dropped packets.
It seems that virtually all RX packets are dropped. But the card is not faulty. Then, this means the card is not used properly. Hence, we need to take a look at the kernel module that is used. Perhaps it has a bug?
With this in mind, your Internet searches will be meaningful. And you ought to stumble across a very intelligent and useful post by Jameson Williams, who tells you about the bad Realtek driver being used in Ubuntu. The sad thing is, this was written for Hardy and the problem still remains.
Solving the problem
We will now remove the existing Realtek module from memory with the rmmod command, blacklist it from future use, download the latest driver source from the Realtek website, compile the module, make it available, and rebuild the initrd file. All of this is written in detail in the above post. However, here are a few more important details you need to pay attention to.
Build essential tools
To compile, you will need kernel source, kernel headers, gcc, make, and a few other tools. You can install them all by running apt-get install build-essential. Now, we did talk about this very procedure in my oldie but goodie Linux commands & configurations tutorial, which as it happens, remains still very much valid and useful today.
Make sure you backup the files you are replacing or editing. Don't delete the old, offending module, just move it aside. Don't destroy the old initrd file under /boot, make a backup. And so forth. It costs you only a few KB of disk space, but it could save you hours of trouble in case something goes wrong.
The procedure in a nutshell
Let's most briefly recap what you need to do. Install build-essential tools, good. Next, compile the module.
tar xjv <downloaded Realtek source code>.tar.bz2
cd <extracted Realtek source code dir>
sudo make install
The last command requires sudo, as it will copy the created module, with the .ko extension into a system directory, so it can be used every time you boot and you won't need to manually insert it into memory. Just as we did five years back on Dapper!
Removing the module is done by running rmmod <name>. You need to find the right name of your Realtek card module. It's normally rXXXX something, where the right sequence of numbers is available through lspci -v command we used earlier. Now, you will notice Kubuntu uses r8169 module, whereas my machine has a r8168 card. This is an obvious discrepancy and quite likely the root cause of the problem.
Before you can remove the module from memory, you might need to stop the network interface. Then, you can verify that the module is no longer in use by running the lsmod command, and if the count shows as 0, remove it with rmmod:
sudo ifconfig <Realtek card, e.g. eth0> down
lsmod | grep r81XX
sudo rmmod r81XX
The module is removed. You can now insert the new one you just compiled:
sudo insmod r8168.ko
You might need to specify the full path for the module, either under the src subdirectory where you compiled or the system path under:
You might also want to run depmod before loading the module, as mentioned in the tutorial above, but this might not be necessary as the module is standalone and does not have dependencies. Now, check that everything works. If it does, blacklist the old, bad module:
cp /etc/modprobe.d/blacklist /etc/modprobe.d/blacklist.bak
sudo echo "blacklist r8169" >> /etc/modprobe.d/blacklist
You can also manually open the file in a text editor and add the blacklist r8168 line. Next, you should rebuild the initrd image, with the necessary backup. You do not need to reboot to test, if the module is loaded and works fine, but you might want to do that, just in case.
Testing we get this:
All is well. Problem solved. We can enjoy the Internets now!
There's one thing you must remember. Every time there's a kernel update, you might need to recompile your module. So if you network card suddenly stops working, redo this section from scratch. It's a bit tiring, but surely better than a crippled functionality.
Note: You don't really need to recompile. There's an alternative method that will do this automatically for you. It's about using the Dynamic Kernel Module support (DKMS). Now, this is a separate topic, but remember the acronym.
Among many suggestions you will find online, there's also disabling of ipv6, which could be the source of your problem. I sincerely doubt it, because if your router does not handle ipv6, then there's nothing to cause the problem. But just in case, you might want to attempt the following hacks. However, seems useless, so feel free to ignore.
Blacklist ipv6 module from loading
It's the same thing as above, add blacklist ipv6 line to the blacklist file.
sudo echo "blacklist ipv6" >> /etc/modprobe.d/blacklist
Change sysctl.conf parameters
You can also issue commands live into the kernel, either by issuing values to /proc or changing the /etc/sysctl.conf configuration file and reloading its values, but the two amount to the same thing. You can do this rather than blacklist modules, or you can attempt both if you feel naughty.
You will need to be root to issue commands to /proc. So you need to sudo su.
sudo su -
echo 1 > /proc/sys/net/ipv6/conf/all/disable_ipv6
echo 1 > /proc/sys/net/ipv6/conf/default/disable_ipv6
echo 1 > /proc/sys/net/ipv6/conf/lo/disable_ipv6
Alternatively, edit /etc/sysctl.conf:
net.ipv6.conf.all.disable = 1
net.ipv6.conf.default.disable = 1
net.ipv6.conf.lo.disable = 1
And reload the configuration:
sudo sysctl -p
And you're done. There's also a GRUB hack, but why bother.
However, remember, this might cripple some of your functionality, so don't do this unless you fully understand what you're doing. Most people do not yet need ipv6, but just remember what you've done and how to do undo it if necessary.
There you go. This tutorial has taught you how to understand, isolate, diagnose, and solve a rather tricky problem with network performance stemming from a bad driver. Along the way, we learned the importance of having a solid and sane baseline to refer to and compare, we utilized the nifty component search method, we learned how to compile modules and insert them into memory and make them available on next boot. We fiddled with system configuration files, and we now understand our network stack a little better.
Mission accomplished. Our Realtek card does not suck after all, nor does Kubuntu. It's just one bad little driver causing congestion and all. No pun intended, hihihi. Well, that would be all. Enjoy.
Thanks to ___Searching, Maxim and Francisco for their suggestions.