Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_usrreq.c
Show First 20 Lines • Show All 2,001 Lines • ▼ Show 20 Lines | if (sopt->sopt_valsize == sizeof(tls_v0)) { | ||||
tls->tls_vminor = tls_v0.tls_vminor; | tls->tls_vminor = tls_v0.tls_vminor; | ||||
return (0); | return (0); | ||||
} | } | ||||
return (sooptcopyin(sopt, tls, sizeof(*tls), sizeof(*tls))); | return (sooptcopyin(sopt, tls, sizeof(*tls), sizeof(*tls))); | ||||
} | } | ||||
#endif | #endif | ||||
extern struct cc_algo newreno_cc_algo; | |||||
int | int | ||||
tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struct tcpcb *tp) | tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struct tcpcb *tp) | ||||
{ | { | ||||
int error, opt, optval; | int error, opt, optval; | ||||
u_int ui; | u_int ui; | ||||
struct tcp_info ti; | struct tcp_info ti; | ||||
#ifdef KERN_TLS | #ifdef KERN_TLS | ||||
struct tls_enable tls; | struct tls_enable tls; | ||||
▲ Show 20 Lines • Show All 200 Lines • ▼ Show 20 Lines | #ifdef STATS | ||||
stats_blob_destroy(sbp); | stats_blob_destroy(sbp); | ||||
#else | #else | ||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
#endif /* !STATS */ | #endif /* !STATS */ | ||||
break; | break; | ||||
case TCP_CONGESTION: | case TCP_CONGESTION: | ||||
{ | |||||
struct cc_var cc_mem; | |||||
size_t mem_sz; | |||||
void *ptr = NULL; | |||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
error = sooptcopyin(sopt, buf, TCP_CA_NAME_MAX - 1, 1); | error = sooptcopyin(sopt, buf, TCP_CA_NAME_MAX - 1, 1); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
buf[sopt->sopt_valsize] = '\0'; | buf[sopt->sopt_valsize] = '\0'; | ||||
INP_WLOCK_RECHECK(inp); | |||||
CC_LIST_RLOCK(); | CC_LIST_RLOCK(); | ||||
lstewart: With the proposed changes, this block is sufficiently large now that I'd suggest carving… | |||||
Done Inline ActionsSure thats a reasonable thing to do ;) rrs: Sure thats a reasonable thing to do ;)
| |||||
STAILQ_FOREACH(algo, &cc_list, entries) | STAILQ_FOREACH(algo, &cc_list, entries) | ||||
if (strncmp(buf, algo->name, | if (strncmp(buf, algo->name, | ||||
TCP_CA_NAME_MAX) == 0) | TCP_CA_NAME_MAX) == 0) | ||||
break; | break; | ||||
CC_LIST_RUNLOCK(); | |||||
if (algo == NULL) { | if (algo == NULL) { | ||||
INP_WUNLOCK(inp); | CC_LIST_RUNLOCK(); | ||||
error = EINVAL; | error = EINVAL; | ||||
Not Done Inline ActionsSuggest using ESRCH to remain consistent with other CC(9) API functions c.f. cc_default_algo() lstewart: Suggest using ESRCH to remain consistent with other CC(9) API functions c.f. cc_default_algo() | |||||
Done Inline Actionsok rrs: ok | |||||
break; | break; | ||||
} | } | ||||
mem_sz = (*algo->cc_data_sz)(); | |||||
CC_LIST_RUNLOCK(); | |||||
/* We can now pre-get the memory for the CC */ | |||||
if (mem_sz) | |||||
ptr = malloc(mem_sz, M_CC_MEM, M_WAITOK); | |||||
else | |||||
ptr = NULL; | |||||
/* | /* | ||||
* We hold a write lock over the tcb so it's safe to | * Make sure its all clean and zero and also get | ||||
* do these things without ordering concerns. | * back the inplock. | ||||
*/ | */ | ||||
if (CC_ALGO(tp)->cb_destroy != NULL) | memset(&cc_mem, 0, sizeof(cc_mem)); | ||||
CC_ALGO(tp)->cb_destroy(tp->ccv); | if (ptr) { | ||||
CC_DATA(tp) = NULL; | memset(ptr, 0, mem_sz); | ||||
CC_ALGO(tp) = algo; | INP_WLOCK_RECHECK_CLEANUP(inp, free(ptr, M_CC_MEM)); | ||||
} else | |||||
INP_WLOCK_RECHECK(inp); | |||||
cc_mem.ccvc.tcp = tp; | |||||
/* | /* | ||||
* If something goes pear shaped initialising the new | * We once again hold a write lock over the tcb so it's | ||||
* algo, fall back to newreno (which does not | * safe to do these things without ordering concerns. | ||||
* require initialisation). | * | ||||
* XXXrrs: Note there is a danger here, where the | |||||
* CC module is unloaded before we init. I don't | |||||
* address this problem here since the whole CC | |||||
* module is weak in this area, i.e. if you unload | |||||
* a module it can be being used and boom the kernel | |||||
* will crash. The CC modules will need refcounting | |||||
* and require a mod-unload function that can be checked | |||||
* against if there is use which is beyond the scope | |||||
* of this work but should be addressed later. | |||||
* | |||||
* Note here we init into stack memory. | |||||
*/ | */ | ||||
if (algo->cb_init != NULL && | if (algo->cb_init != NULL) | ||||
algo->cb_init(tp->ccv) != 0) { | error = algo->cb_init(&cc_mem, ptr); | ||||
CC_ALGO(tp) = &newreno_cc_algo; | else | ||||
error = 0; | |||||
/* | /* | ||||
* The only reason init should fail is | * Without INVARIANT we must recover and we leave the | ||||
* because of malloc. | * previous CC module in place, by freeing the memory | ||||
* we allocated and letting the return error propagate | |||||
* to the caller. | |||||
*/ | */ | ||||
error = ENOMEM; | if (error == 0) { | ||||
/* | |||||
* Touchdown, lets go ahead and move the | |||||
* connection to the new CC module by | |||||
* copying in the cc_mem after we call | |||||
* the old ones cleanup (if any). | |||||
*/ | |||||
if (CC_ALGO(tp)->cb_destroy != NULL) | |||||
CC_ALGO(tp)->cb_destroy(tp->ccv); | |||||
memcpy(tp->ccv, &cc_mem, sizeof(struct cc_var)); | |||||
tp->cc_algo = algo; | |||||
/* Ok now are we where we have gotten past any conn_init? */ | |||||
if (TCPS_HAVEESTABLISHED(tp->t_state) && (CC_ALGO(tp)->conn_init != NULL)) { | |||||
/* Yep run the connection init for the new CC */ | |||||
CC_ALGO(tp)->conn_init(tp->ccv); | |||||
} | } | ||||
} else if (ptr) | |||||
free(ptr, M_CC_MEM); | |||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
break; | break; | ||||
} | |||||
case TCP_REUSPORT_LB_NUMA: | case TCP_REUSPORT_LB_NUMA: | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
error = sooptcopyin(sopt, &optval, sizeof(optval), | error = sooptcopyin(sopt, &optval, sizeof(optval), | ||||
sizeof(optval)); | sizeof(optval)); | ||||
INP_WLOCK_RECHECK(inp); | INP_WLOCK_RECHECK(inp); | ||||
if (!error) | if (!error) | ||||
error = in_pcblbgroup_numa(inp, optval); | error = in_pcblbgroup_numa(inp, optval); | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
▲ Show 20 Lines • Show All 829 Lines • Show Last 20 Lines |
With the proposed changes, this block is sufficiently large now that I'd suggest carving everything between this line and the INP_WUNLOCK() out into a separate function e.g. cc_switch_algo() in cc.c or similar.