diff -Nur orig/include/net/inet_sock.h patched/include/net/inet_sock.h --- orig/include/net/inet_sock.h 2010-08-02 01:11:14.000000000 +0300 +++ patched/include/net/inet_sock.h 2011-03-26 07:41:39.569716034 +0200 @@ -150,6 +150,7 @@ __be32 addr; struct flowi fl; } cork; + __u16 zph_tos; /* ZPH TOS received on connect */ }; #define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */ diff -Nur orig/net/ipv4/ip_sockglue.c patched/net/ipv4/ip_sockglue.c --- orig/net/ipv4/ip_sockglue.c 2010-08-02 01:11:14.000000000 +0300 +++ patched/net/ipv4/ip_sockglue.c 2011-03-26 07:41:39.573716021 +0200 @@ -1211,6 +1211,10 @@ int hlim = inet->mc_ttl; put_cmsg(&msg, SOL_IP, IP_TTL, sizeof(hlim), &hlim); } + if (inet->cmsg_flags&IP_CMSG_TOS) { + int hlim = inet->zph_tos & 0xFF; + put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(hlim), &hlim); + } len -= msg.msg_controllen; return put_user(len, optlen); } diff -Nur orig/net/ipv4/tcp_input.c patched/net/ipv4/tcp_input.c --- orig/net/ipv4/tcp_input.c 2011-03-26 00:01:59.000000000 +0200 +++ patched/net/ipv4/tcp_input.c 2011-03-26 08:14:05.000000000 +0200 @@ -4366,6 +4366,8 @@ struct tcphdr *th = tcp_hdr(skb); struct tcp_sock *tp = tcp_sk(sk); int eaten = -1; + struct inet_sock *inet = inet_sk(sk); + struct iphdr *iph = ip_hdr(skb); if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) goto drop; @@ -4376,6 +4378,12 @@ TCP_ECN_accept_cwr(tp, skb); tp->rx_opt.dsack = 0; + + // ZPH: Copy the TOS value of the first data ACK segment + // received from the remote peer. + if (0==(inet->zph_tos & 0x8000)) { + inet->zph_tos = 0x8000 | iph->tos; + } /* Queue data for delivery to the user. * Packets in sequence go to the receive queue. @@ -5442,6 +5450,8 @@ struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); struct tcp_cookie_values *cvp = tp->cookie_values; + struct inet_sock *inet = inet_sk(sk); + struct iphdr *iph = ip_hdr(skb); int saved_clamp = tp->rx_opt.mss_clamp; tcp_parse_options(skb, &tp->rx_opt, &hash_location, 0); @@ -5500,6 +5510,15 @@ TCP_ECN_rcv_synack(tp, th); + /* ZPH: + * Copy TOS field from the SYNACK packet to zph_tos field of the af_inet + * member of sock structure. This value shall be overwritten when the first + * data segment is received from the peer. However, for completeness in + * case the socket TOS is being asked befor that, we copy the TOS value from + * the SYNACK packet. + */ + inet->zph_tos = iph->tos; + tp->snd_wl1 = TCP_SKB_CB(skb)->seq; tcp_ack(sk, skb, FLAG_SLOWPATH);