tcp缓冲区大小不对称

Time: 五月 12, 2014
Category: tcp/ip internals

今天写单元测试时发现setsockopt/getsockopt在设置SO_SNDBUF/SO_RCVBUF参数时不对应,getsockopt拿到的并不是setsockopt时的值
下面代码可以说明这个问题:

    on = 1024;
    BUG_ON(tcp_setopt(sfd, TP_NOBLOCK, &on, sizeof(on)));
    BUG_ON(tcp_getopt(sfd, TP_NOBLOCK, &on, &optlen));
    BUG_ON(on != 1024);

内核最终设置的值会发生变化,例如可能double,等等,redhat上的BUG反映:https://bugzilla.redhat.com/show_bug.cgi?id=170694
我的内核版本是:Centos 6.5 2.6.32-431.5.1.el6.x86_64 #1 SMP
翻了一下内核源码,linux-2.6.32-358.6.2.el6/net/core/


/*
 *	This is meant for all protocols to use and covers goings on
 *	at the socket level. Everything here is generic.
 */

int sock_setsockopt(struct socket *sock, int level, int optname,
		    char __user *optval, unsigned int optlen)
{
	// ...
	case SO_SNDBUF:
		/* Don't error on this BSD doesn't and if you think
		   about it this is right. Otherwise apps have to
		   play 'guess the biggest size' games. RCVBUF/SNDBUF
		   are treated in BSD as hints */

		if (val > sysctl_wmem_max)
			val = sysctl_wmem_max;
set_sndbuf:
		sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
		if ((val * 2) < SOCK_MIN_SNDBUF)
			sk->sk_sndbuf = SOCK_MIN_SNDBUF;
		else
			sk->sk_sndbuf = val * 2;

		/*
		 *	Wake up sending tasks if we
		 *	upped the value.
		 */
		sk->sk_write_space(sk);
		break;
	// ...

原来如此,内核对输入的参数做了适当调整

Leave a Comment