Skip to content

Commit 957ed5e

Browse files
committed
Merge branch 'tcp-plb'
Mubashir Adnan Qureshi says: ==================== net: Add PLB functionality to TCP This patch series adds PLB (Protective Load Balancing) to TCP and hooks it up to DCTCP. PLB is disabled by default and can be enabled using relevant sysctls and support from underlying CC. PLB (Protective Load Balancing) is a host based mechanism for load balancing across switch links. It leverages congestion signals(e.g. ECN) from transport layer to randomly change the path of the connection experiencing congestion. PLB changes the path of the connection by changing the outgoing IPv6 flow label for IPv6 connections (implemented in Linux by calling sk_rethink_txhash()). Because of this implementation mechanism, PLB can currently only work for IPv6 traffic. For more information, see the SIGCOMM 2022 paper: https://doi.org/10.1145/3544216.3544226 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 7f86cf5 + 71fc704 commit 957ed5e

13 files changed

Lines changed: 305 additions & 2 deletions

File tree

Documentation/networking/ip-sysctl.rst

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,81 @@ tcp_child_ehash_entries - INTEGER
10691069

10701070
Default: 0
10711071

1072+
tcp_plb_enabled - BOOLEAN
1073+
If set and the underlying congestion control (e.g. DCTCP) supports
1074+
and enables PLB feature, TCP PLB (Protective Load Balancing) is
1075+
enabled. PLB is described in the following paper:
1076+
https://doi.org/10.1145/3544216.3544226. Based on PLB parameters,
1077+
upon sensing sustained congestion, TCP triggers a change in
1078+
flow label field for outgoing IPv6 packets. A change in flow label
1079+
field potentially changes the path of outgoing packets for switches
1080+
that use ECMP/WCMP for routing.
1081+
1082+
PLB changes socket txhash which results in a change in IPv6 Flow Label
1083+
field, and currently no-op for IPv4 headers. It is possible
1084+
to apply PLB for IPv4 with other network header fields (e.g. TCP
1085+
or IPv4 options) or using encapsulation where outer header is used
1086+
by switches to determine next hop. In either case, further host
1087+
and switch side changes will be needed.
1088+
1089+
When set, PLB assumes that congestion signal (e.g. ECN) is made
1090+
available and used by congestion control module to estimate a
1091+
congestion measure (e.g. ce_ratio). PLB needs a congestion measure to
1092+
make repathing decisions.
1093+
1094+
Default: FALSE
1095+
1096+
tcp_plb_idle_rehash_rounds - INTEGER
1097+
Number of consecutive congested rounds (RTT) seen after which
1098+
a rehash can be performed, given there are no packets in flight.
1099+
This is referred to as M in PLB paper:
1100+
https://doi.org/10.1145/3544216.3544226.
1101+
1102+
Possible Values: 0 - 31
1103+
1104+
Default: 3
1105+
1106+
tcp_plb_rehash_rounds - INTEGER
1107+
Number of consecutive congested rounds (RTT) seen after which
1108+
a forced rehash can be performed. Be careful when setting this
1109+
parameter, as a small value increases the risk of retransmissions.
1110+
This is referred to as N in PLB paper:
1111+
https://doi.org/10.1145/3544216.3544226.
1112+
1113+
Possible Values: 0 - 31
1114+
1115+
Default: 12
1116+
1117+
tcp_plb_suspend_rto_sec - INTEGER
1118+
Time, in seconds, to suspend PLB in event of an RTO. In order to avoid
1119+
having PLB repath onto a connectivity "black hole", after an RTO a TCP
1120+
connection suspends PLB repathing for a random duration between 1x and
1121+
2x of this parameter. Randomness is added to avoid concurrent rehashing
1122+
of multiple TCP connections. This should be set corresponding to the
1123+
amount of time it takes to repair a failed link.
1124+
1125+
Possible Values: 0 - 255
1126+
1127+
Default: 60
1128+
1129+
tcp_plb_cong_thresh - INTEGER
1130+
Fraction of packets marked with congestion over a round (RTT) to
1131+
tag that round as congested. This is referred to as K in the PLB paper:
1132+
https://doi.org/10.1145/3544216.3544226.
1133+
1134+
The 0-1 fraction range is mapped to 0-256 range to avoid floating
1135+
point operations. For example, 128 means that if at least 50% of
1136+
the packets in a round were marked as congested then the round
1137+
will be tagged as congested.
1138+
1139+
Setting threshold to 0 means that PLB repaths every RTT regardless
1140+
of congestion. This is not intended behavior for PLB and should be
1141+
used only for experimentation purpose.
1142+
1143+
Possible Values: 0 - 256
1144+
1145+
Default: 128
1146+
10721147
UDP variables
10731148
=============
10741149

