ipv6: tcp: fix TCLASS value in ACK messages sent from TIME_WAIT
commit 66b13d99d9 (ipv4: tcp: fix TOS value in ACK messages sent from
TIME_WAIT) fixed IPv4 only.
This part is for the IPv6 side, adding a tclass param to ip6_xmit()
We alias tw_tclass and tw_tos, if socket family is INET6.
[ if sockets is ipv4-mapped, only IP_TOS socket option is used to fill
TOS field, TCLASS is not taken into account ]
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
	
	
This commit is contained in:
		
					parent
					
						
							
								138c4ae9cf
							
						
					
				
			
			
				commit
				
					
						b903d324be
					
				
			
		
					 8 changed files with 19 additions and 18 deletions
				
			
		| 
						 | 
					@ -134,6 +134,7 @@ struct inet_timewait_sock {
 | 
				
			||||||
	struct inet_bind_bucket	*tw_tb;
 | 
						struct inet_bind_bucket	*tw_tb;
 | 
				
			||||||
	struct hlist_node	tw_death_node;
 | 
						struct hlist_node	tw_death_node;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					#define tw_tclass tw_tos
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw,
 | 
					static inline void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw,
 | 
				
			||||||
				      struct hlist_nulls_head *list)
 | 
									      struct hlist_nulls_head *list)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -486,7 +486,8 @@ extern int			ip6_rcv_finish(struct sk_buff *skb);
 | 
				
			||||||
extern int			ip6_xmit(struct sock *sk,
 | 
					extern int			ip6_xmit(struct sock *sk,
 | 
				
			||||||
					 struct sk_buff *skb,
 | 
										 struct sk_buff *skb,
 | 
				
			||||||
					 struct flowi6 *fl6,
 | 
										 struct flowi6 *fl6,
 | 
				
			||||||
					 struct ipv6_txoptions *opt);
 | 
										 struct ipv6_txoptions *opt,
 | 
				
			||||||
 | 
										 int tclass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int			ip6_nd_hdr(struct sock *sk,
 | 
					extern int			ip6_nd_hdr(struct sock *sk,
 | 
				
			||||||
					   struct sk_buff *skb,
 | 
										   struct sk_buff *skb,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -271,7 +271,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
 | 
				
			||||||
							 &ireq6->loc_addr,
 | 
												 &ireq6->loc_addr,
 | 
				
			||||||
							 &ireq6->rmt_addr);
 | 
												 &ireq6->rmt_addr);
 | 
				
			||||||
		ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr);
 | 
							ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr);
 | 
				
			||||||
		err = ip6_xmit(sk, skb, &fl6, opt);
 | 
							err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
 | 
				
			||||||
		err = net_xmit_eval(err);
 | 
							err = net_xmit_eval(err);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -326,7 +326,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
 | 
				
			||||||
	dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
 | 
						dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
 | 
				
			||||||
	if (!IS_ERR(dst)) {
 | 
						if (!IS_ERR(dst)) {
 | 
				
			||||||
		skb_dst_set(skb, dst);
 | 
							skb_dst_set(skb, dst);
 | 
				
			||||||
		ip6_xmit(ctl_sk, skb, &fl6, NULL);
 | 
							ip6_xmit(ctl_sk, skb, &fl6, NULL, 0);
 | 
				
			||||||
		DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
 | 
							DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
 | 
				
			||||||
		DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
 | 
							DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -345,6 +345,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
 | 
				
			||||||
			tw6 = inet6_twsk((struct sock *)tw);
 | 
								tw6 = inet6_twsk((struct sock *)tw);
 | 
				
			||||||
			ipv6_addr_copy(&tw6->tw_v6_daddr, &np->daddr);
 | 
								ipv6_addr_copy(&tw6->tw_v6_daddr, &np->daddr);
 | 
				
			||||||
			ipv6_addr_copy(&tw6->tw_v6_rcv_saddr, &np->rcv_saddr);
 | 
								ipv6_addr_copy(&tw6->tw_v6_rcv_saddr, &np->rcv_saddr);
 | 
				
			||||||
 | 
								tw->tw_tclass = np->tclass;
 | 
				
			||||||
			tw->tw_ipv6only = np->ipv6only;
 | 
								tw->tw_ipv6only = np->ipv6only;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -248,7 +248,7 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused)
 | 
				
			||||||
	/* Restore final destination back after routing done */
 | 
						/* Restore final destination back after routing done */
 | 
				
			||||||
	ipv6_addr_copy(&fl6.daddr, &np->daddr);
 | 
						ipv6_addr_copy(&fl6.daddr, &np->daddr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	res = ip6_xmit(sk, skb, &fl6, np->opt);
 | 
						res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass);
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -180,7 +180,7 @@ int ip6_output(struct sk_buff *skb)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
 | 
					int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
 | 
				
			||||||
	     struct ipv6_txoptions *opt)
 | 
						     struct ipv6_txoptions *opt, int tclass)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net *net = sock_net(sk);
 | 
						struct net *net = sock_net(sk);
 | 
				
			||||||
	struct ipv6_pinfo *np = inet6_sk(sk);
 | 
						struct ipv6_pinfo *np = inet6_sk(sk);
 | 
				
			||||||
