Skip to content

Commit b139ba4

Browse files
xemuldavem330
authored andcommitted
tcp: Repair connection-time negotiated parameters
There are options, which are set up on a socket while performing TCP handshake. Need to resurrect them on a socket while repairing. A new sockoption accepts a buffer and parses it. The buffer should be CODE:VALUE sequence of bytes, where CODE is standard option code and VALUE is the respective value. Only 4 options should be handled on repaired socket. To read 3 out of 4 of these options the TCP_INFO sockoption can be used. An ability to get the last one (the mss_clamp) was added by the previous patch. Now the restore. Three of these options -- timestamp_ok, mss_clamp and snd_wscale -- are just restored on a coket. The sack_ok flags has 2 issues. First, whether or not to do sacks at all. This flag is just read and set back. No other sack info is saved or restored, since according to the standart and the code dropping all sack-ed segments is OK, the sender will resubmit them again, so after the repair we will probably experience a pause in connection. Next, the fack bit. It's just set back on a socket if the respective sysctl is set. No collected stats about packets flow is preserved. As far as I see (plz, correct me if I'm wrong) the fack-based congestion algorithm survives dropping all of the stats and repairs itself eventually, probably losing the performance for that period. Signed-off-by: Pavel Emelyanov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5e6a3ce commit b139ba4

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

include/linux/tcp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ enum {
109109
#define TCP_REPAIR 19 /* TCP sock is under repair right now */
110110
#define TCP_REPAIR_QUEUE 20
111111
#define TCP_QUEUE_SEQ 21
112+
#define TCP_REPAIR_OPTIONS 22
112113

113114
enum {
114115
TCP_NO_QUEUE,

net/ipv4/tcp.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,6 +2218,68 @@ static inline int tcp_can_repair_sock(struct sock *sk)
22182218
((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
22192219
}
22202220

2221+
static int tcp_repair_options_est(struct tcp_sock *tp, char __user *optbuf, unsigned int len)
2222+
{
2223+
/*
2224+
* Options are stored in CODE:VALUE form where CODE is 8bit and VALUE
2225+
* fits the respective TCPOLEN_ size
2226+
*/
2227+
2228+
while (len > 0) {
2229+
u8 opcode;
2230+
2231+
if (get_user(opcode, optbuf))
2232+
return -EFAULT;
2233+
2234+
optbuf++;
2235+
len--;
2236+
2237+
switch (opcode) {
2238+
case TCPOPT_MSS: {
2239+
u16 in_mss;
2240+
2241+
if (len < sizeof(in_mss))
2242+
return -ENODATA;
2243+
if (get_user(in_mss, optbuf))
2244+
return -EFAULT;
2245+
2246+
tp->rx_opt.mss_clamp = in_mss;
2247+
2248+
optbuf += sizeof(in_mss);
2249+
len -= sizeof(in_mss);
2250+
break;
2251+
}
2252+
case TCPOPT_WINDOW: {
2253+
u8 wscale;
2254+
2255+
if (len < sizeof(wscale))
2256+
return -ENODATA;
2257+
if (get_user(wscale, optbuf))
2258+
return -EFAULT;
2259+
2260+
if (wscale > 14)
2261+
return -EFBIG;
2262+
2263+
tp->rx_opt.snd_wscale = wscale;
2264+
2265+
optbuf += sizeof(wscale);
2266+
len -= sizeof(wscale);
2267+
break;
2268+
}
2269+
case TCPOPT_SACK_PERM:
2270+
tp->rx_opt.sack_ok |= TCP_SACK_SEEN;
2271+
if (sysctl_tcp_fack)
2272+
tcp_enable_fack(tp);
2273+
break;
2274+
case TCPOPT_TIMESTAMP:
2275+
tp->rx_opt.tstamp_ok = 1;
2276+
break;
2277+
}
2278+
}
2279+
2280+
return 0;
2281+
}
2282+
22212283
/*
22222284
* Socket option code for TCP.
22232285
*/
@@ -2426,6 +2488,15 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
24262488
err = -EINVAL;
24272489
break;
24282490

2491+
case TCP_REPAIR_OPTIONS:
2492+
if (!tp->repair)
2493+
err = -EINVAL;
2494+
else if (sk->sk_state == TCP_ESTABLISHED)
2495+
err = tcp_repair_options_est(tp, optval, optlen);
2496+
else
2497+
err = -EPERM;
2498+
break;
2499+
24292500
case TCP_CORK:
24302501
/* When set indicates to always queue non-full frames.
24312502
* Later the user clears this option and we transmit

0 commit comments

Comments
 (0)