Setting the mss for socket

Luiz Otavio O Souza lists.br at gmail.com
Sat Apr 4 06:50:55 PDT 2009


> Luiz Otavio O Souza wrote:
>>>> Is there a way to set the mss for a socket ? Like you can do
>>>> in linux with setsockopt(TCP_MAXSEG) ?
>>>>
>>>> So i can set the maximum size of packets (or sort of) from a
>>>> simple userland program.
>>>
>>> Depending on exactly what you need to accomplish, you may
>>> find something useful in this thread from last August in
>>> freebsd-questions@
>>>
>>>  setting the other end's TCP segment size
>>
>> Very informative thread, thanks.
>>
>> This thread show me that TCP_MAXSEG is implemented in freebsd but don't
>> work. You can set the setsockopt(IPPROTO_TCP, TCP_MAXSEG), wich will set 
>> the
>> tp->t_maxseg, but this value is recalculated at tcp_input, so in short, 
>> you
>> cannot set the max segment size for a socket.
>>
>> I've posted a completly wrong patch (from style point-of-view - and using
>> SOL_SOCKET instead of IPPROTO_TCP), but with that patch i'm able to set 
>> the
>> mss in iperf.
>
> this thread shoud be in FreeBSD-net@ so tha the right people see it
> many developers do not read hackers every day as it tends to overload 
> them.

The above patch is a better fix for this, it fix the setsockopt(IPPROTO_TCP, 
TCP_MAXSEG), so iperf (and other userland programs) works by default.

It's clear on code that tp->t_maxseg should not be changed, at least in this 
situation (it keeps the maximum mss for connection and it is used to 
calculate the tcp window scaling). tp->t_maxseg is also reseted to maxmtu 
(or rmx_mtu) at tcp_mss_update().

So here is the patch: http://loos.no-ip.org/downloads/mss-patch

Thanks
Luiz 
-------------- next part --------------
--- netinet/socketvar.h.orig	2009-04-03 22:29:34.000000000 -0300
+++ netinet/socketvar.h	2009-04-03 22:29:44.000000000 -0300
@@ -115,6 +115,7 @@
 		char	*so_accept_filter_str;	/* saved user args */
 	} *so_accf;
 	int so_fibnum;		/* routing domain for this socket */
+	int so_maxseg;		/* maxseg this socket */
 };
 
 /*
--- netinet/tcp_usrreq.c.orig	2009-04-03 22:24:53.000000000 -0300
+++ netinet/tcp_usrreq.c	2009-04-03 23:26:35.000000000 -0300
@@ -1352,9 +1352,8 @@
 				return (error);
 
 			INP_WLOCK_RECHECK(inp);
-			if (optval > 0 && optval <= tp->t_maxseg &&
-			    optval + 40 >= V_tcp_minmss)
-				tp->t_maxseg = optval;
+			if (optval >= 40 && optval <= tp->t_maxseg)
+				so->so_maxseg = optval;
 			else
 				error = EINVAL;
 			INP_WUNLOCK(inp);
@@ -1389,7 +1388,10 @@
 			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
 		case TCP_MAXSEG:
-			optval = tp->t_maxseg;
+			if (so->so_maxseg)
+				optval = so->so_maxseg;
+			else
+				optval = tp->t_maxseg;
 			INP_WUNLOCK(inp);
 			error = sooptcopyout(sopt, &optval, sizeof optval);
 			break;
--- netinet/tcp_output.c.orig	2009-04-02 22:48:04.000000000 -0300
+++ netinet/tcp_output.c	2009-04-03 23:28:07.000000000 -0300
@@ -493,6 +493,11 @@
 		}
 	}
 
+	if (so->so_maxseg && len > so->so_maxseg) {
+	    len = so->so_maxseg;
+	    sendalot = 1;
+	}
+
 	if (sack_rxmit) {
 		if (SEQ_LT(p->rxmit + len, tp->snd_una + so->so_snd.sb_cc))
 			flags &= ~TH_FIN;
@@ -518,6 +523,8 @@
 	if (len) {
 		if (len >= tp->t_maxseg)
 			goto send;
+		if (so->so_maxseg && len >= so->so_maxseg)
+			goto send;
 		/*
 		 * NOTE! on localhost connections an 'ack' from the remote
 		 * end may occur synchronously with the output and cause


More information about the freebsd-net mailing list