| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Pluggable TCP congestion control support and newReno |
|---|
| 3 | 4 | * congestion control. |
|---|
| .. | .. |
|---|
| 20 | 21 | static LIST_HEAD(tcp_cong_list); |
|---|
| 21 | 22 | |
|---|
| 22 | 23 | /* Simple linear search, don't expect many entries! */ |
|---|
| 23 | | -static struct tcp_congestion_ops *tcp_ca_find(const char *name) |
|---|
| 24 | +struct tcp_congestion_ops *tcp_ca_find(const char *name) |
|---|
| 24 | 25 | { |
|---|
| 25 | 26 | struct tcp_congestion_ops *e; |
|---|
| 26 | 27 | |
|---|
| .. | .. |
|---|
| 161 | 162 | |
|---|
| 162 | 163 | rcu_read_lock(); |
|---|
| 163 | 164 | ca = rcu_dereference(net->ipv4.tcp_congestion_control); |
|---|
| 164 | | - if (unlikely(!try_module_get(ca->owner))) |
|---|
| 165 | + if (unlikely(!bpf_try_module_get(ca, ca->owner))) |
|---|
| 165 | 166 | ca = &tcp_reno; |
|---|
| 166 | 167 | icsk->icsk_ca_ops = ca; |
|---|
| 167 | 168 | rcu_read_unlock(); |
|---|
| .. | .. |
|---|
| 175 | 176 | |
|---|
| 176 | 177 | void tcp_init_congestion_control(struct sock *sk) |
|---|
| 177 | 178 | { |
|---|
| 178 | | - const struct inet_connection_sock *icsk = inet_csk(sk); |
|---|
| 179 | + struct inet_connection_sock *icsk = inet_csk(sk); |
|---|
| 179 | 180 | |
|---|
| 180 | 181 | tcp_sk(sk)->prior_ssthresh = 0; |
|---|
| 181 | 182 | if (icsk->icsk_ca_ops->init) |
|---|
| .. | .. |
|---|
| 184 | 185 | INET_ECN_xmit(sk); |
|---|
| 185 | 186 | else |
|---|
| 186 | 187 | INET_ECN_dontxmit(sk); |
|---|
| 188 | + icsk->icsk_ca_initialized = 1; |
|---|
| 187 | 189 | } |
|---|
| 188 | 190 | |
|---|
| 189 | 191 | static void tcp_reinit_congestion_control(struct sock *sk, |
|---|
| .. | .. |
|---|
| 212 | 214 | |
|---|
| 213 | 215 | if (icsk->icsk_ca_ops->release) |
|---|
| 214 | 216 | icsk->icsk_ca_ops->release(sk); |
|---|
| 215 | | - module_put(icsk->icsk_ca_ops->owner); |
|---|
| 217 | + bpf_module_put(icsk->icsk_ca_ops, icsk->icsk_ca_ops->owner); |
|---|
| 216 | 218 | } |
|---|
| 217 | 219 | |
|---|
| 218 | 220 | /* Used by sysctl to change default congestion control */ |
|---|
| .. | .. |
|---|
| 226 | 228 | ca = tcp_ca_find_autoload(net, name); |
|---|
| 227 | 229 | if (!ca) { |
|---|
| 228 | 230 | ret = -ENOENT; |
|---|
| 229 | | - } else if (!try_module_get(ca->owner)) { |
|---|
| 231 | + } else if (!bpf_try_module_get(ca, ca->owner)) { |
|---|
| 230 | 232 | ret = -EBUSY; |
|---|
| 231 | 233 | } else if (!net_eq(net, &init_net) && |
|---|
| 232 | 234 | !(ca->flags & TCP_CONG_NON_RESTRICTED)) { |
|---|
| .. | .. |
|---|
| 235 | 237 | } else { |
|---|
| 236 | 238 | prev = xchg(&net->ipv4.tcp_congestion_control, ca); |
|---|
| 237 | 239 | if (prev) |
|---|
| 238 | | - module_put(prev->owner); |
|---|
| 240 | + bpf_module_put(prev, prev->owner); |
|---|
| 239 | 241 | |
|---|
| 240 | 242 | ca->flags |= TCP_CONG_NON_RESTRICTED; |
|---|
| 241 | 243 | ret = 0; |
|---|
| .. | .. |
|---|
| 264 | 266 | offs += snprintf(buf + offs, maxlen - offs, |
|---|
| 265 | 267 | "%s%s", |
|---|
| 266 | 268 | offs == 0 ? "" : " ", ca->name); |
|---|
| 269 | + |
|---|
| 270 | + if (WARN_ON_ONCE(offs >= maxlen)) |
|---|
| 271 | + break; |
|---|
| 267 | 272 | } |
|---|
| 268 | 273 | rcu_read_unlock(); |
|---|
| 269 | 274 | } |
|---|
| .. | .. |
|---|
| 293 | 298 | offs += snprintf(buf + offs, maxlen - offs, |
|---|
| 294 | 299 | "%s%s", |
|---|
| 295 | 300 | offs == 0 ? "" : " ", ca->name); |
|---|
| 301 | + |
|---|
| 302 | + if (WARN_ON_ONCE(offs >= maxlen)) |
|---|
| 303 | + break; |
|---|
| 296 | 304 | } |
|---|
| 297 | 305 | rcu_read_unlock(); |
|---|
| 298 | 306 | } |
|---|
| .. | .. |
|---|
| 342 | 350 | * already initialized. |
|---|
| 343 | 351 | */ |
|---|
| 344 | 352 | int tcp_set_congestion_control(struct sock *sk, const char *name, bool load, |
|---|
| 345 | | - bool reinit, bool cap_net_admin) |
|---|
| 353 | + bool cap_net_admin) |
|---|
| 346 | 354 | { |
|---|
| 347 | 355 | struct inet_connection_sock *icsk = inet_csk(sk); |
|---|
| 348 | 356 | const struct tcp_congestion_ops *ca; |
|---|
| .. | .. |
|---|
| 363 | 371 | goto out; |
|---|
| 364 | 372 | } |
|---|
| 365 | 373 | |
|---|
| 366 | | - if (!ca) { |
|---|
| 374 | + if (!ca) |
|---|
| 367 | 375 | err = -ENOENT; |
|---|
| 368 | | - } else if (!load) { |
|---|
| 369 | | - const struct tcp_congestion_ops *old_ca = icsk->icsk_ca_ops; |
|---|
| 370 | | - |
|---|
| 371 | | - if (try_module_get(ca->owner)) { |
|---|
| 372 | | - if (reinit) { |
|---|
| 373 | | - tcp_reinit_congestion_control(sk, ca); |
|---|
| 374 | | - } else { |
|---|
| 375 | | - icsk->icsk_ca_ops = ca; |
|---|
| 376 | | - module_put(old_ca->owner); |
|---|
| 377 | | - } |
|---|
| 378 | | - } else { |
|---|
| 379 | | - err = -EBUSY; |
|---|
| 380 | | - } |
|---|
| 381 | | - } else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || cap_net_admin)) { |
|---|
| 376 | + else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || cap_net_admin)) |
|---|
| 382 | 377 | err = -EPERM; |
|---|
| 383 | | - } else if (!try_module_get(ca->owner)) { |
|---|
| 378 | + else if (!bpf_try_module_get(ca, ca->owner)) |
|---|
| 384 | 379 | err = -EBUSY; |
|---|
| 385 | | - } else { |
|---|
| 380 | + else |
|---|
| 386 | 381 | tcp_reinit_congestion_control(sk, ca); |
|---|
| 387 | | - } |
|---|
| 388 | 382 | out: |
|---|
| 389 | 383 | rcu_read_unlock(); |
|---|
| 390 | 384 | return err; |
|---|