[RFC PATCH net-next 3/3] tcp: netns: optionally inherit IPv4 TCP sysctls from parent netns

nmreadelf
2026-04-30T01:33:32Z

During netns creation, setup_net() initializes IPv4 TCP sysctls. Add an
optional follow-up copy step in copy_net_ns() so selected IPv4 TCP sysctl
settings can be inherited from old_net when
net.ipv4.netns_inherit_tcp_sysctls=1.

The copy uses the tcp_sysctl struct_group plus selected related fields
outside that group, guarded by BUILD_BUG_ON checks for layout safety.

Default behavior is unchanged because inheritance is disabled unless
explicitly enabled in old_net.
---
net/core/net_namespace.c | 72 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)

diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index a6e6a964a287..d6587362d450 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -548,6 +548,74 @@ void net_drop_ns(void *p)
net_passive_dec(net);
}

+static int __net_init copy_net_ns_tcp_sysctls(struct net *net, struct net *old_net)
+{
+ if (net == old_net)
+ return 0;
+
+ /* Make sure TCP sysctl fields are contained by tcp_sysctl group */
+#define CHECK_SYSCTL_TCP_FIELD(lhs, rhs) \
+ BUILD_BUG_ON(offsetof(struct netns_ipv4, lhs) != \
+ offsetof(struct netns_ipv4, tcp_sysctl.rhs))
+
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_ecn, sysctl_tcp_ecn);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_ecn_fallback, sysctl_tcp_ecn_fallback);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_base_mss, sysctl_tcp_base_mss);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_keepalive_time, sysctl_tcp_keepalive_time);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_syncookies, sysctl_tcp_syncookies);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_fin_timeout, sysctl_tcp_fin_timeout);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_sack, sysctl_tcp_sack);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_window_scaling, sysctl_tcp_window_scaling);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_timestamps, sysctl_tcp_timestamps);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_rto_min_us, sysctl_tcp_rto_min_us);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_rto_max_ms, sysctl_tcp_rto_max_ms);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_recovery, sysctl_tcp_recovery);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_max_reordering, sysctl_tcp_max_reordering);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_challenge_ack_limit, sysctl_tcp_challenge_ack_limit);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_pacing_ss_ratio, sysctl_tcp_pacing_ss_ratio);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_pacing_ca_ratio, sysctl_tcp_pacing_ca_ratio);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_comp_sack_delay_ns, sysctl_tcp_comp_sack_delay_ns);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_comp_sack_slack_ns, sysctl_tcp_comp_sack_slack_ns);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_fastopen, sysctl_tcp_fastopen);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_fastopen_blackhole_timeout,
+ sysctl_tcp_fastopen_blackhole_timeout);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_plb_enabled, sysctl_tcp_plb_enabled);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_plb_cong_thresh, sysctl_tcp_plb_cong_thresh);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_shrink_window, sysctl_tcp_shrink_window);
+ CHECK_SYSCTL_TCP_FIELD(sysctl_tcp_syn_linear_timeouts, sysctl_tcp_syn_linear_timeouts);
+
+ memcpy(&net->ipv4.tcp_sysctl,
+ &old_net->ipv4.tcp_sysctl, sizeof(net->ipv4.tcp_sysctl));
+ net->ipv4.sysctl_netns_inherit_tcp_sysctls =
+ old_net->ipv4.sysctl_netns_inherit_tcp_sysctls;
+ net->ipv4.sysctl_tcp_min_snd_mss =
+ old_net->ipv4.sysctl_tcp_min_snd_mss;
+ net->ipv4.sysctl_tcp_reordering =
+ old_net->ipv4.sysctl_tcp_reordering;
+ net->ipv4.sysctl_tcp_notsent_lowat =
+ old_net->ipv4.sysctl_tcp_notsent_lowat;
+
+ net->ipv4.sysctl_tcp_early_retrans =
+ old_net->ipv4.sysctl_tcp_early_retrans;
+ net->ipv4.sysctl_tcp_tso_win_divisor =
+ old_net->ipv4.sysctl_tcp_tso_win_divisor;
+ net->ipv4.sysctl_tcp_tso_rtt_log =
+ old_net->ipv4.sysctl_tcp_tso_rtt_log;
+ net->ipv4.sysctl_tcp_autocorking =
+ old_net->ipv4.sysctl_tcp_autocorking;
+ net->ipv4.sysctl_tcp_limit_output_bytes =
+ old_net->ipv4.sysctl_tcp_limit_output_bytes;
+ net->ipv4.sysctl_tcp_min_rtt_wlen =
+ old_net->ipv4.sysctl_tcp_min_rtt_wlen;
+ net->ipv4.sysctl_tcp_moderate_rcvbuf =
+ old_net->ipv4.sysctl_tcp_moderate_rcvbuf;
+ net->ipv4.sysctl_tcp_rcvbuf_low_rtt =
+ old_net->ipv4.sysctl_tcp_rcvbuf_low_rtt;
+ atomic_set(&net->ipv4.tfo_active_disable_times,
+ atomic_read(&old_net->ipv4.tfo_active_disable_times));
+ return 0;
+}
+
struct net *copy_net_ns(u64 flags,
struct user_namespace *user_ns, struct net *old_net)
{
@@ -594,6 +662,10 @@ struct net *copy_net_ns(u64 flags,
dec_net_namespaces(ucounts);
return ERR_PTR(rv);
}
+
+ if (READ_ONCE(old_net->ipv4.sysctl_netns_inherit_tcp_sysctls))
+ copy_net_ns_tcp_sysctls(net, old_net);
+
return net;
}

--
2.47.3