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 --- |