Monday, December 18th 2017, 9:42am UTC+1

You are not logged in.

  • Login
  • Register

Dear visitor, welcome to SEGGER Forum. If this is your first visit here, please read the Help. It explains how this page works. You must be registered before you can use all the page's features. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

pawdrexel

Beginner

Date of registration: Nov 15th 2011

Posts: 4

Location: Coquitlam, BC, Canada

Occupation: Electrical Engineer

1

Friday, December 16th 2011, 12:22am

TCP Window Scaling Option

embOS/IP's support for TCP window scaling is incomplete and I think there may be a bug in the code that prevents proper support.

Window scaling allows a host to specify receive/send windows that are larger than 65535 bytes by specifying an optional scaling factor during the connection (SYN) phase. This is useful in cases where the receiver has a lot of memory (say a PC) and the sender has a lot of data to send quickly. Of course, the sender needs a fair amount of memory too in order to hold the TCP packets that are waiting for ACKs. However, many of today's MCUs have external memory controllers that can access many megabytes of RAM (e.g., NXP LPC246).

According to pages 864 - 866 of "TCP/IP Illustrated - Volume 2: The Implementation" by Wright & Stevens, a client (connecting) host can request window scaling by specifying a 3-byte option in the TCP options portion of the header. In order for the option to be accepted, however, the server host must respond with the window scaling option in its SYN packet. embOS/IP includes some fo the code necessary for supporting this capability, but it's incomplete. The changes I believe are necessary (there may be more) to get embOS/IP to respond properly are

1) IP_socket.c, sosetopt() function

Add an additional SO_WINSCALE case to the switch statement (line 16). Also, after creating a socket, your code must call setsockopt( sock, SOL_SOCKET, SO_WINSCALE, NULL, 0 ); to enable window scaling support.

C/C++ Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  switch (optname) {
  case SO_LINGER:
	so->so_linger = (short) ((struct linger *)arg)->l_linger;
	arg = &((struct linger *)arg)->l_onoff;
	// Fall through
  case SO_KEEPALIVE:
  case SO_DONTROUTE:
  case SO_BROADCAST:
  case SO_REUSEADDR:
  case SO_OOBINLINE:
  case SO_TCPSACK:
  case SO_NOSLOWSTART:
#ifdef SUPPORT_SO_FULLMSS
  case SO_FULLMSS:
#endif
  case SO_WINSCALE:
	if (*(int *)arg) {
  	so->so_options |= optname;
	} else {
  	so->so_options &= ~optname;
	}
	break;


2) IP_TCP_in.c, _HandleOptions() function

Fix what I think is a bug by changing this (line 6)

C/C++ Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
  //
  // Compute True MSS based on mss and Option lne
  //
  if (ti->ti_flags & TH_SYN) {   /* MSS only on SYN */
	int OptLen = 0;
	if (tp->t_flags &= TF_TIMESTAMP) {
  	OptLen += 12;
	}
	tp->OptLen  = OptLen;
	tp->TrueMSS = tp->Mss - OptLen;
	tp->snd_cwnd = 0xFFFF;   // Use max. value initially
  }
  return;


to this (line 6)

C/C++ Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
  //
  // Compute True MSS based on mss and Option lne
  //
  if (ti->ti_flags & TH_SYN) {   /* MSS only on SYN */
	int OptLen = 0;
	if (tp->t_flags & TF_TIMESTAMP) {
  	OptLen += 12;
	}
	tp->OptLen  = OptLen;
	tp->TrueMSS = tp->Mss - OptLen;
	tp->snd_cwnd = 0xFFFF;   // Use max. value initially
  }
  return;


3) If window scaling is going to be supported generally, then the SO_WINSCALE option should be documented in the user manual.

I have tested changes (1) & (2) with a Windows XP PC as a client requesting 8x window scaling and observed the results in WireShark. The window scaling options do appear in the SYN packets as expected. Also, using a debugger, I have observed that the embOS/IP TCP control block field "snd_wnd" is expanded by the scaling factor as requested by the PC. Further testing, however, is required to ensure that TCP packets are sent, ACKed and disposed of properly.