Skip to contentSkip to conversation

tcp: constify congestion_ops

RFC In review Stephen Hemminger 3 participants 6 messages Aug 2, 2017 – Aug 8, 2017

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover tcp: constify congestion_ops

This is a proposed method of making TCP congestion_ops structure const.

I wonder if restricting congestion control choices is still necessary? It seems like being overly paranoid, and better enforced by having a more limited kernel config, seccomp or other mechanism.

Stephen Hemminger (1):
constify tcp congestion

 include/net/tcp.h        |  10 ++-
 net/ipv4/tcp.c           |   2 -
 net/ipv4/tcp_bbr.c       |   2 +-
 net/ipv4/tcp_bic.c       |   2 +-
 net/ipv4/tcp_cdg.c       |   2 +-
 net/ipv4/tcp_cong.c      | 162 +++++++++++++++++++++++++++++------------------
 net/ipv4/tcp_cubic.c     |   2 +-
 net/ipv4/tcp_dctcp.c     |   6 +-
 net/ipv4/tcp_highspeed.c |   2 +-
 net/ipv4/tcp_htcp.c      |   2 +-
 net/ipv4/tcp_hybla.c     |   2 +-
 net/ipv4/tcp_illinois.c  |   2 +-
 net/ipv4/tcp_lp.c        |   2 +-
 net/ipv4/tcp_nv.c        |   2 +-
 net/ipv4/tcp_scalable.c  |   2 +-
 net/ipv4/tcp_vegas.c     |   2 +-
 net/ipv4/tcp_veno.c      |   2 +-
 net/ipv4/tcp_westwood.c  |   2 +-
 net/ipv4/tcp_yeah.c      |   2 +-
 19 files changed, 124 insertions(+), 86 deletions(-)
Signature · 1 line
2.11.0
#1 lore raw

RFC 1/1 constify tcp congestion

Split the TCP congestion ops structure into const and mutable portions. Put the list pointers, key and a copy of the flags in new tcp_congestion_entry structure.

---
 include/net/tcp.h        |  10 ++-
 net/ipv4/tcp.c           |   2 -
 net/ipv4/tcp_bbr.c       |   2 +-
 net/ipv4/tcp_bic.c       |   2 +-
 net/ipv4/tcp_cdg.c       |   2 +-
 net/ipv4/tcp_cong.c      | 162 +++++++++++++++++++++++++++++------------------
 net/ipv4/tcp_cubic.c     |   2 +-
 net/ipv4/tcp_dctcp.c     |   6 +-
 net/ipv4/tcp_highspeed.c |   2 +-
 net/ipv4/tcp_htcp.c      |   2 +-
 net/ipv4/tcp_hybla.c     |   2 +-
 net/ipv4/tcp_illinois.c  |   2 +-
 net/ipv4/tcp_lp.c        |   2 +-
 net/ipv4/tcp_nv.c        |   2 +-
 net/ipv4/tcp_scalable.c  |   2 +-
 net/ipv4/tcp_vegas.c     |   2 +-
 net/ipv4/tcp_veno.c      |   2 +-
 net/ipv4/tcp_westwood.c  |   2 +-
 net/ipv4/tcp_yeah.c      |   2 +-
 19 files changed, 124 insertions(+), 86 deletions(-)
include/net/tcp.h +4 -6
index bb1881b4ce48..725395a7c6d1 100644
@@ -931,8 +931,6 @@ struct rate_sample {
 };
 
 struct tcp_congestion_ops {
-	struct list_head	list;
-	u32 key;
 	u32 flags;
 
 	/* initialize private data (optional) */
@@ -970,8 +968,8 @@ struct tcp_congestion_ops {
 	struct module 	*owner;
 };
 
-int tcp_register_congestion_control(struct tcp_congestion_ops *type);
-void tcp_unregister_congestion_control(struct tcp_congestion_ops *type);
+int tcp_register_congestion_control(const struct tcp_congestion_ops *type);
+void tcp_unregister_congestion_control(const struct tcp_congestion_ops *type);
 
 void tcp_assign_congestion_control(struct sock *sk);
 void tcp_init_congestion_control(struct sock *sk);
@@ -990,9 +988,9 @@ void tcp_cong_avoid_ai(struct tcp_sock *tp, u32 w, u32 acked);
 u32 tcp_reno_ssthresh(struct sock *sk);
 u32 tcp_reno_undo_cwnd(struct sock *sk);
 void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 acked);
-extern struct tcp_congestion_ops tcp_reno;
+extern const struct tcp_congestion_ops tcp_reno;
 