include/linux/tcp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ struct tcp_sock {
423423
u32 probe_seq_start;
424424
u32 probe_seq_end;
425425
} mtu_probe;
426+
u32 plb_rehash; /* PLB-triggered rehash attempts */
426427
u32 mtu_info; /* We received an ICMP_FRAG_NEEDED / ICMPV6_PKT_TOOBIG
427428
* while socket was owned by user.
428429
*/

include/net/netns/ipv4.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ struct netns_ipv4 {
183183
unsigned long tfo_active_disable_stamp;
184184
u32 tcp_challenge_timestamp;
185185
u32 tcp_challenge_count;
186+
u8 sysctl_tcp_plb_enabled;
187+
u8 sysctl_tcp_plb_idle_rehash_rounds;
188+
u8 sysctl_tcp_plb_rehash_rounds;
189+
u8 sysctl_tcp_plb_suspend_rto_sec;
190+
int sysctl_tcp_plb_cong_thresh;
186191

187192
int sysctl_udp_wmem_min;
188193
int sysctl_udp_rmem_min;

include/net/tcp.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,6 +2140,34 @@ extern void tcp_rack_advance(struct tcp_sock *tp, u8 sacked, u32 end_seq,
21402140
extern void tcp_rack_reo_timeout(struct sock *sk);
21412141
extern void tcp_rack_update_reo_wnd(struct sock *sk, struct rate_sample *rs);
21422142

2143+
/* tcp_plb.c */
2144+
2145+
/*
2146+
* Scaling factor for fractions in PLB. For example, tcp_plb_update_state
2147+
* expects cong_ratio which represents fraction of traffic that experienced
2148+
* congestion over a single RTT. In order to avoid floating point operations,
2149+
* this fraction should be mapped to (1 << TCP_PLB_SCALE) and passed in.
2150+
*/
2151+
#define TCP_PLB_SCALE 8
2152+
2153+
/* State for PLB (Protective Load Balancing) for a single TCP connection. */
2154+
struct tcp_plb_state {
2155+
u8 consec_cong_rounds:5, /* consecutive congested rounds */
2156+
unused:3;
2157+
u32 pause_until; /* jiffies32 when PLB can resume rerouting */
2158+
};
2159+
2160+
static inline void tcp_plb_init(const struct sock *sk,
2161+
struct tcp_plb_state *plb)
2162+
{
2163+
plb->consec_cong_rounds = 0;
2164+
plb->pause_until = 0;
2165+
}
2166+
void tcp_plb_update_state(const struct sock *sk, struct tcp_plb_state *plb,
2167+
const int cong_ratio);
2168+
void tcp_plb_check_rehash(struct sock *sk, struct tcp_plb_state *plb);
2169+
void tcp_plb_update_state_upon_rto(struct sock *sk, struct tcp_plb_state *plb);
2170+
21432171
/* At how many usecs into the future should the RTO fire? */
21442172
static inline s64 tcp_rto_delta_us(const struct sock *sk)
21452173
{

include/uapi/linux/snmp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ enum
292292
LINUX_MIB_TCPDSACKIGNOREDDUBIOUS, /* TCPDSACKIgnoredDubious */
293293
LINUX_MIB_TCPMIGRATEREQSUCCESS, /* TCPMigrateReqSuccess */
294294
LINUX_MIB_TCPMIGRATEREQFAILURE, /* TCPMigrateReqFailure */
295+
LINUX_MIB_TCPPLBREHASH, /* TCPPLBRehash */
295296
__LINUX_MIB_MAX
296297
};
297298

include/uapi/linux/tcp.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ struct tcp_info {
284284
__u32 tcpi_snd_wnd; /* peer's advertised receive window after
285285
* scaling (bytes)
286286
*/
287+
__u32 tcpi_rcv_wnd; /* local advertised receive window after
288+
* scaling (bytes)
289+
*/
290+
291+
__u32 tcpi_rehash; /* PLB or timeout triggered rehash attempts */
287292
};
288293

289294
/* netlink attributes types for SCM_TIMESTAMPING_OPT_STATS */
@@ -315,6 +320,7 @@ enum {
315320
TCP_NLA_BYTES_NOTSENT, /* Bytes in write queue not yet sent */
316321
TCP_NLA_EDT, /* Earliest departure time (CLOCK_MONOTONIC) */
317322
TCP_NLA_TTL, /* TTL or hop limit of a packet received */
323+
TCP_NLA_REHASH, /* PLB and timeout triggered rehash attempts */
318324
};
319325

320326
/* for TCP_MD5SIG socket option */

net/ipv4/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ obj-y := route.o inetpeer.o protocol.o \
1010
tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
1111
tcp_minisocks.o tcp_cong.o tcp_metrics.o tcp_fastopen.o \
1212
tcp_rate.o tcp_recovery.o tcp_ulp.o \
13-
tcp_offload.o datagram.o raw.o udp.o udplite.o \
13+
tcp_offload.o tcp_plb.o datagram.o raw.o udp.o udplite.o \
1414
udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \
1515
fib_frontend.o fib_semantics.o fib_trie.o fib_notifier.o \
1616
inet_fragment.o ping.o ip_tunnel_core.o gre_offload.o \

net/ipv4/proc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ static const struct snmp_mib snmp4_net_list[] = {
297297
SNMP_MIB_ITEM("TCPDSACKIgnoredDubious", LINUX_MIB_TCPDSACKIGNOREDDUBIOUS),
298298
SNMP_MIB_ITEM("TCPMigrateReqSuccess", LINUX_MIB_TCPMIGRATEREQSUCCESS),
299299
SNMP_MIB_ITEM("TCPMigrateReqFailure", LINUX_MIB_TCPMIGRATEREQFAILURE),
300+
SNMP_MIB_ITEM("TCPPLBRehash", LINUX_MIB_TCPPLBREHASH),
300301
SNMP_MIB_SENTINEL
301302
};
302303

net/ipv4/sysctl_net_ipv4.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ static int one_day_secs = 24 * 3600;
4040
static u32 fib_multipath_hash_fields_all_mask __maybe_unused =
4141
FIB_MULTIPATH_HASH_FIELD_ALL_MASK;
4242
static unsigned int tcp_child_ehash_entries_max = 16 * 1024 * 1024;
43+
static int tcp_plb_max_rounds = 31;
44+
static int tcp_plb_max_cong_thresh = 256;
4345

4446
/* obsolete */
4547
static int sysctl_tcp_low_latency __read_mostly;
@@ -1384,6 +1386,47 @@ static struct ctl_table ipv4_net_table[] = {
13841386
.extra1 = SYSCTL_ZERO,
13851387
.extra2 = SYSCTL_TWO,
13861388
},
1389+
{
1390+
.procname = "tcp_plb_enabled",
1391+
.data = &init_net.ipv4.sysctl_tcp_plb_enabled,
1392+
.maxlen = sizeof(u8),
1393+
.mode = 0644,
1394+
.proc_handler = proc_dou8vec_minmax,
1395+
.extra1 = SYSCTL_ZERO,
1396+
.extra2 = SYSCTL_ONE,
1397+
},
1398+
{
1399+
.procname = "tcp_plb_idle_rehash_rounds",
1400+
.data = &init_net.ipv4.sysctl_tcp_plb_idle_rehash_rounds,
1401+
.maxlen = sizeof(u8),
1402+
.mode = 0644,
1403+
.proc_handler = proc_dou8vec_minmax,
1404+
.extra2 = &tcp_plb_max_rounds,
1405+
},
1406+
{
1407+
.procname = "tcp_plb_rehash_rounds",
1408+
.data = &init_net.ipv4.sysctl_tcp_plb_rehash_rounds,
1409+
.maxlen = sizeof(u8),
1410+
.mode = 0644,
1411+
.proc_handler = proc_dou8vec_minmax,
1412+
.extra2 = &tcp_plb_max_rounds,
1413+
},
1414+
{
1415+
.procname = "tcp_plb_suspend_rto_sec",
1416+
.data = &init_net.ipv4.sysctl_tcp_plb_suspend_rto_sec,
1417+
.maxlen = sizeof(u8),
1418+
.mode = 0644,
1419+
.proc_handler = proc_dou8vec_minmax,
1420+
},
1421+
{
1422+
.procname = "tcp_plb_cong_thresh",
1423+
.data = &init_net.ipv4.sysctl_tcp_plb_cong_thresh,
1424+
.maxlen = sizeof(int),
1425+
.mode = 0644,
1426+
.proc_handler = proc_dointvec_minmax,
1427+
.extra1 = SYSCTL_ZERO,
1428+
.extra2 = &tcp_plb_max_cong_thresh,
1429+
},
13871430
{ }
13881431
};
13891432

net/ipv4/tcp.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3176,6 +3176,7 @@ int tcp_disconnect(struct sock *sk, int flags)
31763176
tp->sacked_out = 0;
31773177
tp->tlp_high_seq = 0;
31783178
tp->last_oow_ack_time = 0;
3179+
tp->plb_rehash = 0;
31793180
/* There's a bubble in the pipe until at least the first ACK. */
31803181
tp->app_limited = ~0U;
31813182
tp->rack.mstamp = 0;
@@ -3939,6 +3940,8 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
39393940
info->tcpi_reord_seen = tp->reord_seen;
39403941
info->tcpi_rcv_ooopack = tp->rcv_ooopack;
39413942
info->tcpi_snd_wnd = tp->snd_wnd;
3943+
info->tcpi_rcv_wnd = tp->rcv_wnd;
3944+
info->tcpi_rehash = tp->plb_rehash + tp->timeout_rehash;
39423945
info->tcpi_fastopen_client_fail = tp->fastopen_client_fail;
39433946
unlock_sock_fast(sk, slow);
39443947
}
@@ -3973,6 +3976,7 @@ static size_t tcp_opt_stats_get_size(void)
39733976
nla_total_size(sizeof(u32)) + /* TCP_NLA_BYTES_NOTSENT */
39743977
nla_total_size_64bit(sizeof(u64)) + /* TCP_NLA_EDT */
39753978
nla_total_size(sizeof(u8)) + /* TCP_NLA_TTL */
3979+
nla_total_size(sizeof(u32)) + /* TCP_NLA_REHASH */
39763980
0;
39773981
}
39783982

@@ -4049,6 +4053,7 @@ struct sk_buff *tcp_get_timestamping_opt_stats(const struct sock *sk,
40494053
nla_put_u8(stats, TCP_NLA_TTL,
40504054
tcp_skb_ttl_or_hop_limit(ack_skb));
40514055

4056+
nla_put_u32(stats, TCP_NLA_REHASH, tp->plb_rehash + tp->timeout_rehash);
40524057
return stats;
40534058
}
40544059

0 commit comments

Comments
 (0)