[lwip-users] Getting the server to use an MSS larger than 536

386 views
Skip to first unread message

Mason

unread,
Mar 21, 2012, 11:26:09 AM3/21/12
to Mailing list for lwIP users
Hello,

Consider the attached Wireshark trace of a simple HTTP request:

GET / HTTP/1.1
Host: www.google.fr
Accept: */*

223.200.200.68 = set-top box using lwip+libcurl
223.200.200.254 = LAN gateway
223.200.200.204 = LAN DNS server
173.194.78.94 = google.fr (apparently)

Note that Google sends only 590-byte frames. How do I get lwip
to advertize larger MSS?

NB: I have the following TCP-related definitions in my lwipopts.h

#define TCP_MSS 1460
#define TCP_WND (40*TCP_MSS)
#define TCP_SND_BUF (8*TCP_MSS)
#define TCP_SND_QUEUELEN 16

There's relevant code in src/core/tcp.c

pcb->snd_wnd = TCP_WND;
/* As initial send MSS, we use TCP_MSS but limit it to 536.
The send MSS is updated when an MSS option is received. */
pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
#if TCP_CALCULATE_EFF_SEND_MSS
pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */

(TCP_CALCULATE_EFF_SEND_MSS is 1 by default)
/**
* TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really
* sends, the 'effective send MSS,' MUST be the smaller of the send MSS (which
* reflects the available reassembly buffer size at the remote host) and the
* largest size permitted by the IP layer" (RFC 1122)
* Setting this to 1 enables code that checks TCP_MSS against the MTU of the
* netif used for a connection and limits the MSS if it would be too big otherwise.
*/

