tcp_subr.c (e3ba94d4f34e9f3a1d25396afffe2f5cbf4f5286) tcp_subr.c (b8d60729deefa0bd13e6a395fcab4928e6e10445)
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 2123 unchanged lines hidden (view full) ---

2132 tp->t_fb = tcp_func_set_ptr;
2133 refcount_acquire(&tp->t_fb->tfb_refcnt);
2134 rw_runlock(&tcp_function_lock);
2135 /*
2136 * Use the current system default CC algorithm.
2137 */
2138 CC_LIST_RLOCK();
2139 KASSERT(!STAILQ_EMPTY(&cc_list), ("cc_list is empty!"));
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 2123 unchanged lines hidden (view full) ---

2132 tp->t_fb = tcp_func_set_ptr;
2133 refcount_acquire(&tp->t_fb->tfb_refcnt);
2134 rw_runlock(&tcp_function_lock);
2135 /*
2136 * Use the current system default CC algorithm.
2137 */
2138 CC_LIST_RLOCK();
2139 KASSERT(!STAILQ_EMPTY(&cc_list), ("cc_list is empty!"));
2140 CC_ALGO(tp) = CC_DEFAULT();
2140 CC_ALGO(tp) = CC_DEFAULT_ALGO();
2141 CC_LIST_RUNLOCK();
2141 CC_LIST_RUNLOCK();
2142
2142 /*
2143 * The tcpcb will hold a reference on its inpcb until tcp_discardcb()
2144 * is called.
2145 */
2146 in_pcbref(inp); /* Reference for tcpcb */
2147 tp->t_inpcb = inp;
2148
2149 if (CC_ALGO(tp)->cb_init != NULL)
2143 /*
2144 * The tcpcb will hold a reference on its inpcb until tcp_discardcb()
2145 * is called.
2146 */
2147 in_pcbref(inp); /* Reference for tcpcb */
2148 tp->t_inpcb = inp;
2149
2150 if (CC_ALGO(tp)->cb_init != NULL)
2150 if (CC_ALGO(tp)->cb_init(tp->ccv) > 0) {
2151 if (CC_ALGO(tp)->cb_init(tp->ccv, NULL) > 0) {
2151 if (tp->t_fb->tfb_tcp_fb_fini)
2152 (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1);
2153 in_pcbrele_wlocked(inp);
2154 refcount_release(&tp->t_fb->tfb_refcnt);
2155 uma_zfree(V_tcpcb_zone, tm);
2156 return (NULL);
2157 }
2158

--- 76 unchanged lines hidden (view full) ---

2235 tp->t_stats = stats_blob_alloc(V_tcp_perconn_stats_dflt_tpl, 0);
2236#endif
2237 if (V_tcp_do_lrd)
2238 tp->t_flags |= TF_LRD;
2239 return (tp); /* XXX */
2240}
2241
2242/*
2152 if (tp->t_fb->tfb_tcp_fb_fini)
2153 (*tp->t_fb->tfb_tcp_fb_fini)(tp, 1);
2154 in_pcbrele_wlocked(inp);
2155 refcount_release(&tp->t_fb->tfb_refcnt);
2156 uma_zfree(V_tcpcb_zone, tm);
2157 return (NULL);
2158 }
2159

--- 76 unchanged lines hidden (view full) ---

2236 tp->t_stats = stats_blob_alloc(V_tcp_perconn_stats_dflt_tpl, 0);
2237#endif
2238 if (V_tcp_do_lrd)
2239 tp->t_flags |= TF_LRD;
2240 return (tp); /* XXX */
2241}
2242
2243/*
2243 * Switch the congestion control algorithm back to NewReno for any active
2244 * control blocks using an algorithm which is about to go away.
2245 * This ensures the CC framework can allow the unload to proceed without leaving
2246 * any dangling pointers which would trigger a panic.
2247 * Returning non-zero would inform the CC framework that something went wrong
2248 * and it would be unsafe to allow the unload to proceed. However, there is no
2249 * way for this to occur with this implementation so we always return zero.
2244 * Switch the congestion control algorithm back to Vnet default for any active
2245 * control blocks using an algorithm which is about to go away. If the algorithm
2246 * has a cb_init function and it fails (no memory) then the operation fails and
2247 * the unload will not succeed.
2248 *
2250 */
2251int
2252tcp_ccalgounload(struct cc_algo *unload_algo)
2253{
2249 */
2250int
2251tcp_ccalgounload(struct cc_algo *unload_algo)
2252{
2254 struct cc_algo *tmpalgo;
2253 struct cc_algo *oldalgo, *newalgo;
2255 struct inpcb *inp;
2256 struct tcpcb *tp;
2257 VNET_ITERATOR_DECL(vnet_iter);
2258
2259 /*
2260 * Check all active control blocks across all network stacks and change
2254 struct inpcb *inp;
2255 struct tcpcb *tp;
2256 VNET_ITERATOR_DECL(vnet_iter);
2257
2258 /*
2259 * Check all active control blocks across all network stacks and change
2261 * any that are using "unload_algo" back to NewReno. If "unload_algo"
2260 * any that are using "unload_algo" back to its default. If "unload_algo"
2262 * requires cleanup code to be run, call it.
2263 */
2264 VNET_LIST_RLOCK();
2265 VNET_FOREACH(vnet_iter) {
2266 CURVNET_SET(vnet_iter);
2267 INP_INFO_WLOCK(&V_tcbinfo);
2268 /*
2269 * New connections already part way through being initialised
2270 * with the CC algo we're removing will not race with this code
2271 * because the INP_INFO_WLOCK is held during initialisation. We
2272 * therefore don't enter the loop below until the connection
2273 * list has stabilised.
2274 */
2261 * requires cleanup code to be run, call it.
2262 */
2263 VNET_LIST_RLOCK();
2264 VNET_FOREACH(vnet_iter) {
2265 CURVNET_SET(vnet_iter);
2266 INP_INFO_WLOCK(&V_tcbinfo);
2267 /*
2268 * New connections already part way through being initialised
2269 * with the CC algo we're removing will not race with this code
2270 * because the INP_INFO_WLOCK is held during initialisation. We
2271 * therefore don't enter the loop below until the connection
2272 * list has stabilised.
2273 */
2274 newalgo = CC_DEFAULT_ALGO();
2275 CK_LIST_FOREACH(inp, &V_tcb, inp_list) {
2276 INP_WLOCK(inp);
2277 /* Important to skip tcptw structs. */
2278 if (!(inp->inp_flags & INP_TIMEWAIT) &&
2279 (tp = intotcpcb(inp)) != NULL) {
2280 /*
2281 * By holding INP_WLOCK here, we are assured
2282 * that the connection is not currently
2275 CK_LIST_FOREACH(inp, &V_tcb, inp_list) {
2276 INP_WLOCK(inp);
2277 /* Important to skip tcptw structs. */
2278 if (!(inp->inp_flags & INP_TIMEWAIT) &&
2279 (tp = intotcpcb(inp)) != NULL) {
2280 /*
2281 * By holding INP_WLOCK here, we are assured
2282 * that the connection is not currently
2283 * executing inside the CC module's functions
2284 * i.e. it is safe to make the switch back to
2285 * NewReno.
2283 * executing inside the CC module's functions.
2284 * We attempt to switch to the Vnets default,
2285 * if the init fails then we fail the whole
2286 * operation and the module unload will fail.
2286 */
2287 if (CC_ALGO(tp) == unload_algo) {
2287 */
2288 if (CC_ALGO(tp) == unload_algo) {
2288 tmpalgo = CC_ALGO(tp);
2289 if (tmpalgo->cb_destroy != NULL)
2290 tmpalgo->cb_destroy(tp->ccv);
2291 CC_DATA(tp) = NULL;
2292 /*
2293 * NewReno may allocate memory on
2294 * demand for certain stateful
2295 * configuration as needed, but is
2296 * coded to never fail on memory
2297 * allocation failure so it is a safe
2298 * fallback.
2299 */
2300 CC_ALGO(tp) = &newreno_cc_algo;
2289 struct cc_var cc_mem;
2290 int err;
2291
2292 oldalgo = CC_ALGO(tp);
2293 memset(&cc_mem, 0, sizeof(cc_mem));
2294 cc_mem.ccvc.tcp = tp;
2295 if (newalgo->cb_init == NULL) {
2296 /*
2297 * No init we can skip the
2298 * dance around a possible failure.
2299 */
2300 CC_DATA(tp) = NULL;
2301 goto proceed;
2302 }
2303 err = (newalgo->cb_init)(&cc_mem, NULL);
2304 if (err) {
2305 /*
2306 * Presumably no memory the caller will
2307 * need to try again.
2308 */
2309 INP_WUNLOCK(inp);
2310 INP_INFO_WUNLOCK(&V_tcbinfo);
2311 CURVNET_RESTORE();
2312 VNET_LIST_RUNLOCK();
2313 return (err);
2314 }
2315proceed:
2316 if (oldalgo->cb_destroy != NULL)
2317 oldalgo->cb_destroy(tp->ccv);
2318 CC_ALGO(tp) = newalgo;
2319 memcpy(tp->ccv, &cc_mem, sizeof(struct cc_var));
2320 if (TCPS_HAVEESTABLISHED(tp->t_state) &&
2321 (CC_ALGO(tp)->conn_init != NULL)) {
2322 /* Yep run the connection init for the new CC */
2323 CC_ALGO(tp)->conn_init(tp->ccv);
2324 }
2301 }
2302 }
2303 INP_WUNLOCK(inp);
2304 }
2305 INP_INFO_WUNLOCK(&V_tcbinfo);
2306 CURVNET_RESTORE();
2307 }
2308 VNET_LIST_RUNLOCK();
2325 }
2326 }
2327 INP_WUNLOCK(inp);
2328 }
2329 INP_INFO_WUNLOCK(&V_tcbinfo);
2330 CURVNET_RESTORE();
2331 }
2332 VNET_LIST_RUNLOCK();
2309
2310 return (0);
2311}
2312
2313/*
2314 * Drop a TCP connection, reporting
2315 * the specified error. If connection is synchronized,
2316 * then send a RST to peer.
2317 */

--- 1879 unchanged lines hidden ---
2333 return (0);
2334}
2335
2336/*
2337 * Drop a TCP connection, reporting
2338 * the specified error. If connection is synchronized,
2339 * then send a RST to peer.
2340 */

--- 1879 unchanged lines hidden ---