-struct tcp_congestion_ops *tcp_ca_find_key(u32 key);
+const struct tcp_congestion_ops *tcp_ca_find_key(u32 key);
 u32 tcp_ca_get_key_by_name(const char *name, bool *ecn_ca);
 #ifdef CONFIG_INET
 char *tcp_ca_get_name_by_key(u32 key, char *buffer);
net/ipv4/tcp.c +0 -2
index 9dd6f4dba9b1..b26eeff90cff 100644
@@ -3344,8 +3344,6 @@ int tcp_abort(struct sock *sk, int err)
 }
 EXPORT_SYMBOL_GPL(tcp_abort);
 
-extern struct tcp_congestion_ops tcp_reno;
-
 static __initdata unsigned long thash_entries;
 static int __init set_thash_entries(char *str)
 {
net/ipv4/tcp_bbr.c +1 -1
index 69ee877574d0..353574dd1eb8 100644
@@ -917,7 +917,7 @@ static void bbr_set_state(struct sock *sk, u8 new_state)
 	}
 }
 
-static struct tcp_congestion_ops tcp_bbr_cong_ops __read_mostly = {
+static const struct tcp_congestion_ops tcp_bbr_cong_ops = {
 	.flags		= TCP_CONG_NON_RESTRICTED,
 	.name		= "bbr",
 	.owner		= THIS_MODULE,
net/ipv4/tcp_bic.c +1 -1
index 609965f0e298..8a8a3a6bde1a 100644
@@ -209,7 +209,7 @@ static void bictcp_acked(struct sock *sk, const struct ack_sample *sample)
 	}
 }
 
