xref: /xnu-10002.81.5/bsd/netinet/tcp_ccdbg.c (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1*5e3eaea3SApple OSS Distributions /*
2*5e3eaea3SApple OSS Distributions  * Copyright (c) 2021 Apple Inc. All rights reserved.
3*5e3eaea3SApple OSS Distributions  *
4*5e3eaea3SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*5e3eaea3SApple OSS Distributions  *
6*5e3eaea3SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*5e3eaea3SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*5e3eaea3SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*5e3eaea3SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*5e3eaea3SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*5e3eaea3SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*5e3eaea3SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*5e3eaea3SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*5e3eaea3SApple OSS Distributions  *
15*5e3eaea3SApple OSS Distributions  * Please obtain a copy of the License at
16*5e3eaea3SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*5e3eaea3SApple OSS Distributions  *
18*5e3eaea3SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*5e3eaea3SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*5e3eaea3SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*5e3eaea3SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*5e3eaea3SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*5e3eaea3SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*5e3eaea3SApple OSS Distributions  * limitations under the License.
25*5e3eaea3SApple OSS Distributions  *
26*5e3eaea3SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*5e3eaea3SApple OSS Distributions  */
28*5e3eaea3SApple OSS Distributions 
29*5e3eaea3SApple OSS Distributions #include "tcp_includes.h"
30*5e3eaea3SApple OSS Distributions 
31*5e3eaea3SApple OSS Distributions #include <sys/domain.h>
32*5e3eaea3SApple OSS Distributions #include <sys/sdt.h>
33*5e3eaea3SApple OSS Distributions 
34*5e3eaea3SApple OSS Distributions #define TCP_CCDBG_NOUNIT 0xffffffff
35*5e3eaea3SApple OSS Distributions static kern_ctl_ref tcp_ccdbg_ctlref = NULL;
36*5e3eaea3SApple OSS Distributions volatile uint32_t tcp_ccdbg_unit = TCP_CCDBG_NOUNIT;
37*5e3eaea3SApple OSS Distributions 
38*5e3eaea3SApple OSS Distributions /* Allow only one socket to connect at any time for debugging */
39*5e3eaea3SApple OSS Distributions static errno_t
tcp_ccdbg_control_connect(kern_ctl_ref kctl,struct sockaddr_ctl * sac,void ** uinfo)40*5e3eaea3SApple OSS Distributions tcp_ccdbg_control_connect(kern_ctl_ref kctl, struct sockaddr_ctl *sac,
41*5e3eaea3SApple OSS Distributions     void **uinfo)
42*5e3eaea3SApple OSS Distributions {
43*5e3eaea3SApple OSS Distributions #pragma unused(kctl)
44*5e3eaea3SApple OSS Distributions #pragma unused(uinfo)
45*5e3eaea3SApple OSS Distributions 
46*5e3eaea3SApple OSS Distributions 	UInt32 old_value = TCP_CCDBG_NOUNIT;
47*5e3eaea3SApple OSS Distributions 	UInt32 new_value = sac->sc_unit;
48*5e3eaea3SApple OSS Distributions 
49*5e3eaea3SApple OSS Distributions 	if (tcp_ccdbg_unit != old_value) {
50*5e3eaea3SApple OSS Distributions 		return EALREADY;
51*5e3eaea3SApple OSS Distributions 	}
52*5e3eaea3SApple OSS Distributions 
53*5e3eaea3SApple OSS Distributions 	if (OSCompareAndSwap(old_value, new_value, &tcp_ccdbg_unit)) {
54*5e3eaea3SApple OSS Distributions 		return 0;
55*5e3eaea3SApple OSS Distributions 	} else {
56*5e3eaea3SApple OSS Distributions 		return EALREADY;
57*5e3eaea3SApple OSS Distributions 	}
58*5e3eaea3SApple OSS Distributions }
59*5e3eaea3SApple OSS Distributions 
60*5e3eaea3SApple OSS Distributions static errno_t
tcp_ccdbg_control_disconnect(kern_ctl_ref kctl,u_int32_t unit,void * uinfo)61*5e3eaea3SApple OSS Distributions tcp_ccdbg_control_disconnect(kern_ctl_ref kctl, u_int32_t unit, void *uinfo)
62*5e3eaea3SApple OSS Distributions {
63*5e3eaea3SApple OSS Distributions #pragma unused(kctl, unit, uinfo)
64*5e3eaea3SApple OSS Distributions 
65*5e3eaea3SApple OSS Distributions 	if (unit == tcp_ccdbg_unit) {
66*5e3eaea3SApple OSS Distributions 		UInt32 old_value = tcp_ccdbg_unit;
67*5e3eaea3SApple OSS Distributions 		UInt32 new_value = TCP_CCDBG_NOUNIT;
68*5e3eaea3SApple OSS Distributions 		if (tcp_ccdbg_unit == new_value) {
69*5e3eaea3SApple OSS Distributions 			return 0;
70*5e3eaea3SApple OSS Distributions 		}
71*5e3eaea3SApple OSS Distributions 
72*5e3eaea3SApple OSS Distributions 		if (!OSCompareAndSwap(old_value, new_value,
73*5e3eaea3SApple OSS Distributions 		    &tcp_ccdbg_unit)) {
74*5e3eaea3SApple OSS Distributions 			log(LOG_DEBUG,
75*5e3eaea3SApple OSS Distributions 			    "failed to disconnect tcp_cc debug control");
76*5e3eaea3SApple OSS Distributions 		}
77*5e3eaea3SApple OSS Distributions 	}
78*5e3eaea3SApple OSS Distributions 	return 0;
79*5e3eaea3SApple OSS Distributions }
80*5e3eaea3SApple OSS Distributions 
81*5e3eaea3SApple OSS Distributions inline void
tcp_ccdbg_trace(struct tcpcb * tp,struct tcphdr * th,int32_t event)82*5e3eaea3SApple OSS Distributions tcp_ccdbg_trace(struct tcpcb *tp, struct tcphdr *th, int32_t event)
83*5e3eaea3SApple OSS Distributions {
84*5e3eaea3SApple OSS Distributions #if !CONFIG_DTRACE
85*5e3eaea3SApple OSS Distributions #pragma unused(th)
86*5e3eaea3SApple OSS Distributions #endif /* !CONFIG_DTRACE */
87*5e3eaea3SApple OSS Distributions 	struct inpcb *inp = tp->t_inpcb;
88*5e3eaea3SApple OSS Distributions 
89*5e3eaea3SApple OSS Distributions 	if (tcp_cc_debug && tcp_ccdbg_unit > 0) {
90*5e3eaea3SApple OSS Distributions 		struct tcp_cc_debug_state dbg_state;
91*5e3eaea3SApple OSS Distributions 		struct timespec tv;
92*5e3eaea3SApple OSS Distributions 
93*5e3eaea3SApple OSS Distributions 		bzero(&dbg_state, sizeof(dbg_state));
94*5e3eaea3SApple OSS Distributions 
95*5e3eaea3SApple OSS Distributions 		nanotime(&tv);
96*5e3eaea3SApple OSS Distributions 		/* Take time in seconds */
97*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_tsns = (tv.tv_sec * 1000000000) + tv.tv_nsec;
98*5e3eaea3SApple OSS Distributions 		inet_ntop(SOCK_DOM(inp->inp_socket),
99*5e3eaea3SApple OSS Distributions 		    ((SOCK_DOM(inp->inp_socket) == PF_INET) ?
100*5e3eaea3SApple OSS Distributions 		    (void *)&inp->inp_laddr.s_addr :
101*5e3eaea3SApple OSS Distributions 		    (void *)&inp->in6p_laddr), dbg_state.ccd_srcaddr,
102*5e3eaea3SApple OSS Distributions 		    sizeof(dbg_state.ccd_srcaddr));
103*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_srcport = ntohs(inp->inp_lport);
104*5e3eaea3SApple OSS Distributions 		inet_ntop(SOCK_DOM(inp->inp_socket),
105*5e3eaea3SApple OSS Distributions 		    ((SOCK_DOM(inp->inp_socket) == PF_INET) ?
106*5e3eaea3SApple OSS Distributions 		    (void *)&inp->inp_faddr.s_addr :
107*5e3eaea3SApple OSS Distributions 		    (void *)&inp->in6p_faddr), dbg_state.ccd_destaddr,
108*5e3eaea3SApple OSS Distributions 		    sizeof(dbg_state.ccd_destaddr));
109*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_destport = ntohs(inp->inp_fport);
110*5e3eaea3SApple OSS Distributions 
111*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_snd_cwnd = tp->snd_cwnd;
112*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_snd_wnd = tp->snd_wnd;
113*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_snd_ssthresh = tp->snd_ssthresh;
114*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_pipeack = tp->t_pipeack;
115*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_rttcur = tp->t_rttcur;
116*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_rxtcur = tp->t_rxtcur;
117*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_srtt = tp->t_srtt >> TCP_RTT_SHIFT;
118*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_event = event;
119*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_sndcc = inp->inp_socket->so_snd.sb_cc;
120*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_sndhiwat = inp->inp_socket->so_snd.sb_hiwat;
121*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_bytes_acked = tp->t_bytes_acked;
122*5e3eaea3SApple OSS Distributions 		dbg_state.ccd_cc_index = tp->tcp_cc_index;
123*5e3eaea3SApple OSS Distributions 		switch (tp->tcp_cc_index) {
124*5e3eaea3SApple OSS Distributions 		case TCP_CC_ALGO_CUBIC_INDEX:
125*5e3eaea3SApple OSS Distributions 			dbg_state.u.cubic_state.ccd_last_max =
126*5e3eaea3SApple OSS Distributions 			    tp->t_ccstate->cub_last_max;
127*5e3eaea3SApple OSS Distributions 			dbg_state.u.cubic_state.ccd_tcp_win =
128*5e3eaea3SApple OSS Distributions 			    tp->t_ccstate->cub_tcp_win;
129*5e3eaea3SApple OSS Distributions 			dbg_state.u.cubic_state.ccd_avg_lastmax =
130*5e3eaea3SApple OSS Distributions 			    tp->t_ccstate->cub_avg_lastmax;
131*5e3eaea3SApple OSS Distributions 			dbg_state.u.cubic_state.ccd_mean_deviation =
132*5e3eaea3SApple OSS Distributions 			    tp->t_ccstate->cub_mean_dev;
133*5e3eaea3SApple OSS Distributions 			break;
134*5e3eaea3SApple OSS Distributions 		case TCP_CC_ALGO_BACKGROUND_INDEX:
135*5e3eaea3SApple OSS Distributions 			dbg_state.u.ledbat_state.led_base_rtt =
136*5e3eaea3SApple OSS Distributions 			    get_base_rtt(tp);
137*5e3eaea3SApple OSS Distributions 			break;
138*5e3eaea3SApple OSS Distributions 		default:
139*5e3eaea3SApple OSS Distributions 			break;
140*5e3eaea3SApple OSS Distributions 		}
141*5e3eaea3SApple OSS Distributions 
142*5e3eaea3SApple OSS Distributions 		ctl_enqueuedata(tcp_ccdbg_ctlref, tcp_ccdbg_unit,
143*5e3eaea3SApple OSS Distributions 		    &dbg_state, sizeof(dbg_state), 0);
144*5e3eaea3SApple OSS Distributions 	}
145*5e3eaea3SApple OSS Distributions 	DTRACE_TCP5(cc, void, NULL, struct inpcb *, inp,
146*5e3eaea3SApple OSS Distributions 	    struct tcpcb *, tp, struct tcphdr *, th, int32_t, event);
147*5e3eaea3SApple OSS Distributions }
148*5e3eaea3SApple OSS Distributions 
149*5e3eaea3SApple OSS Distributions void
tcp_ccdbg_control_register(void)150*5e3eaea3SApple OSS Distributions tcp_ccdbg_control_register(void)
151*5e3eaea3SApple OSS Distributions {
152*5e3eaea3SApple OSS Distributions 	struct kern_ctl_reg ccdbg_control;
153*5e3eaea3SApple OSS Distributions 	errno_t err;
154*5e3eaea3SApple OSS Distributions 
155*5e3eaea3SApple OSS Distributions 	bzero(&ccdbg_control, sizeof(ccdbg_control));
156*5e3eaea3SApple OSS Distributions 	strlcpy(ccdbg_control.ctl_name, TCP_CC_CONTROL_NAME,
157*5e3eaea3SApple OSS Distributions 	    sizeof(ccdbg_control.ctl_name));
158*5e3eaea3SApple OSS Distributions 	ccdbg_control.ctl_connect = tcp_ccdbg_control_connect;
159*5e3eaea3SApple OSS Distributions 	ccdbg_control.ctl_disconnect = tcp_ccdbg_control_disconnect;
160*5e3eaea3SApple OSS Distributions 	ccdbg_control.ctl_flags |= CTL_FLAG_PRIVILEGED;
161*5e3eaea3SApple OSS Distributions 	ccdbg_control.ctl_flags |= CTL_FLAG_REG_SOCK_STREAM;
162*5e3eaea3SApple OSS Distributions 	ccdbg_control.ctl_sendsize = 32 * 1024;
163*5e3eaea3SApple OSS Distributions 
164*5e3eaea3SApple OSS Distributions 	err = ctl_register(&ccdbg_control, &tcp_ccdbg_ctlref);
165*5e3eaea3SApple OSS Distributions 	if (err != 0) {
166*5e3eaea3SApple OSS Distributions 		log(LOG_ERR, "failed to register tcp_cc debug control");
167*5e3eaea3SApple OSS Distributions 	}
168*5e3eaea3SApple OSS Distributions }
169