Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/tcp_usrreq.c
| Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
| #include "opt_inet.h" | #include "opt_inet.h" | ||||
| #include "opt_inet6.h" | #include "opt_inet6.h" | ||||
| #include "opt_ipsec.h" | #include "opt_ipsec.h" | ||||
| #include "opt_kern_tls.h" | #include "opt_kern_tls.h" | ||||
| #include "opt_tcpdebug.h" | #include "opt_tcpdebug.h" | ||||
| #include <sys/param.h> | #include <sys/param.h> | ||||
| #include <sys/systm.h> | #include <sys/systm.h> | ||||
| #include <sys/arb.h> | |||||
| #include <sys/limits.h> | #include <sys/limits.h> | ||||
| #include <sys/malloc.h> | #include <sys/malloc.h> | ||||
| #include <sys/refcount.h> | #include <sys/refcount.h> | ||||
| #include <sys/kernel.h> | #include <sys/kernel.h> | ||||
| #include <sys/ktls.h> | #include <sys/ktls.h> | ||||
| #include <sys/qmath.h> | |||||
| #include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
| #include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
| #ifdef INET6 | #ifdef INET6 | ||||
| #include <sys/domain.h> | #include <sys/domain.h> | ||||
| #endif /* INET6 */ | #endif /* INET6 */ | ||||
| #include <sys/socket.h> | #include <sys/socket.h> | ||||
| #include <sys/socketvar.h> | #include <sys/socketvar.h> | ||||
| #include <sys/protosw.h> | #include <sys/protosw.h> | ||||
| #include <sys/proc.h> | #include <sys/proc.h> | ||||
| #include <sys/jail.h> | #include <sys/jail.h> | ||||
| #include <sys/syslog.h> | #include <sys/syslog.h> | ||||
| #include <sys/stats.h> | |||||
| #ifdef DDB | #ifdef DDB | ||||
| #include <ddb/ddb.h> | #include <ddb/ddb.h> | ||||
| #endif | #endif | ||||
| #include <net/if.h> | #include <net/if.h> | ||||
| #include <net/if_var.h> | #include <net/if_var.h> | ||||
| #include <net/route.h> | #include <net/route.h> | ||||
| Show All 27 Lines | |||||
| #ifdef TCPDEBUG | #ifdef TCPDEBUG | ||||
| #include <netinet/tcp_debug.h> | #include <netinet/tcp_debug.h> | ||||
| #endif | #endif | ||||
| #ifdef TCP_OFFLOAD | #ifdef TCP_OFFLOAD | ||||
| #include <netinet/tcp_offload.h> | #include <netinet/tcp_offload.h> | ||||
| #endif | #endif | ||||
| #include <netipsec/ipsec_support.h> | #include <netipsec/ipsec_support.h> | ||||
| #include <vm/vm.h> | |||||
| #include <vm/vm_param.h> | |||||
| #include <vm/pmap.h> | |||||
| #include <vm/vm_extern.h> | |||||
| #include <vm/vm_map.h> | |||||
| #include <vm/vm_page.h> | |||||
| /* | /* | ||||
| * TCP protocol interface to socket abstraction. | * TCP protocol interface to socket abstraction. | ||||
| */ | */ | ||||
| static int tcp_attach(struct socket *); | static int tcp_attach(struct socket *); | ||||
| #ifdef INET | #ifdef INET | ||||
| static int tcp_connect(struct tcpcb *, struct sockaddr *, | static int tcp_connect(struct tcpcb *, struct sockaddr *, | ||||
| struct thread *td); | struct thread *td); | ||||
| #endif /* INET */ | #endif /* INET */ | ||||
| ▲ Show 20 Lines • Show All 1,451 Lines • ▼ Show 20 Lines | tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti) | ||||
| if ((tp->t_flags & TF_REQ_SCALE) && (tp->t_flags & TF_RCVD_SCALE)) { | if ((tp->t_flags & TF_REQ_SCALE) && (tp->t_flags & TF_RCVD_SCALE)) { | ||||
| ti->tcpi_options |= TCPI_OPT_WSCALE; | ti->tcpi_options |= TCPI_OPT_WSCALE; | ||||
| ti->tcpi_snd_wscale = tp->snd_scale; | ti->tcpi_snd_wscale = tp->snd_scale; | ||||
| ti->tcpi_rcv_wscale = tp->rcv_scale; | ti->tcpi_rcv_wscale = tp->rcv_scale; | ||||
| } | } | ||||
| if (tp->t_flags & TF_ECN_PERMIT) | if (tp->t_flags & TF_ECN_PERMIT) | ||||
| ti->tcpi_options |= TCPI_OPT_ECN; | ti->tcpi_options |= TCPI_OPT_ECN; | ||||
| ti->tcpi_rto = tp->t_rxtcur * tick; | ti->tcpi_rto = tp->t_rxtcur * tick; | ||||
allanjude: should the fixup of missing TF_FASTOPEN bits be a separate commit? | |||||
| ti->tcpi_last_data_recv = ((uint32_t)ticks - tp->t_rcvtime) * tick; | ti->tcpi_last_data_recv = ((uint32_t)ticks - tp->t_rcvtime) * tick; | ||||
| ti->tcpi_rtt = ((u_int64_t)tp->t_srtt * tick) >> TCP_RTT_SHIFT; | ti->tcpi_rtt = ((u_int64_t)tp->t_srtt * tick) >> TCP_RTT_SHIFT; | ||||
| ti->tcpi_rttvar = ((u_int64_t)tp->t_rttvar * tick) >> TCP_RTTVAR_SHIFT; | ti->tcpi_rttvar = ((u_int64_t)tp->t_rttvar * tick) >> TCP_RTTVAR_SHIFT; | ||||
| ti->tcpi_snd_ssthresh = tp->snd_ssthresh; | ti->tcpi_snd_ssthresh = tp->snd_ssthresh; | ||||
| ti->tcpi_snd_cwnd = tp->snd_cwnd; | ti->tcpi_snd_cwnd = tp->snd_cwnd; | ||||
| /* | /* | ||||
| ▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | 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; | ||||
| #endif | #endif | ||||
| struct cc_algo *algo; | struct cc_algo *algo; | ||||
| char *pbuf, buf[TCP_LOG_ID_LEN]; | char *pbuf, buf[TCP_LOG_ID_LEN]; | ||||
| #ifdef STATS | |||||
| struct statsblob *sbp; | |||||
| #endif | |||||
| size_t len; | size_t len; | ||||
| /* | /* | ||||
| * For TCP_CCALGOOPT forward the control to CC module, for both | * For TCP_CCALGOOPT forward the control to CC module, for both | ||||
| * SOPT_SET and SOPT_GET. | * SOPT_SET and SOPT_GET. | ||||
| */ | */ | ||||
| switch (sopt->sopt_name) { | switch (sopt->sopt_name) { | ||||
| case TCP_CCALGOOPT: | case TCP_CCALGOOPT: | ||||
| ▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | case TCP_MAXSEG: | ||||
| error = EINVAL; | error = EINVAL; | ||||
| goto unlock_and_done; | goto unlock_and_done; | ||||
| case TCP_INFO: | case TCP_INFO: | ||||
| INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
| error = EINVAL; | error = EINVAL; | ||||
| break; | break; | ||||
| case TCP_STATS: | |||||
| INP_WUNLOCK(inp); | |||||
| #ifdef STATS | |||||
Done Inline ActionsThe INP_WUNLOCK can be shifted outside the #ifdef lstewart: The INP_WUNLOCK can be shifted outside the `#ifdef` | |||||
| error = sooptcopyin(sopt, &optval, sizeof optval, | |||||
| sizeof optval); | |||||
| if (error) | |||||
| return (error); | |||||
| if (optval > 0) | |||||
| sbp = stats_blob_alloc( | |||||
| V_tcp_perconn_stats_dflt_tpl, 0); | |||||
| else | |||||
| sbp = NULL; | |||||
| INP_WLOCK_RECHECK(inp); | |||||
| if ((tp->t_stats != NULL && sbp == NULL) || | |||||
| (tp->t_stats == NULL && sbp != NULL)) { | |||||
| struct statsblob *t = tp->t_stats; | |||||
| tp->t_stats = sbp; | |||||
| sbp = t; | |||||
| } | |||||
| INP_WUNLOCK(inp); | |||||
| stats_blob_destroy(sbp); | |||||
| #else | |||||
| return (EOPNOTSUPP); | |||||
| #endif /* !STATS */ | |||||
| break; | |||||
| case TCP_CONGESTION: | case TCP_CONGESTION: | ||||
| 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); | INP_WLOCK_RECHECK(inp); | ||||
| CC_LIST_RLOCK(); | CC_LIST_RLOCK(); | ||||
| ▲ Show 20 Lines • Show All 268 Lines • ▼ Show 20 Lines | case TCP_NOPUSH: | ||||
| INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
| error = sooptcopyout(sopt, &optval, sizeof optval); | error = sooptcopyout(sopt, &optval, sizeof optval); | ||||
| break; | break; | ||||
| case TCP_INFO: | case TCP_INFO: | ||||
| tcp_fill_info(tp, &ti); | tcp_fill_info(tp, &ti); | ||||
| INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
| error = sooptcopyout(sopt, &ti, sizeof ti); | error = sooptcopyout(sopt, &ti, sizeof ti); | ||||
| break; | break; | ||||
| case TCP_STATS: | |||||
| { | |||||
| #ifdef STATS | |||||
| int nheld; | |||||
| TYPEOF_MEMBER(struct statsblob, flags) sbflags = 0; | |||||
| error = 0; | |||||
| socklen_t outsbsz = sopt->sopt_valsize; | |||||
| if (tp->t_stats == NULL) | |||||
| error = ENOENT; | |||||
| else if (outsbsz >= tp->t_stats->cursz) | |||||
| outsbsz = tp->t_stats->cursz; | |||||
| else if (outsbsz >= sizeof(struct statsblob)) | |||||
| outsbsz = sizeof(struct statsblob); | |||||
| else | |||||
| error = EINVAL; | |||||
| INP_WUNLOCK(inp); | |||||
| if (error) | |||||
| break; | |||||
| sbp = sopt->sopt_val; | |||||
| nheld = atop(round_page(((vm_offset_t)sbp) + | |||||
| (vm_size_t)outsbsz) - trunc_page((vm_offset_t)sbp)); | |||||
| vm_page_t ma[nheld]; | |||||
| if (vm_fault_quick_hold_pages( | |||||
| &curproc->p_vmspace->vm_map, (vm_offset_t)sbp, | |||||
| outsbsz, VM_PROT_READ | VM_PROT_WRITE, ma, | |||||
| nheld) < 0) { | |||||
| error = EFAULT; | |||||
| break; | |||||
| } | |||||
| if ((error = copyin_nofault(&(sbp->flags), &sbflags, | |||||
| SIZEOF_MEMBER(struct statsblob, flags)))) | |||||
| goto unhold; | |||||
| INP_WLOCK_RECHECK(inp); | |||||
| error = stats_blob_snapshot(&sbp, outsbsz, tp->t_stats, | |||||
| sbflags | SB_CLONE_USRDSTNOFAULT); | |||||
| INP_WUNLOCK(inp); | |||||
| sopt->sopt_valsize = outsbsz; | |||||
| unhold: | |||||
| vm_page_unhold_pages(ma, nheld); | |||||
| #else | |||||
| INP_WUNLOCK(inp); | |||||
| error = EOPNOTSUPP; | |||||
| #endif /* !STATS */ | |||||
| break; | |||||
| } | |||||
| case TCP_CONGESTION: | case TCP_CONGESTION: | ||||
| len = strlcpy(buf, CC_ALGO(tp)->name, TCP_CA_NAME_MAX); | len = strlcpy(buf, CC_ALGO(tp)->name, TCP_CA_NAME_MAX); | ||||
| INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
| error = sooptcopyout(sopt, buf, len + 1); | error = sooptcopyout(sopt, buf, len + 1); | ||||
| break; | break; | ||||
| case TCP_KEEPIDLE: | case TCP_KEEPIDLE: | ||||
| case TCP_KEEPINTVL: | case TCP_KEEPINTVL: | ||||
| case TCP_KEEPINIT: | case TCP_KEEPINIT: | ||||
| ▲ Show 20 Lines • Show All 537 Lines • Show Last 20 Lines | |||||
should the fixup of missing TF_FASTOPEN bits be a separate commit?