-static struct tcp_congestion_ops bictcp __read_mostly = {
+static const struct tcp_congestion_ops bictcp = {
 	.init		= bictcp_init,
 	.ssthresh	= bictcp_recalc_ssthresh,
 	.cong_avoid	= bictcp_cong_avoid,
net/ipv4/tcp_cdg.c +1 -1
index 50a0f3e51d5b..32e8631dd128 100644
@@ -399,7 +399,7 @@ static void tcp_cdg_release(struct sock *sk)
 	kfree(ca->gradients);
 }
 
-struct tcp_congestion_ops tcp_cdg __read_mostly = {
+static const struct tcp_congestion_ops tcp_cdg = {
 	.cong_avoid = tcp_cdg_cong_avoid,
 	.cwnd_event = tcp_cdg_cwnd_event,
 	.pkts_acked = tcp_cdg_acked,
net/ipv4/tcp_cong.c +102 -60

345 lines not on this page · raw message

net/ipv4/tcp_cubic.c +1 -1
index 57ae5b5ae643..6a358d8408c4 100644
@@ -465,7 +465,7 @@ static void bictcp_acked(struct sock *sk, const struct ack_sample *sample)
 		hystart_update(sk, delay);
 }
 
-static struct tcp_congestion_ops cubictcp __read_mostly = {
+static const struct tcp_congestion_ops cubictcp = {
 	.init		= bictcp_init,
 	.ssthresh	= bictcp_recalc_ssthresh,
 	.cong_avoid	= bictcp_cong_avoid,
net/ipv4/tcp_dctcp.c +3 -3
index 5f5e5936760e..7c608527c581 100644
@@ -72,7 +72,7 @@ module_param(dctcp_clamp_alpha_on_loss, uint, 0644);
 MODULE_PARM_DESC(dctcp_clamp_alpha_on_loss,
 		 "parameter for clamping alpha on loss");
 
-static struct tcp_congestion_ops dctcp_reno;
+static const struct tcp_congestion_ops dctcp_reno;
 
 static void dctcp_reset(const struct tcp_sock *tp, struct dctcp *ca)
 {
@@ -318,7 +318,7 @@ static u32 dctcp_cwnd_undo(struct sock *sk)
 	return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);
 }
 
-static struct tcp_congestion_ops dctcp __read_mostly = {
+static const struct tcp_congestion_ops dctcp = {
 	.init		= dctcp_init,
 	.in_ack_event   = dctcp_update_alpha,
 	.cwnd_event	= dctcp_cwnd_event,
@@ -332,7 +332,7 @@ static struct tcp_congestion_ops dctcp __read_mostly = {
 	.name		= "dctcp",
 };
 
-static struct tcp_congestion_ops dctcp_reno __read_mostly = {
+static const struct tcp_congestion_ops dctcp_reno = {
 	.ssthresh	= tcp_reno_ssthresh,
 	.cong_avoid	= tcp_reno_cong_avoid,
 	.undo_cwnd	= tcp_reno_undo_cwnd,
net/ipv4/tcp_highspeed.c +1 -1
index 6d9879e93648..0faf9f952cf4 100644
@@ -165,7 +165,7 @@ static u32 hstcp_cwnd_undo(struct sock *sk)
 	return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);
 }
 
-static struct tcp_congestion_ops tcp_highspeed __read_mostly = {
+static const struct tcp_congestion_ops tcp_highspeed = {
 	.init		= hstcp_init,
 	.ssthresh	= hstcp_ssthresh,
 	.undo_cwnd	= hstcp_cwnd_undo,
net/ipv4/tcp_htcp.c +1 -1
index 3eb78cde6ff0..74a5992f0323 100644
@@ -286,7 +286,7 @@ static void htcp_state(struct sock *sk, u8 new_state)
 	}
 }
 
-static struct tcp_congestion_ops htcp __read_mostly = {
+static const struct tcp_congestion_ops htcp = {
 	.init		= htcp_init,
 	.ssthresh	= htcp_recalc_ssthresh,
 	.cong_avoid	= htcp_cong_avoid,
net/ipv4/tcp_hybla.c +1 -1
index 0f7175c3338e..4705a65cd23a 100644
@@ -163,7 +163,7 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 acked)
 	tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
 }
 
-static struct tcp_congestion_ops tcp_hybla __read_mostly = {
+static const struct tcp_congestion_ops tcp_hybla = {
 	.init		= hybla_init,
 	.ssthresh	= tcp_reno_ssthresh,
 	.undo_cwnd	= tcp_reno_undo_cwnd,
net/ipv4/tcp_illinois.c +1 -1
index 60352ff4f5a8..f0ea215a66fd 100644
@@ -333,7 +333,7 @@ static size_t tcp_illinois_info(struct sock *sk, u32 ext, int *attr,
 	return 0;
 }
 
-static struct tcp_congestion_ops tcp_illinois __read_mostly = {
+static const struct tcp_congestion_ops tcp_illinois = {
 	.init		= tcp_illinois_init,
 	.ssthresh	= tcp_illinois_ssthresh,
 	.undo_cwnd	= tcp_illinois_cwnd_undo,
net/ipv4/tcp_lp.c +1 -1
index ae10ed64fe13..9960add64363 100644
@@ -316,7 +316,7 @@ static void tcp_lp_pkts_acked(struct sock *sk, const struct ack_sample *sample)
 	lp->last_drop = now;
 }
 
-static struct tcp_congestion_ops tcp_lp __read_mostly = {
+static const struct tcp_congestion_ops tcp_lp = {
 	.init = tcp_lp_init,
 	.ssthresh = tcp_reno_ssthresh,
 	.undo_cwnd = tcp_reno_undo_cwnd,
net/ipv4/tcp_nv.c +1 -1
index 6d650ed3cb59..fcfc2329953d 100644
@@ -441,7 +441,7 @@ static size_t tcpnv_get_info(struct sock *sk, u32 ext, int *attr,
 	return 0;
 }
 
-static struct tcp_congestion_ops tcpnv __read_mostly = {
+static const struct tcp_congestion_ops tcpnv = {
 	.init		= tcpnv_init,
 	.ssthresh	= tcpnv_recalc_ssthresh,
 	.cong_avoid	= tcpnv_cong_avoid,
net/ipv4/tcp_scalable.c +1 -1
index f2123075ce6e..18c98f8e5f6c 100644
@@ -50,7 +50,7 @@ static u32 tcp_scalable_cwnd_undo(struct sock *sk)
 	return max(tcp_sk(sk)->snd_cwnd, ca->loss_cwnd);
 }
 
-static struct tcp_congestion_ops tcp_scalable __read_mostly = {
+static const struct tcp_congestion_ops tcp_scalable = {
 	.ssthresh	= tcp_scalable_ssthresh,
 	.undo_cwnd	= tcp_scalable_cwnd_undo,
 	.cong_avoid	= tcp_scalable_cong_avoid,
net/ipv4/tcp_vegas.c +1 -1
index 218cfcc77650..c9d7000f00b0 100644
@@ -304,7 +304,7 @@ size_t tcp_vegas_get_info(struct sock *sk, u32 ext, int *attr,
 }
 EXPORT_SYMBOL_GPL(tcp_vegas_get_info);
 
-static struct tcp_congestion_ops tcp_vegas __read_mostly = {
+static const struct tcp_congestion_ops tcp_vegas = {
 	.init		= tcp_vegas_init,
 	.ssthresh	= tcp_reno_ssthresh,
 	.undo_cwnd	= tcp_reno_undo_cwnd,
net/ipv4/tcp_veno.c +1 -1
index 76005d4b8dfc..0d9e33d7d7c5 100644
@@ -210,7 +210,7 @@ static u32 tcp_veno_cwnd_undo(struct sock *sk)
 	return max(tcp_sk(sk)->snd_cwnd, veno->loss_cwnd);
 }
 
-static struct tcp_congestion_ops tcp_veno __read_mostly = {
+static const struct tcp_congestion_ops tcp_veno = {
 	.init		= tcp_veno_init,
 	.ssthresh	= tcp_veno_ssthresh,
 	.undo_cwnd	= tcp_veno_cwnd_undo,
net/ipv4/tcp_westwood.c +1 -1
index e5de84310949..4c9b8711f4fe 100644
@@ -251,7 +251,7 @@ static size_t tcp_westwood_info(struct sock *sk, u32 ext, int *attr,
 	return 0;
 }
 
-static struct tcp_congestion_ops tcp_westwood __read_mostly = {
+static const struct tcp_congestion_ops tcp_westwood = {
 	.init		= tcp_westwood_init,
 	.ssthresh	= tcp_reno_ssthresh,
 	.cong_avoid	= tcp_reno_cong_avoid,
net/ipv4/tcp_yeah.c +1 -1
index e6ff99c4bd3b..507e4b2cb55f 100644
@@ -232,7 +232,7 @@ static u32 tcp_yeah_cwnd_undo(struct sock *sk)
 	return max(tcp_sk(sk)->snd_cwnd, yeah->loss_cwnd);
 }
 
-static struct tcp_congestion_ops tcp_yeah __read_mostly = {
+static const struct tcp_congestion_ops tcp_yeah = {
 	.init		= tcp_yeah_init,
 	.ssthresh	= tcp_yeah_ssthresh,
 	.undo_cwnd      = tcp_yeah_cwnd_undo,
Signature · 1 line
2.11.0
#2 lore raw

Re: [RFC 1/1] constify tcp congestion

Quoted 3 lines · Stephen Hemminger

Split the TCP congestion ops structure into const and mutable portions. Put the list pointers, key and a copy of the flags in new tcp_congestion_entry structure.

...

Quoted 6 lines
net/ipv4/tcp_cong.c +3 -1
-void tcp_unregister_congestion_control(struct tcp_congestion_ops *ca)
+void tcp_unregister_congestion_control(const struct tcp_congestion_ops *ca)
 {
+	struct tcp_congestion_entry *e;
+

net/ipv4/tcp_cong.c EXPORT_SYMBOL_GPL(tcp_register_congestion_control); · line 130

Quoted 10 lines
net/ipv4/tcp_cong.c +7 -1
 	spin_lock(&tcp_cong_list_lock);
-	list_del_rcu(&ca->list);
+	list_for_each_entry_rcu(e, &tcp_cong_list, list) {
+		if (e->ops == ca) {
+			list_del_rcu(&e->list);
+			kfree_rcu(e, rcu);
+			break;
+		}
+	}
 	spin_unlock(&tcp_cong_list_lock);

Since you switched to kfree_rcu(), you could remove the synchronize_rcu() from tcp_unregister_congestion_control()

Otherwise, no need for kfree_rcu() and the rcu head added in struct tcp_congestion_entry :
- You could do a kfree() after the synchronize_rcu().

Also, I am not convinced this would be a good move, since you added an extra structure which is not const anyway.

#3 lore raw

Re: [RFC 1/1] constify tcp congestion

Quoted 2 lines · Eric Dumazet

Also, I am not convinced this would be a good move, since you added an extra structure which is not const anyway.

Actually, this extra structure might be needed if we want to move the tcp congestion sysctls to net namespace.

#4 lore raw

Re: [RFC 1/1] constify tcp congestion

Quoted 10 lines · On Wed, 02 Aug 2017 01:13:09 -0700 Eric Dumazet <[email protected]> wrote:
Quoted 2 lines · Eric Dumazet

Also, I am not convinced this would be a good move, since you added an extra structure which is not const anyway.

Actually, this extra structure might be needed if we want to move the tcp congestion sysctls to net namespace.

I was thinking about this. It should be possible to have different list of congestion controls for each net namespace. The list would be inherited, but each namespace could change:
* default CC
* available CC
* non-restricted CC

#5 lore raw
In reply to Stephen Hemminger
Quoted 3 lines · Stephen Hemminger

I wonder if restricting congestion control choices is still necessary? It seems like being overly paranoid, and better enforced by having a more limited kernel config, seccomp or other mechanism.

Agree, I think it can be removed.