DMYTRO SHYTYI

MPTCP Fast Open in linux kernel

This set of patches will bring “Fast Open” Option support to MPTCP in linux kernel. The aim of Fast Open Mechanism is to eliminate one round trip time from a MPTCP conversation by allowing data to be included as part of the SYN segment that initiates the connection.

IETF RFC 8684: Appendix B. TCP Fast Open and MPTCP. IETF RFC LINK

These new patches (LWN | ML: mptcp.lists.linux.dev) provide the full support of TFO with MPTCP,
which means:

– MSG_FASTOPEN sendmsg flag support (patch 1/8)
– TFO support for the listener side (patches 2345/8)
– TCP_FASTOPEN socket option (patch 6/8)
– TCP_FASTOPEN_KEY socket option (patch 7/8)
– SELFTESTS (patch 8/8)

2 methods to Request a cookie (in MPTCP) are currently exist:

1) Listener side + Initator side with: MSG_FASTOPEN
LWN publication: https://lwn.net/Articles/916023/
2) Initiator side with: TCP_FASTOPEN_CONNECT
LWN publication https://lwn.net/Articles/909590/

Code examples for initiator side:
MSG_FASTOPEN (Updated on 6 Nov. 2022)
Here is example of Initiator in userspace program written in C

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include <string.h>
#include <signal.h>

#define SERVER_PORT 7003
#define MAXLINE 999

int main(int argc, char *argv[])
{
	char sendline[MAXLINE + 1], recvline[MAXLINE + 1];
	char *fileLocation = "./fileToDownload";
	char *serverAddress = "10.10.0.2:1234"
	int sock_fd = -1;
	int ret;
	/* Generate HTTP GET into variable sendline*/	
	snprintf(sendline, 999, 
         "GET %s HTTP/1.0\r\n"   
         "Host: %s\r\n"     
         "Content-type: application/x-www-form-urlencoded\r\n"
         "Content-length: %d\r\n\r\n"
         "%s\r\n", fileLocation, serverAddress , (unsigned int)strlen(""), "");



	
	struct sockaddr_in daddr;
	memset(&daddr,0,sizeof(daddr));      
	inet_pton(AF_INET, "10.10.0.2", &daddr.sin_addr);
	daddr.sin_family = AF_INET;
	daddr.sin_port = htons(SERVER_PORT); 	

	/* set the mprotocol MPTCP */
	sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);
 
	/* set the MSG_FASTOPEN */
	ret = sendto(sock_fd, sendline, strlen(sendline), MSG_FASTOPEN,(struct sockaddr *) &daddr, sizeof(daddr));

	printf ("info: %d \n", ret);	
	close(sock_fd);
	return EXIT_SUCCESS;

}

PacketDrill test: Link to Github
PacketDrill test result: Link to Github

Here is example of Initiator in userspace program written in C:

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/tcp.h>
#include <string.h>
#include <signal.h>

#define SERVER_PORT 7003
#define MAXLINE 999

int main(int argc, char *argv[])
{
	char sendline[MAXLINE + 1], recvline[MAXLINE + 1];
	struct sockaddr_in daddr;
	int sock_fd = -1;
	int enable = 1;
	int ret;

	snprintf(sendline, 999, 
     "GET %s HTTP/1.0\r\n"  // POST or GET, both tested and works. Both HTTP 1.0 HTTP 1.1 works, but sometimes 
     "Host: %s\r\n"     // but sometimes HTTP 1.0 works better in localhost type
     "Content-type: application/x-www-form-urlencoded\r\n"
     "Content-length: %d\r\n\r\n"
     "%s\r\n", "/prepare2.sh", "6.6.6.6:666" , (unsigned int)strlen(""), "")
	
	memset(&daddr,0,sizeof(daddr));      
	inet_pton(AF_INET, "6.6.6.6", &daddr.sin_addr);
	daddr.sin_family = AF_INET;
	daddr.sin_port = htons(SERVER_PORT); 	
	
	/* set the mprotocol MPTCP */
	sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);
 
	/* set the TCP_FASTOPEN_CONNECT */
	setsockopt(sock_fd, SOL_TCP, TCP_FASTOPEN_CONNECT, &enable, sizeof(enable)); 
	connect(sock_fd, (struct sockaddr *) &daddr, sizeof(daddr)); 
	ret = sendto(sock_fd, sendline, strlen(sendline), 0,(struct sockaddr *) &daddr, sizeof(daddr));
	
	printf ("info: %d \n", ret);
	close(sock_fd);
	return EXIT_SUCCESS;

}

Environment configuration (linux) for TCP_FASTOPEN:

sudo modprobe veth
sudo ip netns add server
sudo ip netns add client
sudo ip link add veth0 type veth peer name veth1
sudo ip link set veth1 netns server
sudo ip link set veth0 netns client
sudo ip netns exec client ip a a 10.10.0.1/24 dev veth0
sudo ip netns exec server ip a a 10.10.0.2/24 dev veth1
sudo ip netns exec client ip link set dev  veth0 up
sudo ip netns exec server ip link set dev  veth1 up

sudo ip netns exec server bash -c "echo 3 > /proc/sys/net/ipv4/tcp_fastopen"
sudo ip netns exec client bash -c "echo 3 > /proc/sys/net/ipv4/tcp_fastopen"

Thank you for reading.