Commit b903d324 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

ipv6: tcp: fix TCLASS value in ACK messages sent from TIME_WAIT

commit 66b13d99 (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: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 138c4ae9
...@@ -134,6 +134,7 @@ struct inet_timewait_sock { ...@@ -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); ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment