Kenichi Okuyama
Based Japanese version Date: 2000/05/15 01:22:21
Based Japanese version Revision: 1.6
English version $Date: 2015-12-22 01:14:57 +0900 (Tue, 22 Dec 2015) $
English version $Revision: 1.4 $
The English version of this document is owing to the Samba-jp list. If you found any problems on this document, please give a knowtice to okuyamak at dd.iij4u.or.jp .
Sometimes you experience incredibly slow transfer speed while using Samba as a file server and/or print server on a Linux or FreeBSD machine from a Windows client.
If the speed with Windows NT Server is as slow, you may take it for granted. However, you can't be patient when Samba is slow against Windows NT.
This document describes how to reconfigure the smb.conf in order to gain the same speed as Windows NT in such an occasion.
Since Samba is installed on a unix machine, it uses unix's TCP/IP layer for connection. Windows client uses Winsock2, which is also TCP/IP layer, to connect to Samba server.
Generally, the TCP/IP layer of a Unix machine is strictly conformed to RFC. Therefore it will send IP packets as many as the receiver permits by TCP window size. Ack means 'being ready to receive the next packet'. If Ack is received, it would shift a transmission area window and send data in that window. The byte length of the above transmission area window is called 'Send Buffer Size'. In smb.conf SO_SNDBUF parameter within 'socket options' will specify the size of this transmission area window .
In Unix, this size is very large, e.g. in FreeBSD its default is 16384 bytes. Such a large Send Buffer Size is intolerable for most of Windows machines. That is why Send Buffer Size is made small by setting the parameter of socket options in smb.conf. So far, size such as 8192 bytes are recommended. This size will slightly adapted to become optimized in progress of TCP communication.
But, strange to say, data packets are dropped accidentally on a Windows machines with a particular Network Interface Card (NIC). It can be because of NIC, NIC driver, Winsock, or Windows itself, but I have not found the reasons. Even if Receive Buffer Size is large enough, some packets will be dropped.
When a data packet is dropped, a resend request is transmitted. This resend request is performed by transmitting several Ack packets showing that reception up to how many bytes is completed .
Samba (to be strict the TCP driver of a Unix machine running Samba) will anyway resend a packet in response to such Ack packets.
As it is just one packet that Windows has dropped, when data has reached from Samba, Ack will proceed by several packets at a time. Then after a while (i.e. only 15 msec or so) Windows will drop a packet again.
After these things were repeated several times, TCP layer of Samba will anticipate as follows:
"Some packet's arraival might be delayed for some reasons. Let's wait for a while for delayed Ack packet".
Then, it will try to send nothing for about one second. Eventually,the condition does not become better, and Samba's TCP layer will decide to resend a data packet.
If Windows machine will cause this problem, data transmitting will occur for 0.1 - 0.3 seconds and then wait for 1 second, repeatingly. Moreover, this value of one second will actually become bigger each time of waiting. Consequently, the effective transfer speed become 1/20 of the real speed that should be obtained.
If this will occur in any OS, you may take it for granted. However, this will not happen on case of Windows NT server. Then Samba server looks as if it's performance is worse than Windows NT.
Unfortunately the source code of Winsock2 is not available. And so with Windows, ether. Therefore, the reason for this phenomenon is not known exactly. But, to some extent the characteristics of the communication in Winsock2 can be examined using such tools as tcpdump and WinDump . At least the characteristics I found are as follows:
You can easily guess that, if NIC Driver is implemented so as to satisfy only this characteristics of Winsock2, it works fast with NT server but slowly with Samba server .
You need some information to configure smb.conf so as to obtain at least the same performance as NT in case of being fast with NT but slow with Samba.
First, you need root permission on Samba Server. Since you are going to edit smb.conf, usually this may not be the problem.
Next, you need to know how to use tcpdump. If you are root, you can execute tcpdump. But you must know how to use tcpdump ( or if you are going to observe on Windows machine, WinDump ). If only one NIC is installed, all you need to do is
# tcpdump > logfile
However, if a number of NIC's are installed, you need to specify which NIC to get data. Please learn how to use tcpdump by reading the manual carefully. In addition, it is better to be able to read output results. (However, through some experiences you will understand required information.)
Moreover, you need to know about OS and Internet machine name of a machine in question , and must have permission to operate that machine (without this permission, you can't run performance tests).
Then please prepare for a sample file whose size is about 5 to 10 MB. This file will be used for performance test.
Now, in the following example we assume that Samba Server's machine name is Nohshi.my.domain , and machine name of Windows client (Windows98) is Ayame.my.domain .
First, please execute tcpdump on Nohshi. Since you need to examine the log later, run:
# tcpdump > logfile
Next, from Ayame, open Nohshi.
Please execute file transfer from Nohshi to Ayame. When transferring a file, you can either Drug&Drop a window or do FTP . This is because it's a problem of Winsock2 and not of SMB protocol. You can use any thing as long as it uses TCP.
After completion of file transfer please stop tcpdump, using Ctrl-C for example. But you should not stop it with 'kill -9'. Logs near the end may not be produced.
TCP communication logs must have been stored in logfile. Search
There should be a line with string
Ayame.my.domain > Nohshi.my.domain
and
Nohshi.my.domain > Ayame.my.domain
Please examine both lines and choose one containing numeral xxxx smaller than the other. This numeral is called Maximum Segment Size mss . When using ethernet, usually it's either 1460 or 536. This describes the maximum size of data which can be contained in a single IP packet.
At file smb.conf, end of [global] section, add following lines.
include = <directory containing smb.conf>/smb.conf.global.%a include = <directory containing smb.conf>/smb.conf.global.%M include = <directory containing smb.conf>/smb.conf.global.%a.%M
In FreeBSD, <directory containing smb.conf> is /usr/local/etc , which may be different according to OS. Please specify an appropriate directory.
Please create a file smb.conf.global.ayame.my.domain in the same directory as smb.conf. Add following line to that file.
socket options = TCP_NODELAY SO_SNDBUF=yyyy
yyyy is actually numeral exactly twice the value of mss obtained previously. In case of a poor NIC, even one byte greater value will suddenly cause the terribly low performance.
Finally restart smbd.
You can create a configuration file for a specific OS as smb.conf.global.<OS name> and for a specific OS on a specific machine (e.g. multi-boot) as smb.conf.global.<OS name>.<Machine name> .
%M is internet machine name.
%a is OS specific, a string for each OS as described in the manual of smb.conf.
Why does this work?
From Winsock2's log, we can easily guess that after receiving two IP packet, Winsock2 will concentrate on sending Ack packet. No data will be pulled from Ethernet Driver, and as result, NIC, or NIC driver's buffer will cause overflood and drop packet.
We can also guess that, the reason why this will not happen on NT is that when "Receiver" consentrate on sending Ack, "Sender" consentrate on receiving Ack, not sending anything.
Then, it is quite clear that, by changing the sender(Samba server)'s Send Buffer Size to exactly twice the size of mss, we can make sender to send only two IP packet at a time then wait for ack. As result of this, since there will be no packet dropping, we'll earn more transfer speed.
Actually, even in case of the other, more effective NIC, it should be better to set SO_SNDBUF size to multiple number of mss. Hence so, compare to setting SO_SNDBUF to 8192 byte, it is better to set it to 8576 bytes in case mss is 536bytes ( since 8192/536 = 15.2...., 16*536 = 8576), and 8760 bytes in case mss is 1460 bytes ( 8192/1460 = 5.61... so 6 * 1460= 8760).
If you have no idea which mss( i.e. 536 or 1460 ) to come, I suggest using 8576. It still should be little more effective than 8192.
Generally speaking, mss * n ( n to be natural number ) is a proper number for SO_SNDBUF to be set. You can easily recognize the limit, for transfer speed will be drastically slow if you exceed the limit size even by 1 packet size, for that 1 packet will cause packet lost . It is good idea to look for limit by changing n.
Also, the above smb.conf uses the following two features which are not clearly written in manual.
Once you made this establishment, transfer rate for accessing from ayame.my.domain to nohshi.my.domain will become independent from which NIC you will use. This means, the performance will not be improved, even if you bought and installed higher performance NIC to ayame. It is because server ignores the NIC performance and sends data only little by little.
So, if you want to gain performance, you'll have to delete, or revise 'smb.conf.global.Ayame.my.domain' ( or any other appropriate config file) to change the parameters to more effective one.
If you have any Comment, Information, Errata about this page, please give a knotice to Okuyama .