aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/inet_connection_sock.h1
-rw-r--r--include/net/tcp.h4
-rw-r--r--net/ipv4/tcp_output.c19
-rw-r--r--net/ipv6/tcp_ipv6.c1
4 files changed, 21 insertions, 4 deletions
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 46c9e2ccdf02..7d83f90f203f 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -45,6 +45,7 @@ struct inet_connection_sock_af_ops {
45 struct dst_entry *dst); 45 struct dst_entry *dst);
46 struct inet_peer *(*get_peer)(struct sock *sk, bool *release_it); 46 struct inet_peer *(*get_peer)(struct sock *sk, bool *release_it);
47 u16 net_header_len; 47 u16 net_header_len;
48 u16 net_frag_header_len;
48 u16 sockaddr_len; 49 u16 sockaddr_len;
49 int (*setsockopt)(struct sock *sk, int level, int optname, 50 int (*setsockopt)(struct sock *sk, int level, int optname,
50 char __user *optval, unsigned int optlen); 51 char __user *optval, unsigned int optlen);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index fc880e92164a..0fb84de6da36 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -544,8 +544,8 @@ extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
544 544
545extern void tcp_initialize_rcv_mss(struct sock *sk); 545extern void tcp_initialize_rcv_mss(struct sock *sk);
546 546
547extern int tcp_mtu_to_mss(const struct sock *sk, int pmtu); 547extern int tcp_mtu_to_mss(struct sock *sk, int pmtu);
548extern int tcp_mss_to_mtu(const struct sock *sk, int mss); 548extern int tcp_mss_to_mtu(struct sock *sk, int mss);
549extern void tcp_mtup_init(struct sock *sk); 549extern void tcp_mtup_init(struct sock *sk);
550extern void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt); 550extern void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt);
551 551
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 7b7cf3811348..834e89fc541b 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1150,7 +1150,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
1150} 1150}
1151 1151
1152/* Calculate MSS. Not accounting for SACKs here. */ 1152/* Calculate MSS. Not accounting for SACKs here. */
1153int tcp_mtu_to_mss(const struct sock *sk, int pmtu) 1153int tcp_mtu_to_mss(struct sock *sk, int pmtu)
1154{ 1154{
1155 const struct tcp_sock *tp = tcp_sk(sk); 1155 const struct tcp_sock *tp = tcp_sk(sk);
1156 const struct inet_connection_sock *icsk = inet_csk(sk); 1156 const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -1161,6 +1161,14 @@ int tcp_mtu_to_mss(const struct sock *sk, int pmtu)
1161 */ 1161 */
1162 mss_now = pmtu - icsk->icsk_af_ops->net_header_len - sizeof(struct tcphdr); 1162 mss_now = pmtu - icsk->icsk_af_ops->net_header_len - sizeof(struct tcphdr);
1163 1163
1164 /* IPv6 adds a frag_hdr in case RTAX_FEATURE_ALLFRAG is set */
1165 if (icsk->icsk_af_ops->net_frag_header_len) {
1166 const struct dst_entry *dst = __sk_dst_get(sk);
1167
1168 if (dst && dst_allfrag(dst))
1169 mss_now -= icsk->icsk_af_ops->net_frag_header_len;
1170 }
1171
1164 /* Clamp it (mss_clamp does not include tcp options) */ 1172 /* Clamp it (mss_clamp does not include tcp options) */
1165 if (mss_now > tp->rx_opt.mss_clamp) 1173 if (mss_now > tp->rx_opt.mss_clamp)
1166 mss_now = tp->rx_opt.mss_clamp; 1174 mss_now = tp->rx_opt.mss_clamp;
@@ -1179,7 +1187,7 @@ int tcp_mtu_to_mss(const struct sock *sk, int pmtu)
1179} 1187}
1180 1188
1181/* Inverse of above */ 1189/* Inverse of above */
1182int tcp_mss_to_mtu(const struct sock *sk, int mss) 1190int tcp_mss_to_mtu(struct sock *sk, int mss)
1183{ 1191{
1184 const struct tcp_sock *tp = tcp_sk(sk); 1192 const struct tcp_sock *tp = tcp_sk(sk);
1185 const struct inet_connection_sock *icsk = inet_csk(sk); 1193 const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -1190,6 +1198,13 @@ int tcp_mss_to_mtu(const struct sock *sk, int mss)
1190 icsk->icsk_ext_hdr_len + 1198 icsk->icsk_ext_hdr_len +
1191 icsk->icsk_af_ops->net_header_len; 1199 icsk->icsk_af_ops->net_header_len;
1192 1200
1201 /* IPv6 adds a frag_hdr in case RTAX_FEATURE_ALLFRAG is set */
1202 if (icsk->icsk_af_ops->net_frag_header_len) {
1203 const struct dst_entry *dst = __sk_dst_get(sk);
1204
1205 if (dst && dst_allfrag(dst))
1206 mtu += icsk->icsk_af_ops->net_frag_header_len;
1207 }
1193 return mtu; 1208 return mtu;
1194} 1209}
1195 1210
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index cdbf292ad208..57b210969834 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1778,6 +1778,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = {
1778 .syn_recv_sock = tcp_v6_syn_recv_sock, 1778 .syn_recv_sock = tcp_v6_syn_recv_sock,
1779 .get_peer = tcp_v6_get_peer, 1779 .get_peer = tcp_v6_get_peer,
1780 .net_header_len = sizeof(struct ipv6hdr), 1780 .net_header_len = sizeof(struct ipv6hdr),
1781 .net_frag_header_len = sizeof(struct frag_hdr),
1781 .setsockopt = ipv6_setsockopt, 1782 .setsockopt = ipv6_setsockopt,
1782 .getsockopt = ipv6_getsockopt, 1783 .getsockopt = ipv6_getsockopt,
1783 .addr2sockaddr = inet6_csk_addr2sockaddr, 1784 .addr2sockaddr = inet6_csk_addr2sockaddr,