| 
						 | 
					@ -190,7 +190,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
 | 
				
			||||||
	u8  proto = fl6->flowi6_proto;
 | 
						u8  proto = fl6->flowi6_proto;
 | 
				
			||||||
	int seg_len = skb->len;
 | 
						int seg_len = skb->len;
 | 
				
			||||||
	int hlimit = -1;
 | 
						int hlimit = -1;
 | 
				
			||||||
	int tclass = 0;
 | 
					 | 
				
			||||||
	u32 mtu;
 | 
						u32 mtu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (opt) {
 | 
						if (opt) {
 | 
				
			||||||
| 
						 | 
					@ -228,10 +227,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 *	Fill in the IPv6 header
 | 
						 *	Fill in the IPv6 header
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (np) {
 | 
						if (np)
 | 
				
			||||||
		tclass = np->tclass;
 | 
					 | 
				
			||||||
		hlimit = np->hop_limit;
 | 
							hlimit = np->hop_limit;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (hlimit < 0)
 | 
						if (hlimit < 0)
 | 
				
			||||||
		hlimit = ip6_dst_hoplimit(dst);
 | 
							hlimit = ip6_dst_hoplimit(dst);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -513,7 +513,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
 | 
				
			||||||
		__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
 | 
							__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr);
 | 
							ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr);
 | 
				
			||||||
		err = ip6_xmit(sk, skb, &fl6, opt);
 | 
							err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
 | 
				
			||||||
		err = net_xmit_eval(err);
 | 
							err = net_xmit_eval(err);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -979,7 +979,7 @@ static int tcp6_gro_complete(struct sk_buff *skb)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
 | 
					static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
 | 
				
			||||||
				 u32 ts, struct tcp_md5sig_key *key, int rst)
 | 
									 u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct tcphdr *th = tcp_hdr(skb);
 | 
						const struct tcphdr *th = tcp_hdr(skb);
 | 
				
			||||||
	struct tcphdr *t1;
 | 
						struct tcphdr *t1;
 | 
				
			||||||
| 
						 | 
					@ -1060,7 +1060,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
 | 
				
			||||||
	dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
 | 
						dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
 | 
				
			||||||
	if (!IS_ERR(dst)) {
 | 
						if (!IS_ERR(dst)) {
 | 
				
			||||||
		skb_dst_set(buff, dst);
 | 
							skb_dst_set(buff, dst);
 | 
				
			||||||
		ip6_xmit(ctl_sk, buff, &fl6, NULL);
 | 
							ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
 | 
				
			||||||
		TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
 | 
							TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
 | 
				
			||||||
		if (rst)
 | 
							if (rst)
 | 
				
			||||||
			TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
 | 
								TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
 | 
				
			||||||
| 
						 | 
					@ -1093,13 +1093,13 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
		ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
 | 
							ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
 | 
				
			||||||
			  (th->doff << 2);
 | 
								  (th->doff << 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1);
 | 
						tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
 | 
					static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
 | 
				
			||||||
			    struct tcp_md5sig_key *key)
 | 
								    struct tcp_md5sig_key *key, u8 tclass)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	tcp_v6_send_response(skb, seq, ack, win, ts, key, 0);
 | 
						tcp_v6_send_response(skb, seq, ack, win, ts, key, 0, tclass);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
 | 
					static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
| 
						 | 
					@ -1109,7 +1109,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
 | 
						tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
 | 
				
			||||||
			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
 | 
								tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
 | 
				
			||||||
			tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw));
 | 
								tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw),
 | 
				
			||||||
 | 
								tw->tw_tclass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inet_twsk_put(tw);
 | 
						inet_twsk_put(tw);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1118,7 +1119,7 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
				  struct request_sock *req)
 | 
									  struct request_sock *req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
 | 
						tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
 | 
				
			||||||
			tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr));
 | 
								tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -243,7 +243,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
 | 
				
			||||||
	if (!(transport->param_flags & SPP_PMTUD_ENABLE))
 | 
						if (!(transport->param_flags & SPP_PMTUD_ENABLE))
 | 
				
			||||||
		skb->local_df = 1;
 | 
							skb->local_df = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ip6_xmit(sk, skb, &fl6, np->opt);
 | 
						return ip6_xmit(sk, skb, &fl6, np->opt, np->tclass);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Returns the dst cache entry for the given source and destination ip
 | 
					/* Returns the dst cache entry for the given source and destination ip
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue