1 diff -urNp -x '*.orig' linux-4.4/include/net/inet_sock.h linux-4.4/include/net/inet_sock.h
2 --- linux-4.4/include/net/inet_sock.h 2021-02-24 16:52:56.472941287 +0100
3 +++ linux-4.4/include/net/inet_sock.h 2021-02-24 16:53:08.266645321 +0100
4 @@ -201,6 +201,7 @@ struct inet_sock {
6 struct ip_mc_socklist __rcu *mc_list;
7 struct inet_cork_full cork;
8 + __u16 zph_tos; /* ZPH TOS received on connect */
11 #define IPCORK_OPT 1 /* ip-options has been held in ipcork.opt */
12 diff -urNp -x '*.orig' linux-4.4/net/ipv4/ip_sockglue.c linux-4.4/net/ipv4/ip_sockglue.c
13 --- linux-4.4/net/ipv4/ip_sockglue.c 2021-02-24 16:52:56.629612878 +0100
14 +++ linux-4.4/net/ipv4/ip_sockglue.c 2021-02-24 16:53:08.266645321 +0100
15 @@ -1474,6 +1474,10 @@ static int do_ip_getsockopt(struct sock
16 int tos = inet->rcv_tos;
17 put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(tos), &tos);
19 + if (inet->cmsg_flags&IP_CMSG_TOS) {
20 + int hlim = inet->zph_tos & 0xFF;
21 + put_cmsg(&msg, SOL_IP, IP_TOS, sizeof(hlim), &hlim);
23 len -= msg.msg_controllen;
24 return put_user(len, optlen);
26 diff -urNp -x '*.orig' linux-4.4/net/ipv4/tcp_input.c linux-4.4/net/ipv4/tcp_input.c
27 --- linux-4.4/net/ipv4/tcp_input.c 2021-02-24 16:52:56.639613193 +0100
28 +++ linux-4.4/net/ipv4/tcp_input.c 2021-02-24 16:53:08.266645321 +0100
29 @@ -4631,6 +4631,8 @@ static void tcp_data_queue(struct sock *
30 struct tcp_sock *tp = tcp_sk(sk);
31 bool fragstolen = false;
33 + struct inet_sock *inet = inet_sk(sk);
34 + struct iphdr *iph = ip_hdr(skb);
36 if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
38 @@ -4643,6 +4645,12 @@ static void tcp_data_queue(struct sock *
42 + // ZPH: Copy the TOS value of the first data ACK segment
43 + // received from the remote peer.
44 + if (0==(inet->zph_tos & 0x8000)) {
45 + inet->zph_tos = 0x8000 | iph->tos;
48 /* Queue data for delivery to the user.
49 * Packets in sequence go to the receive queue.
50 * Out of sequence packets to the out_of_order_queue.
51 @@ -5679,6 +5687,8 @@ static int tcp_rcv_synsent_state_process
53 struct inet_connection_sock *icsk = inet_csk(sk);
54 struct tcp_sock *tp = tcp_sk(sk);
55 + struct inet_sock *inet = inet_sk(sk);
56 + struct iphdr *iph = ip_hdr(skb);
57 struct tcp_fastopen_cookie foc = { .len = -1 };
58 int saved_clamp = tp->rx_opt.mss_clamp;
60 @@ -5739,6 +5749,15 @@ static int tcp_rcv_synsent_state_process
62 tcp_ecn_rcv_synack(tp, th);
65 + * Copy TOS field from the SYNACK packet to zph_tos field of the af_inet
66 + * member of sock structure. This value shall be overwritten when the first
67 + * data segment is received from the peer. However, for completeness in
68 + * case the socket TOS is being asked befor that, we copy the TOS value from
69 + * the SYNACK packet.
71 + inet->zph_tos = iph->tos;
73 tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
74 tcp_ack(sk, skb, FLAG_SLOWPATH);