(My MTU is 1500, I'm using Ethernet.)

When I receive Google's SYN+ACK packet with MSS=1430 in
tcp_parseopt, the pcb mss is correctly set to 1430. Perhaps
this is only the /write/ MSS?

How can I make Google send larger datagrams?

Is this a Path MTU Discovery issue?

--
Regards.

curl_google_from_STB.pcap

Simon Goldschmidt

unread,
Mar 21, 2012, 12:00:05 PM3/21/12
to Mailing list for lwIP users
Mason <mpeg...@free.fr> wrote:
> Note that Google sends only 590-byte frames. How do I get lwip
> to advertize larger MSS?
>
> NB: I have the following TCP-related definitions in my lwipopts.h
>
> #define TCP_MSS 1460
> #define TCP_WND (40*TCP_MSS)
> #define TCP_SND_BUF (8*TCP_MSS)
> #define TCP_SND_QUEUELEN 16
>
> There's relevant code in src/core/tcp.c
>
> pcb->snd_wnd = TCP_WND;
> /* As initial send MSS, we use TCP_MSS but limit it to 536.
> The send MSS is updated when an MSS option is received. */
> pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
> #if TCP_CALCULATE_EFF_SEND_MSS
> pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
> #endif /* TCP_CALCULATE_EFF_SEND_MSS */
>
> [..]

>
> (My MTU is 1500, I'm using Ethernet.)

In that case (if you have set netif->mtu to 1500), tcp_eff_send_mss() should return 1460 (1500 - IP_HLEN - TCP_HLEN). If it doesn't, possible problems could be that ip_route() doesn't return your netif or that netif->mtu isn't set to 1500.

> When I receive Google's SYN+ACK packet with MSS=1430 in
> tcp_parseopt, the pcb mss is correctly set to 1430. Perhaps
> this is only the /write/ MSS?

Yes, this is lwIP's send MSS, while the initial pcb->mss is used to construct an MSS option in the initial SYN packet sent on connect.

> How can I make Google send larger datagrams?

You should check the MSS option in the SYN packet sent to the Google server.

> Is this a Path MTU Discovery issue?

No.


Simon
--
Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir
belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de

_______________________________________________
lwip-users mailing list
lwip-...@nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users

Mason

unread,
Mar 21, 2012, 12:28:04 PM3/21/12
to Mailing list for lwIP users
Simon Goldschmidt wrote:

> Mason wrote:
>
>> Note that Google sends only 590-byte frames. How do I get lwip
>> to advertize larger MSS?
>>
>> NB: I have the following TCP-related definitions in my lwipopts.h
>>
>> #define TCP_MSS 1460
>> #define TCP_WND (40*TCP_MSS)
>> #define TCP_SND_BUF (8*TCP_MSS)
>> #define TCP_SND_QUEUELEN 16
>>
>> There's relevant code in src/core/tcp.c
>>
>> pcb->snd_wnd = TCP_WND;
>> /* As initial send MSS, we use TCP_MSS but limit it to 536.
>> The send MSS is updated when an MSS option is received. */
>> pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
>> #if TCP_CALCULATE_EFF_SEND_MSS
>> pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
>> #endif /* TCP_CALCULATE_EFF_SEND_MSS */
>>
>> [..]
>>
>> (My MTU is 1500, I'm using Ethernet.)
>
> In that case (if you have set netif->mtu to 1500), tcp_eff_send_mss()
> should return 1460 (1500 - IP_HLEN - TCP_HLEN). If it doesn't,
> possible problems could be that ip_route() doesn't return your netif
> or that netif->mtu isn't set to 1500.

tcp_eff_send_mss will never return 1460 if it is called with
536 as the first parameter, since it returns the minimum of
first parameter and MTU (minus headers).

pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;

pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);

First statement is equivalent to pcb->mss = LWIP_MIN(536, TCP_MSS);
and sets pcb->mss to 536.
Second statement calls tcp_eff_send_mss(536, ipaddr);

Why is the MSS being clipped in the first statement?

/**
* Calcluates the effective send mss that can be used for a specific IP address
* by using ip_route to determin the netif used to send to the address and
* calculating the minimum of TCP_MSS and that netif's mtu (if set).
*/
u16_t
tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr)
{
u16_t mss_s;
struct netif *outif;

outif = ip_route(addr);
if ((outif != NULL) && (outif->mtu != 0)) {
mss_s = outif->mtu - IP_HLEN - TCP_HLEN;
/* RFC 1122, chap 4.2.2.6:
* Eff.snd.MSS = min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
* We correct for TCP options in tcp_write(), and don't support IP options.
*/
sendmss = LWIP_MIN(sendmss, mss_s);
}
return sendmss;
}

NB: the comment does not match the code. We're not dealing with
TCP_MSS, but a clipped value of TCP_MSS.

> You should check the MSS option in the SYN packet sent to the Google server.

I did! (cf. trace) lwip advertizes a 536-byte MSS.

--
Regards.

Mason

unread,
Mar 21, 2012, 12:45:52 PM3/21/12
to Mailing list for lwIP users
Simon Goldschmidt wrote:

> Mason wrote:
>
>> Note that Google sends only 590-byte frames. How do I get lwip
>> to advertize larger MSS?
>>
>> NB: I have the following TCP-related definitions in my lwipopts.h
>>
>> #define TCP_MSS 1460
>> #define TCP_WND (40*TCP_MSS)
>> #define TCP_SND_BUF (8*TCP_MSS)
>> #define TCP_SND_QUEUELEN 16
>>
>> There's relevant code in src/core/tcp.c
>>
>> pcb->snd_wnd = TCP_WND;
>> /* As initial send MSS, we use TCP_MSS but limit it to 536.
>> The send MSS is updated when an MSS option is received. */
>> pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
>> #if TCP_CALCULATE_EFF_SEND_MSS
>> pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
>> #endif /* TCP_CALCULATE_EFF_SEND_MSS */
>

> In that case (if you have set netif->mtu to 1500), tcp_eff_send_mss()
> should return 1460 (1500 - IP_HLEN - TCP_HLEN). If it doesn't,
> possible problems could be that ip_route() doesn't return your netif
> or that netif->mtu isn't set to 1500.
>
>> When I receive Google's SYN+ACK packet with MSS=1430 in
>> tcp_parseopt, the pcb mss is correctly set to 1430. Perhaps
>> this is only the /write/ MSS?
>
> Yes, this is lwIP's send MSS, while the initial pcb->mss is used to
> construct an MSS option in the initial SYN packet sent on connect.

Applying the following patch makes the distant system send larger
frames (1484 bytes in Google's case, 1430-byte segment).

--- tcp.c.orig 2012-02-23 10:57:12.843750000 +0100
+++ tcp.c 2012-03-21 17:29:25.515625000 +0100
@@ -749,7 +749,7 @@


pcb->snd_wnd = TCP_WND;
/* As initial send MSS, we use TCP_MSS but limit it to 536.
The send MSS is updated when an MSS option is received. */

- pcb->mss = (TCP_MSS > 536) ? 536 : TCP_MSS;
+ pcb->mss = TCP_MSS;


#if TCP_CALCULATE_EFF_SEND_MSS
pcb->mss = tcp_eff_send_mss(pcb->mss, ipaddr);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */

I don't understand the comment explaining why the MSS is clipped.
Does this come from an RFC?

Relevant commits are:
http://git.savannah.gnu.org/cgit/lwip.git/commit/?id=2d5908f4dedeac4ae2f568bd6f06ea218de5a125
http://git.savannah.gnu.org/cgit/lwip.git/commit/?id=aee9c4c8e6c9ec54783f3657c40be96753c72dd9

--
Regards.

Mason

unread,
Mar 21, 2012, 1:14:24 PM3/21/12
to Mailing list for lwIP users
Mason wrote:

> I don't understand the comment explaining why the MSS is clipped.
> Does this come from an RFC?

For my own records, relevant RFC is
http://tools.ietf.org/html/rfc879

Reply all
Reply to author
Forward
0 new messages