lkml.org 
[lkml]   [2000]   [Aug]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectTCP_MAXSEG and getsockopt()


It looks like getsockopt() function call always returns a default value of zero for MSS parameter (maximum segement size) unless the user has preset it to some different value by calling setsockopt().
Checking with the source code (net/ipv4/tcp_output.c) I have discovered that Linux uses three different variables for MSS (listed below are fragments form comments found in lines 254-274 in the above mentioned source file):
- "user_mss is mss set by user by TCP_MAXSEG"
- "mss_cache is current effective sending mss"
- "mss_clamp is mss negotiated at connection setup.
It is minumum of user_mss and mss received with SYN"

As you may guess getsockopt()/setsockopt() when called w/ TCP_MAXSEG operates *only* on the user_mss. While I find perfectly normal for setsockopt() to operate on (that is : modify) user_mss - since the user should be provided w/ a meaning to express what he/she wants the mss to be - I don't find any good reason why getsockopt() should return the same value.
At least two reasons makes me belive this is an error:
1. The user program can always remember what value he passed to setsockopt(), if any. Besides of that any system call , including getsockopt()should take longer than a in-memory access in user space.
2. Other implementations of TCP/IP protocol notably SunOS) return correct value. See the source code at the end of this email of a small test application that has been used to verify this assumption.

IMHO getsockopt() should return the value of mss_cache variable. Enclosed is a patch that should modify the kernel in this matter.

---------> CUT HERE <----------------
*** linux/net/ipv4/tcp.c Mon Aug 14 10:52:52 2000
--- - Mon Aug 14 11:01:58 2000
***************
*** 1764,1772 ****
len = min(len, sizeof(int));

switch(optname) {
case TCP_MAXSEG:
! val = tp->user_mss;
break;
case TCP_NODELAY:
val = (sk->nonagle == 1);
break;
--- 1764,1772 ----
len = min(len, sizeof(int));

switch(optname) {
case TCP_MAXSEG:
! val = tp->mss_cache;
break;
case TCP_NODELAY:
val = (sk->nonagle == 1);
break;
---------> CUT HERE <----------------

As promised here it is the source code of the test application that helped me to detect the above bug. The program has been tested on several Linux machines including:
2.2.14-12smp /i686
2.2.16-3 /alpha

---------> CUT HERE <----------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
int main(int argc, char **argv) {

struct sockaddr_in dest ;
unsigned int mss ;
socklen_t sl;
int s ;

if(argc != 3) {
fputs("USAGE: getmss.c <host_ip> <port>\n", stderr) ;
return 0 ;
}

s = socket(AF_INET, SOCK_STREAM, 0) ;
if(s == -1) {
perror("socket");
return -1 ;
}

memset(&dest, 0, sizeof(dest)) ;

dest.sin_family = AF_INET ;
dest.sin_addr.s_addr = inet_addr(argv[1]) ;
dest.sin_port = htons(atoi(argv[2]));

if(connect(s, &dest, sizeof(dest)) == -1) {
perror("connect");
close(s) ;
return -1 ;
}

fprintf(stderr, "Connected to %s on port %s !\n",
argv[1], argv[2]);

mss = 0 ;
sl = sizeof(mss) ;

if(getsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &mss, &sl) == -1) {
perror("getsockopt");
close(s) ;
return -1 ;
}

fprintf(stdout, "MSS = %u (sizeof(MSS) = %d)\n", mss, sl) ;
fflush(stdout) ;
close(s) ;

return 0 ;
}
---------> CUT HERE <----------------


------------------------------
K Free E-mail http://www.k.ro/
by KappaNet http://www.kappa.ro/




-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:58    [W:0.027 / U:0.028 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site