xref: /freebsd/sys/netinet/tcp_stacks/rack_pcm.c (revision 382af4d38b62675f00f64275793a6b5fccfe62fa)
1e18b97bdSRandall Stewart /*-
2e18b97bdSRandall Stewart  * Copyright (c) 2024- Netflix, Inc.
3e18b97bdSRandall Stewart  *
4e18b97bdSRandall Stewart  * Redistribution and use in source and binary forms, with or without
5e18b97bdSRandall Stewart  * modification, are permitted provided that the following conditions
6e18b97bdSRandall Stewart  * are met:
7e18b97bdSRandall Stewart  * 1. Redistributions of source code must retain the above copyright
8e18b97bdSRandall Stewart  *    notice, this list of conditions and the following disclaimer.
9e18b97bdSRandall Stewart  * 2. Redistributions in binary form must reproduce the above copyright
10e18b97bdSRandall Stewart  *    notice, this list of conditions and the following disclaimer in the
11e18b97bdSRandall Stewart  *    documentation and/or other materials provided with the distribution.
12e18b97bdSRandall Stewart  *
13e18b97bdSRandall Stewart  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
14e18b97bdSRandall Stewart  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15e18b97bdSRandall Stewart  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16e18b97bdSRandall Stewart  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17e18b97bdSRandall Stewart  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18e18b97bdSRandall Stewart  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19e18b97bdSRandall Stewart  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20e18b97bdSRandall Stewart  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21e18b97bdSRandall Stewart  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22e18b97bdSRandall Stewart  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23e18b97bdSRandall Stewart  * SUCH DAMAGE.
24e18b97bdSRandall Stewart  *
25e18b97bdSRandall Stewart  */
26e18b97bdSRandall Stewart 
27e18b97bdSRandall Stewart #include <sys/cdefs.h>
28e18b97bdSRandall Stewart #include "opt_inet.h"
29e18b97bdSRandall Stewart #include "opt_inet6.h"
30e18b97bdSRandall Stewart #include "opt_ipsec.h"
31e18b97bdSRandall Stewart #include "opt_ratelimit.h"
32e18b97bdSRandall Stewart #include "opt_kern_tls.h"
33e18b97bdSRandall Stewart #if defined(INET) || defined(INET6)
34e18b97bdSRandall Stewart #include <sys/param.h>
35e18b97bdSRandall Stewart #include <sys/arb.h>
36e18b97bdSRandall Stewart #include <sys/module.h>
37e18b97bdSRandall Stewart #include <sys/kernel.h>
38e18b97bdSRandall Stewart #ifdef TCP_HHOOK
39e18b97bdSRandall Stewart #include <sys/hhook.h>
40e18b97bdSRandall Stewart #endif
41e18b97bdSRandall Stewart #include <sys/lock.h>
42e18b97bdSRandall Stewart #include <sys/malloc.h>
43e18b97bdSRandall Stewart #include <sys/lock.h>
44e18b97bdSRandall Stewart #include <sys/mutex.h>
45e18b97bdSRandall Stewart #include <sys/mbuf.h>
46e18b97bdSRandall Stewart #include <sys/proc.h>		/* for proc0 declaration */
47e18b97bdSRandall Stewart #include <sys/socket.h>
48e18b97bdSRandall Stewart #include <sys/socketvar.h>
49e18b97bdSRandall Stewart #include <sys/sysctl.h>
50e18b97bdSRandall Stewart #include <sys/systm.h>
51e18b97bdSRandall Stewart #ifdef STATS
52e18b97bdSRandall Stewart #include <sys/qmath.h>
53e18b97bdSRandall Stewart #include <sys/tree.h>
54e18b97bdSRandall Stewart #include <sys/stats.h> /* Must come after qmath.h and tree.h */
55e18b97bdSRandall Stewart #else
56e18b97bdSRandall Stewart #include <sys/tree.h>
57e18b97bdSRandall Stewart #endif
58e18b97bdSRandall Stewart #include <sys/refcount.h>
59e18b97bdSRandall Stewart #include <sys/queue.h>
60e18b97bdSRandall Stewart #include <sys/tim_filter.h>
61e18b97bdSRandall Stewart #include <sys/smp.h>
62e18b97bdSRandall Stewart #include <sys/kthread.h>
63e18b97bdSRandall Stewart #include <sys/kern_prefetch.h>
64e18b97bdSRandall Stewart #include <sys/protosw.h>
65e18b97bdSRandall Stewart #ifdef TCP_ACCOUNTING
66e18b97bdSRandall Stewart #include <sys/sched.h>
67e18b97bdSRandall Stewart #include <machine/cpu.h>
68e18b97bdSRandall Stewart #endif
69e18b97bdSRandall Stewart #include <vm/uma.h>
70e18b97bdSRandall Stewart 
71e18b97bdSRandall Stewart #include <net/route.h>
72e18b97bdSRandall Stewart #include <net/route/nhop.h>
73e18b97bdSRandall Stewart #include <net/vnet.h>
74e18b97bdSRandall Stewart 
75e18b97bdSRandall Stewart #define TCPSTATES		/* for logging */
76e18b97bdSRandall Stewart 
77e18b97bdSRandall Stewart #include <netinet/in.h>
78e18b97bdSRandall Stewart #include <netinet/in_kdtrace.h>
79e18b97bdSRandall Stewart #include <netinet/in_pcb.h>
80e18b97bdSRandall Stewart #include <netinet/ip.h>
81e18b97bdSRandall Stewart #include <netinet/ip_icmp.h>	/* required for icmp_var.h */
82e18b97bdSRandall Stewart #include <netinet/icmp_var.h>	/* for ICMP_BANDLIM */
83e18b97bdSRandall Stewart #include <netinet/ip_var.h>
84e18b97bdSRandall Stewart #include <netinet/ip6.h>
85e18b97bdSRandall Stewart #include <netinet6/in6_pcb.h>
86e18b97bdSRandall Stewart #include <netinet6/ip6_var.h>
87e18b97bdSRandall Stewart #include <netinet/tcp.h>
88e18b97bdSRandall Stewart #include <netinet/tcp_fsm.h>
89e18b97bdSRandall Stewart #include <netinet/tcp_seq.h>
90e18b97bdSRandall Stewart #include <netinet/tcp_timer.h>
91e18b97bdSRandall Stewart #include <netinet/tcp_var.h>
92e18b97bdSRandall Stewart #include <netinet/tcp_log_buf.h>
93e18b97bdSRandall Stewart #include <netinet/tcp_syncache.h>
94e18b97bdSRandall Stewart #include <netinet/tcp_hpts.h>
95e18b97bdSRandall Stewart #include <netinet/tcp_ratelimit.h>
96e18b97bdSRandall Stewart #include <netinet/tcp_accounting.h>
97e18b97bdSRandall Stewart #include <netinet/tcpip.h>
98e18b97bdSRandall Stewart #include <netinet/cc/cc.h>
99e18b97bdSRandall Stewart #include <netinet/cc/cc_newreno.h>
100e18b97bdSRandall Stewart #include <netinet/tcp_fastopen.h>
101e18b97bdSRandall Stewart #include <netinet/tcp_lro.h>
102e18b97bdSRandall Stewart #ifdef NETFLIX_SHARED_CWND
103e18b97bdSRandall Stewart #include <netinet/tcp_shared_cwnd.h>
104e18b97bdSRandall Stewart #endif
105e18b97bdSRandall Stewart #ifdef TCP_OFFLOAD
106e18b97bdSRandall Stewart #include <netinet/tcp_offload.h>
107e18b97bdSRandall Stewart #endif
108e18b97bdSRandall Stewart #ifdef INET6
109e18b97bdSRandall Stewart #include <netinet6/tcp6_var.h>
110e18b97bdSRandall Stewart #endif
111e18b97bdSRandall Stewart #include <netinet/tcp_ecn.h>
112e18b97bdSRandall Stewart 
113e18b97bdSRandall Stewart #include <netipsec/ipsec_support.h>
114e18b97bdSRandall Stewart 
115e18b97bdSRandall Stewart #if defined(IPSEC) || defined(IPSEC_SUPPORT)
116e18b97bdSRandall Stewart #include <netipsec/ipsec.h>
117e18b97bdSRandall Stewart #include <netipsec/ipsec6.h>
118e18b97bdSRandall Stewart #endif				/* IPSEC */
119e18b97bdSRandall Stewart 
120e18b97bdSRandall Stewart #include <netinet/udp.h>
121e18b97bdSRandall Stewart #include <netinet/udp_var.h>
122e18b97bdSRandall Stewart #include <machine/in_cksum.h>
123e18b97bdSRandall Stewart 
124e18b97bdSRandall Stewart #ifdef MAC
125e18b97bdSRandall Stewart #include <security/mac/mac_framework.h>
126e18b97bdSRandall Stewart #endif
127e18b97bdSRandall Stewart #include "sack_filter.h"
128e18b97bdSRandall Stewart #include "tcp_rack.h"
129e18b97bdSRandall Stewart #include "tailq_hash.h"
130e18b97bdSRandall Stewart #include "rack_bbr_common.h"
131e18b97bdSRandall Stewart 
132e18b97bdSRandall Stewart MALLOC_DECLARE(M_TCPPCM);
133e18b97bdSRandall Stewart 
134e18b97bdSRandall Stewart void
rack_update_pcm_ack(struct tcp_rack * rack,int was_cumack,uint32_t start,uint32_t end)135e18b97bdSRandall Stewart rack_update_pcm_ack(struct tcp_rack *rack, int was_cumack, uint32_t start, uint32_t end)
136e18b97bdSRandall Stewart {
137e18b97bdSRandall Stewart 	struct rack_pcm_stats *e;
138e18b97bdSRandall Stewart 	int i, completed = 0;
139e18b97bdSRandall Stewart 	uint64_t ack_arrival;
140e18b97bdSRandall Stewart 	int segsiz;
141e18b97bdSRandall Stewart 
142e18b97bdSRandall Stewart 	if (rack->pcm_in_progress == 0)
143e18b97bdSRandall Stewart 		return;
144e18b97bdSRandall Stewart 
145e18b97bdSRandall Stewart 	if (SEQ_LEQ(end, rack->r_ctl.pcm_i.sseq)) {
146e18b97bdSRandall Stewart 		/*
147e18b97bdSRandall Stewart 		 * Its not in our range of data sent, it
148e18b97bdSRandall Stewart 		 * is before our first seq.
149e18b97bdSRandall Stewart 		 */
150e18b97bdSRandall Stewart 		return;
151e18b97bdSRandall Stewart 	}
152e18b97bdSRandall Stewart 	/* We take away 1 mss from the end to avoid delayed ack */
153e18b97bdSRandall Stewart 	segsiz = ctf_fixed_maxseg(rack->rc_tp);
154e18b97bdSRandall Stewart 	if (SEQ_GEQ(end, (rack->r_ctl.pcm_i.eseq - segsiz))) {
155e18b97bdSRandall Stewart 		/*
156e18b97bdSRandall Stewart 		 * We have reached beyond the end of the
157e18b97bdSRandall Stewart 		 * initial send. Even though things may
158e18b97bdSRandall Stewart 		 * still be lost and this could be something
159e18b97bdSRandall Stewart 		 * from a different send than our burst.
160e18b97bdSRandall Stewart 		 */
161e18b97bdSRandall Stewart 		completed = 1;
162e18b97bdSRandall Stewart 		rack->pcm_in_progress = 0;
163e18b97bdSRandall Stewart 		rack->r_ctl.last_pcm_round = rack->r_ctl.current_round;
164e18b97bdSRandall Stewart 		rack->r_ctl.pcm_idle_rounds = 0;
165e18b97bdSRandall Stewart 	}
166e18b97bdSRandall Stewart 	if (SEQ_GEQ(start, rack->r_ctl.pcm_i.eseq)) {
167e18b97bdSRandall Stewart 		/*
168e18b97bdSRandall Stewart 		 * This is outside the scope
169e18b97bdSRandall Stewart 		 * of the measurement itself and
170e18b97bdSRandall Stewart 		 * is likely a sack above our burst.
171e18b97bdSRandall Stewart 		 */
172e18b97bdSRandall Stewart 		goto skip_ack_accounting;
173e18b97bdSRandall Stewart 	}
174e18b97bdSRandall Stewart 	/*
175e18b97bdSRandall Stewart 	 * Record ACK data.
176e18b97bdSRandall Stewart 	 */
177e18b97bdSRandall Stewart 	ack_arrival = tcp_tv_to_lusectick(&rack->r_ctl.act_rcv_time);
178e18b97bdSRandall Stewart 	if (SEQ_GT(end, rack->r_ctl.pcm_i.eseq)) {
179e18b97bdSRandall Stewart 		/* Trim the end to the end of our range if it is beyond */
180e18b97bdSRandall Stewart 		end = rack->r_ctl.pcm_i.eseq;
181e18b97bdSRandall Stewart 	}
182e18b97bdSRandall Stewart 	if ((rack->r_ctl.pcm_i.cnt + 1) > rack->r_ctl.pcm_i.cnt_alloc) {
183e18b97bdSRandall Stewart 		/* Need to expand, first is there any present? */
184e18b97bdSRandall Stewart 		size_t sz;
185e18b97bdSRandall Stewart 
186e18b97bdSRandall Stewart 		if (rack->r_ctl.pcm_i.cnt_alloc == 0) {
187e18b97bdSRandall Stewart 			/*
188e18b97bdSRandall Stewart 			 * Failed at rack_init I suppose.
189e18b97bdSRandall Stewart 			 */
190e18b97bdSRandall Stewart 			rack->r_ctl.pcm_i.cnt_alloc = RACK_DEFAULT_PCM_ARRAY;
191e18b97bdSRandall Stewart 			sz = (sizeof(struct rack_pcm_stats) * rack->r_ctl.pcm_i.cnt_alloc);
192e18b97bdSRandall Stewart 			rack->r_ctl.pcm_s = malloc(sz, M_TCPPCM, M_NOWAIT);
193e18b97bdSRandall Stewart 			if (rack->r_ctl.pcm_s == NULL) {
194e18b97bdSRandall Stewart 				rack->r_ctl.pcm_i.cnt_alloc = 0;
195e18b97bdSRandall Stewart 				rack->pcm_in_progress = 0;
196e18b97bdSRandall Stewart 				return;
197e18b97bdSRandall Stewart 			}
198e18b97bdSRandall Stewart 		} else {
199e18b97bdSRandall Stewart 			/* Need to expand the array */
200e18b97bdSRandall Stewart 			struct rack_pcm_stats *n;
201e18b97bdSRandall Stewart 			uint16_t new_cnt;
202e18b97bdSRandall Stewart 
203e18b97bdSRandall Stewart 			new_cnt = rack->r_ctl.pcm_i.cnt_alloc * 2;
204e18b97bdSRandall Stewart 			sz = (sizeof(struct rack_pcm_stats) * new_cnt);
205e18b97bdSRandall Stewart 			n = malloc(sz,M_TCPPCM, M_NOWAIT);
206e18b97bdSRandall Stewart 			if (n == NULL) {
207e18b97bdSRandall Stewart 				/* We are dead, no memory */
208e18b97bdSRandall Stewart 				rack->pcm_in_progress = 0;
209e18b97bdSRandall Stewart 				rack->r_ctl.pcm_i.cnt = 0;
210e18b97bdSRandall Stewart 				return;
211e18b97bdSRandall Stewart 			}
212e18b97bdSRandall Stewart 			sz = (sizeof(struct rack_pcm_stats) * rack->r_ctl.pcm_i.cnt_alloc);
213e18b97bdSRandall Stewart 			memcpy(n, rack->r_ctl.pcm_s, sz);
214e18b97bdSRandall Stewart 			free(rack->r_ctl.pcm_s, M_TCPPCM);
215e18b97bdSRandall Stewart 			rack->r_ctl.pcm_s = n;
216e18b97bdSRandall Stewart 			rack->r_ctl.pcm_i.cnt_alloc = new_cnt;
217e18b97bdSRandall Stewart 		}
218e18b97bdSRandall Stewart 	}
219e18b97bdSRandall Stewart 	e = &rack->r_ctl.pcm_s[rack->r_ctl.pcm_i.cnt];
220e18b97bdSRandall Stewart 	rack->r_ctl.pcm_i.cnt++;
221e18b97bdSRandall Stewart 	e->sseq = start;
222e18b97bdSRandall Stewart 	e->eseq = end;
223e18b97bdSRandall Stewart 	e->ack_time = ack_arrival;
224e18b97bdSRandall Stewart skip_ack_accounting:
225e18b97bdSRandall Stewart 	if (completed == 0)
226e18b97bdSRandall Stewart 		return;
227e18b97bdSRandall Stewart 	/*
228e18b97bdSRandall Stewart 	 * Ok we are to the point where we can assess what
229e18b97bdSRandall Stewart 	 * has happened and make a PCM judgement.
230e18b97bdSRandall Stewart 	 */
231e18b97bdSRandall Stewart 
232e18b97bdSRandall Stewart 	if (tcp_bblogging_on(rack->rc_tp)) {
233e18b97bdSRandall Stewart 		union tcp_log_stackspecific log;
234e18b97bdSRandall Stewart 		struct timeval tv;
235e18b97bdSRandall Stewart 		uint64_t prev_time = 0;
236e18b97bdSRandall Stewart 		uint64_t tot_byt = 0;
237e18b97bdSRandall Stewart 		uint32_t tot_lt_12us = 0;
238e18b97bdSRandall Stewart 		uint32_t tot_gt_2mss = 0;
239e18b97bdSRandall Stewart 
240e18b97bdSRandall Stewart 		(void)tcp_get_usecs(&tv);
241e18b97bdSRandall Stewart 		for (i=0; i<rack->r_ctl.pcm_i.cnt; i++) {
242e18b97bdSRandall Stewart 
243e18b97bdSRandall Stewart 			e = &rack->r_ctl.pcm_s[i];
244*382af4d3SPeter Lei 			memset(&log, 0, sizeof(log));
245e18b97bdSRandall Stewart 			log.u_bbr.timeStamp = tcp_tv_to_usectick(&tv);
246e18b97bdSRandall Stewart 			log.u_bbr.inflight = ctf_flight_size(rack->rc_tp, rack->r_ctl.rc_sacked);
247e18b97bdSRandall Stewart 			log.u_bbr.flex8 = 1;
248e18b97bdSRandall Stewart 			log.u_bbr.flex1 = e->sseq;
249e18b97bdSRandall Stewart 			log.u_bbr.flex2 = e->eseq;
250e18b97bdSRandall Stewart 			tot_byt += (e->eseq - e->sseq);
251e18b97bdSRandall Stewart 			if ((i > 0) &&
252e18b97bdSRandall Stewart 			    (e->ack_time > prev_time)) {
253e18b97bdSRandall Stewart 				log.u_bbr.flex3 = (uint32_t)(e->ack_time - prev_time);
254e18b97bdSRandall Stewart 			} else {
255e18b97bdSRandall Stewart 				log.u_bbr.flex3 = 0;
256e18b97bdSRandall Stewart 			}
257e18b97bdSRandall Stewart 			if (e->ack_time > rack->r_ctl.pcm_i.send_time) {
258e18b97bdSRandall Stewart 				log.u_bbr.flex4 = (uint32_t)(e->ack_time - rack->r_ctl.pcm_i.send_time);
259e18b97bdSRandall Stewart 			} else {
260e18b97bdSRandall Stewart 				log.u_bbr.flex4 = 0;
261e18b97bdSRandall Stewart 			}
262e18b97bdSRandall Stewart 			if ((e->eseq - e->sseq) > (segsiz * 2)) {
263e18b97bdSRandall Stewart 				tot_gt_2mss++;
264e18b97bdSRandall Stewart 			}
265e18b97bdSRandall Stewart 			if ((i > 0) &&
266e18b97bdSRandall Stewart 			    (log.u_bbr.flex3 < 12)) {
267e18b97bdSRandall Stewart 				tot_lt_12us++;
268e18b97bdSRandall Stewart 			}
269e18b97bdSRandall Stewart 			prev_time = e->ack_time;
270e18b97bdSRandall Stewart 			log.u_bbr.cur_del_rate = rack->r_ctl.pcm_i.send_time;
271e18b97bdSRandall Stewart 			if ((i > 0) &&
272e18b97bdSRandall Stewart 			    (log.u_bbr.flex3 > 0)) {
273e18b97bdSRandall Stewart 				/*
274e18b97bdSRandall Stewart 				 * Calculate a b/w between this chunk and the previous.
275e18b97bdSRandall Stewart 				 */
276e18b97bdSRandall Stewart 				log.u_bbr.delRate = (e->eseq - e->sseq);
277e18b97bdSRandall Stewart 				log.u_bbr.delRate *= HPTS_USEC_IN_SEC;
278e18b97bdSRandall Stewart 				log.u_bbr.delRate /= (uint64_t)log.u_bbr.flex3;
279e18b97bdSRandall Stewart 			}
280e18b97bdSRandall Stewart 			log.u_bbr.rttProp = e->ack_time;
281e18b97bdSRandall Stewart 			(void)tcp_log_event(rack->rc_tp, NULL, NULL, NULL, TCP_PCM_MEASURE, ERRNO_UNK,
282e18b97bdSRandall Stewart 					    0, &log, false, NULL, NULL, 0, &tv);
283e18b97bdSRandall Stewart 		}
284e18b97bdSRandall Stewart 		if (prev_time  > rack->r_ctl.pcm_i.send_time) {
285e18b97bdSRandall Stewart 			/*
286e18b97bdSRandall Stewart 			 * Prev time holds the last ack arrival time.
287e18b97bdSRandall Stewart 			 */
288e18b97bdSRandall Stewart 			memset(&log.u_bbr, 0, sizeof(log.u_bbr));
289e18b97bdSRandall Stewart 			log.u_bbr.timeStamp = tcp_tv_to_usectick(&tv);
290e18b97bdSRandall Stewart 			log.u_bbr.inflight = ctf_flight_size(rack->rc_tp, rack->r_ctl.rc_sacked);
291e18b97bdSRandall Stewart 			log.u_bbr.flex8 = 2;
292e18b97bdSRandall Stewart 			log.u_bbr.flex1 = rack->r_ctl.pcm_i.sseq;
293e18b97bdSRandall Stewart 			log.u_bbr.flex2 = rack->r_ctl.pcm_i.eseq;
294e18b97bdSRandall Stewart 			log.u_bbr.flex3 = tot_byt;
295e18b97bdSRandall Stewart 			log.u_bbr.flex4 = tot_lt_12us;	/* How many deltas indicate > 2Gbps */
296e18b97bdSRandall Stewart 			log.u_bbr.flex5 = tot_gt_2mss;  /* How many acks represent more than 2MSS */
297e18b97bdSRandall Stewart 			log.u_bbr.flex7 = rack->r_ctl.pcm_i.cnt;
298e18b97bdSRandall Stewart 			log.u_bbr.cwnd_gain = rack->r_ctl.pcm_i.cnt_alloc;
299e18b97bdSRandall Stewart 			log.u_bbr.cur_del_rate = rack->r_ctl.pcm_i.send_time;
300e18b97bdSRandall Stewart 			log.u_bbr.rttProp = prev_time;
301e18b97bdSRandall Stewart 			log.u_bbr.delRate = tot_byt;
302e18b97bdSRandall Stewart 			log.u_bbr.delRate *= HPTS_USEC_IN_SEC;
303e18b97bdSRandall Stewart 			log.u_bbr.delRate /= (prev_time - rack->r_ctl.pcm_i.send_time);
304e18b97bdSRandall Stewart 			(void)tcp_log_event(rack->rc_tp, NULL, NULL, NULL, TCP_PCM_MEASURE, ERRNO_UNK,
305e18b97bdSRandall Stewart 					    0, &log, false, NULL, NULL, 0, &tv);
306e18b97bdSRandall Stewart 		}
307e18b97bdSRandall Stewart 	}
308e18b97bdSRandall Stewart 	/*
309e18b97bdSRandall Stewart 	 * Here we need a lot to be added including:
310e18b97bdSRandall Stewart 	 * 1) Some form of measurement, where if we think the measurement
311e18b97bdSRandall Stewart 	 *    is valid we iterate over the PCM data and come up with a path
312e18b97bdSRandall Stewart 	 *    capacity estimate.
313e18b97bdSRandall Stewart 	 * 2) We may decide that the PCM is invalid due to ack meddlers and
314e18b97bdSRandall Stewart 	 *    thus need to increase the PCM size (which defaults to 10mss).
315e18b97bdSRandall Stewart 	 * 3) We may need to think about shrinking the PCM size if we are
316e18b97bdSRandall Stewart 	 *    seeing some sort of presistent loss from making the measurement
317e18b97bdSRandall Stewart 	 *    (i.e. it got to big and our bursts are causing loss).
318e18b97bdSRandall Stewart 	 * 4) If we make a measurement we need to place it somewhere in the
319e18b97bdSRandall Stewart 	 *    stack to be reported later somehow. Is it a WMA in the stack or
320e18b97bdSRandall Stewart 	 *    the highest or?
321e18b97bdSRandall Stewart 	 * 5) Is there a limit on how big we can go PCM size wise, the code
322e18b97bdSRandall Stewart 	 *    here will send multiple TSO bursts all at once, but how big
323e18b97bdSRandall Stewart 	 *    is too big, and does that then put some bound (I think it does)
324e18b97bdSRandall Stewart 	 *    on the largest capacity we can determine?
325e18b97bdSRandall Stewart 	 */
326e18b97bdSRandall Stewart 	/* New code here */
327e18b97bdSRandall Stewart 	/* Clear the cnt we are done */
328e18b97bdSRandall Stewart 	rack->r_ctl.pcm_i.cnt = 0;
329e18b97bdSRandall Stewart }
330e18b97bdSRandall Stewart 
331e18b97bdSRandall Stewart #endif /* #if !defined(INET) && !defined(INET6) */
332