Lines Matching +full:cancel +full:- +full:in +full:- +full:progress
1 /*-
4 * Copyright (c) 2007-2008,2010
6 * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
8 * Copyright (c) 2010-2011 Juniper Networks, Inc.
13 * James Healy and David Hayes, made possible in part by a grant from the Cisco
23 * Redistribution and use in source and binary forms, with or without
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * While looking at the routing entry, we also initialize other path-dependent
62 * parameters from pre-set or cached values in the routing entry.
68 * data in maxopd.
72 * settings are handled in tcp_mssopt().
94 /* samkumar: Copied from in.h */
118 tp->ccv->bytes_this_ack = BYTES_THIS_ACK(tp, th); in cc_ack_received()
119 if (tp->snd_cwnd <= tp->snd_wnd) in cc_ack_received()
120 tp->ccv->flags |= CCF_CWND_LIMITED; in cc_ack_received()
122 tp->ccv->flags &= ~CCF_CWND_LIMITED; in cc_ack_received()
125 if (tp->snd_cwnd > tp->snd_ssthresh) { in cc_ack_received()
126 tp->t_bytes_acked += min(tp->ccv->bytes_this_ack, in cc_ack_received()
127 V_tcp_abc_l_var * tp->t_maxseg); in cc_ack_received()
128 if (tp->t_bytes_acked >= tp->snd_cwnd) { in cc_ack_received()
129 tp->t_bytes_acked -= tp->snd_cwnd; in cc_ack_received()
130 tp->ccv->flags |= CCF_ABC_SENTAWND; in cc_ack_received()
133 tp->ccv->flags &= ~CCF_ABC_SENTAWND; in cc_ack_received()
134 tp->t_bytes_acked = 0; in cc_ack_received()
138 if (CC_ALGO(tp)->ack_received != NULL) { in cc_ack_received()
140 tp->ccv->curack = th->th_ack; in cc_ack_received()
141 CC_ALGO(tp)->ack_received(tp->ccv, type); in cc_ack_received()
155 /* samkumar: Used to take &inp->inp_inc as an argument. */ in cc_conn_init()
158 if (tp->t_srtt == 0 && (rtt = metrics.rmx_rtt)) { in cc_conn_init()
159 tp->t_srtt = rtt; in cc_conn_init()
160 tp->t_rttbest = tp->t_srtt + TCP_RTT_SCALE; in cc_conn_init()
162 tp->t_rttvar = metrics.rmx_rttvar; in cc_conn_init()
164 /* default variation is +- 1 rtt */ in cc_conn_init()
165 tp->t_rttvar = in cc_conn_init()
166 tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE; in cc_conn_init()
168 TCPT_RANGESET(tp->t_rxtcur, in cc_conn_init()
169 ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1, in cc_conn_init()
170 tp->t_rttmin, TCPTV_REXMTMAX); in cc_conn_init()
179 tp->snd_ssthresh = max(2 * tp->t_maxseg, metrics.rmx_ssthresh); in cc_conn_init()
183 * Set the initial slow-start flight size. in cc_conn_init()
194 if (tp->snd_cwnd == 1) in cc_conn_init()
195 tp->snd_cwnd = tp->t_maxseg; /* SYN(-ACK) lost */ in cc_conn_init()
197 tp->snd_cwnd = min(V_tcp_initcwnd_segments * tp->t_maxseg, in cc_conn_init()
198 max(2 * tp->t_maxseg, V_tcp_initcwnd_segments * 1460)); in cc_conn_init()
200 tp->snd_cwnd = min(4 * tp->t_maxseg, in cc_conn_init()
201 max(2 * tp->t_maxseg, 4380)); in cc_conn_init()
204 if (tp->t_maxseg > 2190) in cc_conn_init()
205 tp->snd_cwnd = 2 * tp->t_maxseg; in cc_conn_init()
206 else if (tp->t_maxseg > 1095) in cc_conn_init()
207 tp->snd_cwnd = 3 * tp->t_maxseg; in cc_conn_init()
209 tp->snd_cwnd = 4 * tp->t_maxseg; in cc_conn_init()
212 if (CC_ALGO(tp)->conn_init != NULL) in cc_conn_init()
213 CC_ALGO(tp)->conn_init(tp->ccv); in cc_conn_init()
217 …CC_INIT %u %d %d", (unsigned int) tcplp_sys_get_millis(), (int) tp->snd_cwnd, (int) tp->snd_ssthre… in cc_conn_init()
228 if (!IN_FASTRECOVERY(tp->t_flags)) { in cc_cong_signal()
229 tp->snd_recover = tp->snd_max; in cc_cong_signal()
230 if (tp->t_flags & TF_ECN_PERMIT) in cc_cong_signal()
231 tp->t_flags |= TF_ECN_SND_CWR; in cc_cong_signal()
235 if (!IN_CONGRECOVERY(tp->t_flags)) { in cc_cong_signal()
236 tp->snd_recover = tp->snd_max; in cc_cong_signal()
237 if (tp->t_flags & TF_ECN_PERMIT) in cc_cong_signal()
238 tp->t_flags |= TF_ECN_SND_CWR; in cc_cong_signal()
242 tp->t_dupacks = 0; in cc_cong_signal()
243 tp->t_bytes_acked = 0; in cc_cong_signal()
244 EXIT_RECOVERY(tp->t_flags); in cc_cong_signal()
247 * code scanning alert relating to integer overflow in multiplication. in cc_cong_signal()
249 tp->snd_ssthresh = max(2, min(tp->snd_wnd, tp->snd_cwnd) / 2 / in cc_cong_signal()
250 tp->t_maxseg) * ((uint64_t) tp->t_maxseg); in cc_cong_signal()
251 tp->snd_cwnd = tp->t_maxseg; in cc_cong_signal()
263 … CC_RTO %u %d %d", (unsigned int) tcplp_sys_get_millis(), (int) tp->snd_cwnd, (int) tp->snd_ssthre… in cc_cong_signal()
268 tp->snd_cwnd = tp->snd_cwnd_prev; in cc_cong_signal()
269 tp->snd_ssthresh = tp->snd_ssthresh_prev; in cc_cong_signal()
270 tp->snd_recover = tp->snd_recover_prev; in cc_cong_signal()
271 if (tp->t_flags & TF_WASFRECOVERY) in cc_cong_signal()
272 ENTER_FASTRECOVERY(tp->t_flags); in cc_cong_signal()
273 if (tp->t_flags & TF_WASCRECOVERY) in cc_cong_signal()
274 ENTER_CONGRECOVERY(tp->t_flags); in cc_cong_signal()
275 tp->snd_nxt = tp->snd_max; in cc_cong_signal()
276 tp->t_flags &= ~TF_PREVVALID; in cc_cong_signal()
277 tp->t_badrxtwin = 0; in cc_cong_signal()
279 …RTO_ERR %u %d %d", (unsigned int) tcplp_sys_get_millis(), (int) tp->snd_cwnd, (int) tp->snd_ssthre… in cc_cong_signal()
284 if (CC_ALGO(tp)->cong_signal != NULL) { in cc_cong_signal()
286 tp->ccv->curack = th->th_ack; in cc_cong_signal()
287 CC_ALGO(tp)->cong_signal(tp->ccv, type); in cc_cong_signal()
296 /* XXXLAS: KASSERT that we're in recovery? */ in cc_post_recovery()
297 if (CC_ALGO(tp)->post_recovery != NULL) { in cc_post_recovery()
298 tp->ccv->curack = th->th_ack; in cc_post_recovery()
299 CC_ALGO(tp)->post_recovery(tp->ccv); in cc_post_recovery()
302 tp->t_bytes_acked = 0; in cc_post_recovery()
309 * - There is no delayed ack timer in progress.
310 * - Our last ack wasn't a 0-sized window. We never want to delay
311 * the ack that opens up a 0-sized window.
312 * - LRO wasn't used for this segment. We make sure by checking that the
314 * - Delayed acks are enabled or this is a half-synchronized T/TCP
319 (tp->t_flags & TF_RXWIN0SENT) == 0) && \
320 (tlen <= tp->t_maxopd) && \
321 (V_tcp_delack_enabled || (tp->t_flags & TF_NEEDSYN)))
328 if (CC_ALGO(tp)->ecnpkt_handler != NULL) { in cc_ecnpkt_handler()
331 tp->ccv->flags |= CCF_IPHDR_CE; in cc_ecnpkt_handler()
334 tp->ccv->flags &= ~CCF_IPHDR_CE; in cc_ecnpkt_handler()
337 tp->ccv->flags &= ~CCF_IPHDR_CE; in cc_ecnpkt_handler()
341 if (th->th_flags & TH_CWR) in cc_ecnpkt_handler()
342 tp->ccv->flags |= CCF_TCPHDR_CWR; in cc_ecnpkt_handler()
344 tp->ccv->flags &= ~CCF_TCPHDR_CWR; in cc_ecnpkt_handler()
346 if (tp->t_flags & TF_DELACK) in cc_ecnpkt_handler()
347 tp->ccv->flags |= CCF_DELACK; in cc_ecnpkt_handler()
349 tp->ccv->flags &= ~CCF_DELACK; in cc_ecnpkt_handler()
351 CC_ALGO(tp)->ecnpkt_handler(tp->ccv); in cc_ecnpkt_handler()
353 if (tp->ccv->flags & CCF_ACKNOW) in cc_ecnpkt_handler()
359 * External function: look up an entry in the hostcache and fill out the
360 * supplied TCP metrics structure. Fills in NULL when no entry was found or
365 * in TCPlp, so I changed this to always act as if there is a miss. I removed
375 * External function: look up an entry in the hostcache and return the
381 * in TCPlp, so I changed this to always act as if there is a miss.
406 * packets. In the FreeBSD version of this function, it would just in tcp_dropwithreset()
407 * call m_freem(m), if m->m_flags has M_BCAST or M_MCAST set, and not in tcp_dropwithreset()
411 if (th->th_flags & TH_RST) in tcp_dropwithreset()
415 if (th->th_flags & TH_ACK) { in tcp_dropwithreset()
416 tcp_respond(tp, instance, ip6, th, (tcp_seq) 0, th->th_ack, TH_RST); in tcp_dropwithreset()
418 if (th->th_flags & TH_SYN) in tcp_dropwithreset()
420 tcp_respond(tp, instance, ip6, th, th->th_seq + tlen, (tcp_seq) 0, TH_RST | TH_ACK); in tcp_dropwithreset()
428 * ip6_protox[] call format in ip6_input
449 * them must be NULL, and the other must be set. If tp is non-NULL, then in tcp_input()
451 * (connection endpoint). If tpl is non-NULL, then this function assumes in tcp_input()
466 struct tcpopt to; /* options in this segment */ in tcp_input()
475 * contiguous in memory, setting the ip6 and th pointers, validating the in tcp_input()
476 * checksum, and dropping packets with unspecified source address. In in tcp_input()
480 tlen = ntohs(ip6->ip6_plen); // assume *off == sizeof(*ip6) in tcp_input()
487 iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; in tcp_input()
493 off = (th->th_off_x2 >> TH_OFF_SHIFT) << 2; in tcp_input()
497 tlen -= off; /* tlen is used instead of ti->ti_len */ in tcp_input()
503 * checks for IPv6 extension headers. In TCPlp, we assume that these in tcp_input()
504 * are handled elsewhere in the networking stack, before the incoming in tcp_input()
508 optlen = off - sizeof (struct tcphdr); in tcp_input()
512 thflags = th->th_flags; in tcp_input()
517 * call from there and handle it in TCPlp, before calling this. The reason in tcp_input()
519 * logic (e.g., if the packet matches a TIME-WAIT socket this function in tcp_input()
529 * samkumar: My TCP header is in a different buffer from the IP header. in tcp_input()
543 * connection in TIMEWAIT and SYNs not targeting a listening socket. in tcp_input()
552 * samkumar: The FreeBSD code at logic here to check m->m_flags for the in tcp_input()
554 * store it in fwd_tag if so. In TCPlp, we assume that the IPv6 layer of in tcp_input()
555 * the host network stack handles this kind of IPv6-related functionality, in tcp_input()
563 * this code because, in TCPlp, this is done before calling this function. in tcp_input()
567 * A previous connection in TIMEWAIT state is supposed to catch stray in tcp_input()
575 * drop all locks, acquire a global write lock, and then re-acquire in tcp_input()
577 * has tried to free the inpcb, in which case we need to loop back in tcp_input()
583 * samkumar: The original code checked inp->inp_flags & INP_TIMEWAIT. I in tcp_input()
584 * changed it to instead check tp->t_state, since we don't use inpcbs in in tcp_input()
587 if (tp && tp->t_state == TCP6S_TIME_WAIT) { in tcp_input()
593 * In fact, this call was probably unnecessary even in the original in tcp_input()
601 * taken. Matching with a TCB is done outside of this function in in tcp_input()
603 * to try re-matching this packet to a socket. in tcp_input()
611 * down or it is in the CLOSED state. Either way we drop the in tcp_input()
616 * and drops with reset if the connection is in the closed state or if in tcp_input()
617 * the tp is NULL. In TCPlp, the equivalent logic is done before entering in tcp_input()
624 * inpcbinfo write lock but don't hold it. In this case, attempt to in tcp_input()
627 * now be in TIMEWAIT. in tcp_input()
635 * When the socket is accepting connections (the INPCB is in LISTEN in tcp_input()
638 * so->so_options to check if the socket is listening, we rely on the in tcp_input()
643 if (/*so->so_options & SO_ACCEPTCONN*/tp == NULL) { in tcp_input()
649 …KASSERT(tpl != NULL && tpl->t_state == TCP6S_LISTEN, ("listen socket must be in listening state!")… in tcp_input()
658 * that is processed in the syncache as well. In TCPlp we do not use a in tcp_input()
660 * establishment/processing logic happens in tcp_do_segment anyway, in tcp_input()
662 * to rewrite this code with special-case logic for that. in tcp_input()
670 * samkumar: Here, and in several other instances, the FreeBSD in tcp_input()
671 * code would call tcp_log_addrs. Improving logging in these in tcp_input()
672 * edge cases in TCPlp is left for the future --- for now, I just in tcp_input()
725 * V_ip6_use_deprecated is true. Rejecting the packet, in this case, in tcp_input()
735 * global or subnet broad- or multicast address. in tcp_input()
737 * link-layer packets with a broadcast IP address. Use in tcp_input()
744 * done by checking m->m_flags for (M_BAST|M_MCAST). The original in tcp_input()
745 * FreeBSD code for this has been removed (since checking m->m_flags in tcp_input()
752 if (th->th_dport == th->th_sport && in tcp_input()
753 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &ip6->ip6_src)) { in tcp_input()
760 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || in tcp_input()
761 IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) { in tcp_input()
779 * In that case, there is a "goto" statement to the removed logic in tcp_input()
786 * samkumar: TCP Fast Open logic taken from syncache_add in in tcp_input()
789 if (V_tcp_fastopen_server_enable && /*IS_FASTOPEN(tp->t_flags) && in tcp_input()
790 (tp->t_tfo_pending != NULL) && */ in tcp_input()
813 …tp = tcplp_sys_accept_ready(tpl, &ip6->ip6_src, th->th_sport); // Try to allocate an active socket… in tcp_input()
818 if (tp == (struct tcpcb *) -1) { in tcp_input()
823 sig->accepted_connection = tp; in tcp_input()
826 tp->iss = tcp_new_isn(tp); in tcp_input()
827 tp->irs = th->th_seq; in tcp_input()
830 tp->snd_wl1 = th->th_seq; in tcp_input()
833 * tcp_output to send the appropriate SYN-ACK. For in tcp_input()
837 * SYN-ACK has already been ACKed, which is not how in tcp_input()
840 tp->snd_max = tp->iss/* + 1*/; in tcp_input()
841 tp->snd_nxt = tp->iss/* + 1*/; in tcp_input()
842 tp->rcv_up = th->th_seq + 1; in tcp_input()
843 tp->rcv_wnd = imin(imax(cbuf_free_space(&tp->recvbuf), 0), TCP_MAXWIN); in tcp_input()
844 tp->rcv_adv += tp->rcv_wnd; in tcp_input()
845 tp->last_ack_sent = tp->rcv_nxt; in tcp_input()
846 memcpy(&tp->laddr, &ip6->ip6_dst, sizeof(tp->laddr)); in tcp_input()
847 memcpy(&tp->faddr, &ip6->ip6_src, sizeof(tp->faddr)); in tcp_input()
848 tp->fport = th->th_sport; in tcp_input()
849 tp->lport = tpl->lport; in tcp_input()
853 * check for flags in sc->sc_flags. They have been written to directly in tcp_input()
854 * check for the conditions on the TCP options structure or in the TCP in tcp_input()
855 * header that would ordinarily be used to set flags in sc->sc_flags in tcp_input()
858 * In effect, we combine the logic in syncache_add to set elements of in tcp_input()
859 * sc with the logic in syncache_socket to transfer state from sc in tcp_input()
860 * to the socket, but short-circuit the process to avoid ever storing in tcp_input()
861 * data in sc. Since this isn't just adding or deleting code, I decided in tcp_input()
865 tp->t_flags = tp->t_flags & (TF_NOPUSH | TF_NODELAY | TF_NOOPT); in tcp_input()
866 // tp->t_flags = sototcpcb(lso)->t_flags & (TF_NOPUSH|TF_NODELAY); in tcp_input()
867 // if (sc->sc_flags & SCF_NOOPT) in tcp_input()
868 // tp->t_flags |= TF_NOOPT; in tcp_input()
870 if (!(tp->t_flags & TF_NOOPT) && V_tcp_do_rfc1323) { in tcp_input()
871 if (/*sc->sc_flags & SCF_WINSCALE*/to.to_flags & TOF_SCALE) { in tcp_input()
892 * RFC1323: The Window field in a SYN (i.e., a <SYN> in tcp_input()
898 * listed below, commented out. In practice, we just use in tcp_input()
899 * wscale = 0 because in TCPlp we assume that the buffers in tcp_input()
908 tp->t_flags |= TF_REQ_SCALE|TF_RCVD_SCALE; in tcp_input()
909 tp->snd_scale = /*sc->sc_requested_s_scale*/to.to_wscale; in tcp_input()
910 tp->request_r_scale = wscale; in tcp_input()
912 if (/*sc->sc_flags & SCF_TIMESTAMP*/to.to_flags & TOF_TS) { in tcp_input()
913 tp->t_flags |= TF_REQ_TSTMP|TF_RCVD_TSTMP; in tcp_input()
914 tp->ts_recent = /*sc->sc_tsreflect*/to.to_tsval; in tcp_input()
915 tp->ts_recent_age = tcp_ts_getticks(); in tcp_input()
916 tp->ts_offset = /*sc->sc_tsoff*/0; // No syncookies, so this should always be 0 in tcp_input()
921 * TF_SIGNATURE flag on tp->t_flags if SCF_SIGNATURE is set on in tcp_input()
922 * sc->sc_flags. I've left it in below, commented out. in tcp_input()
926 if (sc->sc_flags & SCF_SIGNATURE) in tcp_input()
927 tp->t_flags |= TF_SIGNATURE; in tcp_input()
930 if (/*sc->sc_flags & SCF_SACK*/ to.to_flags & TOF_SACKPERM) in tcp_input()
931 tp->t_flags |= TF_SACK_PERMIT; in tcp_input()
933 if (/*sc->sc_flags & SCF_ECN*/(th->th_flags & (TH_ECE|TH_CWR)) && V_tcp_do_ecn) in tcp_input()
934 tp->t_flags |= TF_ECN_PERMIT; in tcp_input()
940 tcp_mss(tp, /*sc->sc_peer_mss*/(to.to_flags & TOF_MSS) ? to.to_mss : 0); in tcp_input()
948 tp->t_flags |= TF_FASTOPEN; in tcp_input()
949 tp->t_tfo_cookie.server = tfo_response_cookie; in tcp_input()
950 tp->snd_max = tp->iss; in tcp_input()
951 tp->snd_nxt = tp->iss; in tcp_input()
952 // tp->tfo_pending = pending_counter; in tcp_input()
956 tp->accepted_from = tpl; in tcp_input()
959 tp->t_flags |= TF_ACKNOW; // samkumar: my addition in tcp_input()
962 tcp_output(tp); // to send the SYN-ACK in tcp_input()
964 tp->accepted_from = tpl; in tcp_input()
966 } else if (tp->t_state == TCPS_LISTEN) { in tcp_input()
970 * from the accept queue in a unlock/lock cycle of the in tcp_input()
981 * support TCP signatures in TCPlp. in tcp_input()
985 * Segment belongs to a connection in SYN_SENT, ESTABLISHED or later in tcp_input()
997 * management in TCPlp. in tcp_input()
1005 tcp_dropwithreset(ip6, th, tp, tp->instance, tlen, rstreason); in tcp_input()
1007 tcp_dropwithreset(ip6, th, NULL, tpl->instance, tlen, rstreason); in tcp_input()
1038 otInstance* instance = tp->instance; in tcp_do_segment()
1039 thflags = th->th_flags; in tcp_do_segment()
1040 tp->sackhint.last_sack_ack = 0; in tcp_do_segment()
1043 * If this is either a state-changing packet or current state isn't in tcp_do_segment()
1045 * allow the tcbinfo to be in either alocked or unlocked, as the in tcp_do_segment()
1050 KASSERT(tp->t_state > TCPS_LISTEN, ("%s: TCPS_LISTEN", in tcp_do_segment()
1052 KASSERT(tp->t_state != TCPS_TIME_WAIT, ("%s: TCPS_TIME_WAIT", in tcp_do_segment()
1057 * Reset idle time and keep-alive timer. in tcp_do_segment()
1061 tp->t_rcvtime = ticks; in tcp_do_segment()
1062 if (TCPS_HAVEESTABLISHED(tp->t_state)) in tcp_do_segment()
1066 * Scale up the window into a 32-bit value. in tcp_do_segment()
1069 tiwin = th->th_win << tp->snd_scale; in tcp_do_segment()
1079 if (tp->t_flags & TF_ECN_PERMIT) { in tcp_do_segment()
1081 tp->t_flags &= ~TF_ECN_SND_ECE; in tcp_do_segment()
1084 tp->t_flags |= TF_ECN_SND_ECE; in tcp_do_segment()
1108 ((th->th_off_x2 >> TH_OFF_SHIFT) << 2) - sizeof(struct tcphdr), in tcp_do_segment()
1119 to.to_tsecr -= tp->ts_offset; in tcp_do_segment()
1127 if ((tp->t_flags & TF_RCVD_TSTMP) && !(to.to_flags & TOF_TS)) { in tcp_do_segment()
1132 if (!(tp->t_flags & TF_RCVD_TSTMP) && (to.to_flags & TOF_TS)) { in tcp_do_segment()
1140 * for incoming connections is handled in tcp_syncache. in tcp_do_segment()
1141 * According to RFC1323 the window field in a SYN (i.e., a <SYN> in tcp_do_segment()
1145 if (tp->t_state == TCPS_SYN_SENT && (thflags & TH_SYN)) { in tcp_do_segment()
1147 (tp->t_flags & TF_REQ_SCALE)) { in tcp_do_segment()
1148 tp->t_flags |= TF_RCVD_SCALE; in tcp_do_segment()
1149 tp->snd_scale = to.to_wscale; in tcp_do_segment()
1155 tp->snd_wnd = th->th_win; in tcp_do_segment()
1157 tp->t_flags |= TF_RCVD_TSTMP; in tcp_do_segment()
1158 tp->ts_recent = to.to_tsval; in tcp_do_segment()
1159 tp->ts_recent_age = tcp_ts_getticks(); in tcp_do_segment()
1163 if ((tp->t_flags & TF_SACK_PERMIT) && in tcp_do_segment()
1165 tp->t_flags &= ~TF_SACK_PERMIT; in tcp_do_segment()
1169 if (IS_FASTOPEN(tp->t_flags)) { in tcp_do_segment()
1179 * on whether the INP_IPV6 flag is present in in tcp_do_segment()
1180 * tp->t_inpcb->inp_vflag. In TCPlp, we always in tcp_do_segment()
1192 * of a uni-directional data xfer. If the packet has in tcp_do_segment()
1193 * no control flags, is in-sequence, the window didn't in tcp_do_segment()
1199 * is non-zero and the ack didn't move, we're the in tcp_do_segment()
1200 * receiver side. If we're getting packets in-order in tcp_do_segment()
1203 * Make sure that the hidden state-flags are also off. in tcp_do_segment()
1208 * samkumar: Replaced LIST_EMPTY(&tp->tsegq with the call to bmp_isempty). in tcp_do_segment()
1210 if (tp->t_state == TCPS_ESTABLISHED && in tcp_do_segment()
1211 th->th_seq == tp->rcv_nxt && in tcp_do_segment()
1213 tp->snd_nxt == tp->snd_max && in tcp_do_segment()
1214 tiwin && tiwin == tp->snd_wnd && in tcp_do_segment()
1215 ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) && in tcp_do_segment()
1216 bmp_isempty(tp->reassbmp, REASSBMP_SIZE(tp)) && in tcp_do_segment()
1218 TSTMP_GEQ(to.to_tsval, tp->ts_recent)) ) { in tcp_do_segment()
1227 SEQ_LEQ(th->th_seq, tp->last_ack_sent)) { in tcp_do_segment()
1228 tp->ts_recent_age = tcp_ts_getticks(); in tcp_do_segment()
1229 tp->ts_recent = to.to_tsval; in tcp_do_segment()
1233 if (SEQ_GT(th->th_ack, tp->snd_una) && in tcp_do_segment()
1234 SEQ_LEQ(th->th_ack, tp->snd_max) && in tcp_do_segment()
1235 !IN_RECOVERY(tp->t_flags) && in tcp_do_segment()
1237 TAILQ_EMPTY(&tp->snd_holes)) { in tcp_do_segment()
1245 if (tp->t_rxtshift == 1 && in tcp_do_segment()
1246 tp->t_flags & TF_PREVVALID && in tcp_do_segment()
1247 (int)(ticks - tp->t_badrxtwin) < 0) { in tcp_do_segment()
1264 t = tcp_ts_getticks() - to.to_tsecr; in tcp_do_segment()
1265 if (!tp->t_rttlow || tp->t_rttlow > t) in tcp_do_segment()
1266 tp->t_rttlow = t; in tcp_do_segment()
1269 } else if (tp->t_rtttime && in tcp_do_segment()
1270 SEQ_GT(th->th_ack, tp->t_rtseq)) { in tcp_do_segment()
1271 if (!tp->t_rttlow || in tcp_do_segment()
1272 tp->t_rttlow > ticks - tp->t_rtttime) in tcp_do_segment()
1273 tp->t_rttlow = ticks - tp->t_rtttime; in tcp_do_segment()
1275 ticks - tp->t_rtttime); in tcp_do_segment()
1281 * samkumar: Replaced sbdrop(&so->so_snd, acked) with this call in tcp_do_segment()
1285 uint32_t poppedbytes = lbuf_pop(&tp->sendbuf, acked, &sig->links_popped); in tcp_do_segment()
1286 KASSERT(poppedbytes == acked, ("More bytes were acked than are in the send buffer")); in tcp_do_segment()
1287 sig->bytes_acked += poppedbytes; in tcp_do_segment()
1289 if (SEQ_GT(tp->snd_una, tp->snd_recover) && in tcp_do_segment()
1290 SEQ_LEQ(th->th_ack, tp->snd_recover)) in tcp_do_segment()
1291 tp->snd_recover = th->th_ack - 1; in tcp_do_segment()
1301 tp->snd_una = th->th_ack; in tcp_do_segment()
1306 tp->snd_wl2 = th->th_ack; in tcp_do_segment()
1307 tp->t_dupacks = 0; in tcp_do_segment()
1312 * using current (possibly backed-off) value. in tcp_do_segment()
1319 if (tp->snd_una == tp->snd_max) in tcp_do_segment()
1323 tp->t_rxtcur); in tcp_do_segment()
1334 * samkumar: Replaced sbavail(&so->so_snd) with this call to in tcp_do_segment()
1337 if (lbuf_used_space(&tp->sendbuf)) in tcp_do_segment()
1341 } else if (th->th_ack == tp->snd_una && in tcp_do_segment()
1343 * samkumar: Replaced sbspace(&so->so_rcv) with this call to in tcp_do_segment()
1346 tlen <= cbuf_free_space(&tp->recvbuf)) { in tcp_do_segment()
1349 * This is a pure, in-sequence data packet with in tcp_do_segment()
1354 if ((tp->t_flags & TF_SACK_PERMIT) && tp->rcv_numsacks) in tcp_do_segment()
1357 tp->rcv_nxt += tlen; in tcp_do_segment()
1362 tp->snd_wl1 = th->th_seq; in tcp_do_segment()
1367 tp->rcv_up = tp->rcv_nxt; in tcp_do_segment()
1374 * bandwidth and high delay (eg. trans-continental/oceanic links). in tcp_do_segment()
1378 * more aggressive in scaling the receive socket buffer. For in tcp_do_segment()
1407 * receive buffer (tp->rfbuf_ts, rp->rfbuf_cnt, and the local in tcp_do_segment()
1408 * newsize variable). In TCPlp, we don't support this, as the user in tcp_do_segment()
1419 * (with m_freem(m)) if SBS_CANTRCVMORE is set in in tcp_do_segment()
1420 * so->so_rcv.sb_state. Otherwise, it would cut drop_hdrlen bytes in tcp_do_segment()
1423 * sbappendstream_locked(&so->so_rcv, m, 0). I've rewritten this in tcp_do_segment()
1424 * to work the TCPlp way. The check to so->so_rcv.sb_state is in tcp_do_segment()
1427 * having dynamically-allocated memory for the receive buffer). in tcp_do_segment()
1431 …cbuf_write(&tp->recvbuf, msg, otMessageGetOffset(msg) + drop_hdrlen, tlen, cbuf_copy_from_message); in tcp_do_segment()
1433 sig->recvbuf_added = true; in tcp_do_segment()
1439 * receiving a FIN. I'm going to drop the connection in this in tcp_do_segment()
1456 tp->t_flags |= TF_DELACK; in tcp_do_segment()
1458 tp->t_flags |= TF_ACKNOW; in tcp_do_segment()
1466 * Calculate amount of space in receive window, in tcp_do_segment()
1468 * Receive window is amount of space in rcv queue, in tcp_do_segment()
1471 /* samkumar: Replaced sbspace(&so->so_rcv) with call to cbuf_free_space. */ in tcp_do_segment()
1472 win = cbuf_free_space(&tp->recvbuf); in tcp_do_segment()
1475 tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt)); in tcp_do_segment()
1477 /* Reset receive buffer auto scaling when not in bulk receive mode. */ in tcp_do_segment()
1480 switch (tp->t_state) { in tcp_do_segment()
1491 * custom logic for it. It is handled in the "else if" clause below. in tcp_do_segment()
1495 (SEQ_LEQ(th->th_ack, tp->snd_una) || in tcp_do_segment()
1496 SEQ_GT(th->th_ack, tp->snd_max))) { in tcp_do_segment()
1499 …} else if (!IS_FASTOPEN(tp->t_flags) && (thflags & TH_SYN) && !(thflags & TH_ACK) && (th->th_seq =… in tcp_do_segment()
1500 tp->t_flags |= TF_ACKNOW; in tcp_do_segment()
1505 if (IS_FASTOPEN(tp->t_flags)) { in tcp_do_segment()
1507 * When a TFO connection is in SYN_RECEIVED, the in tcp_do_segment()
1517 /* non-initial SYN is ignored */ in tcp_do_segment()
1533 * initialize tp->rcv_nxt and tp->irs in tcp_do_segment()
1534 * if seg contains ack then advance tp->snd_una in tcp_do_segment()
1543 (SEQ_LEQ(th->th_ack, tp->iss) || in tcp_do_segment()
1544 SEQ_GT(th->th_ack, tp->snd_max))) { in tcp_do_segment()
1556 tp->irs = th->th_seq; in tcp_do_segment()
1567 if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == in tcp_do_segment()
1569 tp->rcv_scale = tp->request_r_scale; in tcp_do_segment()
1571 tp->rcv_adv += imin(tp->rcv_wnd, in tcp_do_segment()
1572 TCP_MAXWIN << tp->rcv_scale); in tcp_do_segment()
1573 tp->snd_una++; /* SYN is acked */ in tcp_do_segment()
1575 * If not all the data that was sent in the TFO SYN in tcp_do_segment()
1578 if (IS_FASTOPEN(tp->t_flags) && in tcp_do_segment()
1579 (tp->snd_una != tp->snd_max)) { in tcp_do_segment()
1580 tp->snd_nxt = th->th_ack; in tcp_do_segment()
1591 tp->t_flags |= TF_ACKNOW; in tcp_do_segment()
1594 tp->t_flags |= TF_ECN_PERMIT; in tcp_do_segment()
1598 * Received <SYN,ACK> in SYN_SENT[*] state. in tcp_do_segment()
1600 * SYN_SENT --> ESTABLISHED in tcp_do_segment()
1601 * SYN_SENT* --> FIN_WAIT_1 in tcp_do_segment()
1603 tp->t_starttime = ticks; in tcp_do_segment()
1604 if (tp->t_flags & TF_NEEDFIN) { in tcp_do_segment()
1606 tp->t_flags &= ~TF_NEEDFIN; in tcp_do_segment()
1611 sig->conn_established = true; in tcp_do_segment()
1618 * Received initial SYN in SYN-SENT[*] state => in tcp_do_segment()
1620 * If it succeeds, connection is * half-synchronized. in tcp_do_segment()
1621 * Otherwise, do 3-way handshake: in tcp_do_segment()
1622 * SYN-SENT -> SYN-RECEIVED in tcp_do_segment()
1623 * SYN-SENT* -> SYN-RECEIVED* in tcp_do_segment()
1625 tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN); in tcp_do_segment()
1629 * samkumar: We would have incremented snd_next in tcp_output when in tcp_do_segment()
1633 tp->snd_nxt--; in tcp_do_segment()
1637 * Advance th->th_seq to correspond to first data byte. in tcp_do_segment()
1641 th->th_seq++; in tcp_do_segment()
1642 if (tlen > tp->rcv_wnd) { in tcp_do_segment()
1643 todrop = tlen - tp->rcv_wnd; in tcp_do_segment()
1645 * samkumar: I removed a call to m_adj(m, -todrop), which intends in tcp_do_segment()
1646 * to trim the data so it fits in the window. We can just read less in tcp_do_segment()
1647 * when copying into the receive buffer in TCPlp, so we don't need in tcp_do_segment()
1651 tlen = tp->rcv_wnd; in tcp_do_segment()
1654 tp->snd_wl1 = th->th_seq - 1; in tcp_do_segment()
1655 tp->rcv_up = th->th_seq; in tcp_do_segment()
1660 * processing in the middle of step 5, ack processing. in tcp_do_segment()
1684 * below which allowed reset segments in half the sequence space in tcp_do_segment()
1698 * - RST drops connection only if SEG.SEQ == RCV.NXT. in tcp_do_segment()
1699 * - If RST is in window, we send challenge ACK. in tcp_do_segment()
1706 if ((SEQ_GEQ(th->th_seq, tp->last_ack_sent) && in tcp_do_segment()
1707 SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) || in tcp_do_segment()
1708 (tp->rcv_wnd == 0 && tp->last_ack_sent == th->th_seq)) { in tcp_do_segment()
1713 * reason to support an insecure option in TCPlp (my guess is that in tcp_do_segment()
1716 if (tp->last_ack_sent == th->th_seq) { in tcp_do_segment()
1718 * samkumar: Normally, the error number would be stored in in tcp_do_segment()
1719 * so->so_error. Instead, we put it in this "droperror" local in tcp_do_segment()
1724 switch (tp->t_state) { in tcp_do_segment()
1742 tcp_respond(tp, tp->instance, ip6, th, tp->rcv_nxt, tp->snd_nxt, TH_ACK); in tcp_do_segment()
1743 tp->last_ack_sent = tp->rcv_nxt; in tcp_do_segment()
1751 * Send challenge ACK for any SYN in synchronized state. in tcp_do_segment()
1754 * samkumar: I added the check for the SYN-RECEIVED state in this if in tcp_do_segment()
1757 if ((thflags & TH_SYN) && tp->t_state != TCPS_SYN_SENT && tp->t_state != TCP6S_SYN_RECEIVED) { in tcp_do_segment()
1762 * in the receive window. In TCPlp we *only* support Challenge ACKs in tcp_do_segment()
1765 * for legacy code, which we don't really care about in TCPlp). in tcp_do_segment()
1769 tcp_respond(tp, tp->instance, ip6, th, tp->rcv_nxt, tp->snd_nxt, TH_ACK); in tcp_do_segment()
1770 tp->last_ack_sent = tp->rcv_nxt; in tcp_do_segment()
1778 if ((to.to_flags & TOF_TS) != 0 && tp->ts_recent && in tcp_do_segment()
1779 TSTMP_LT(to.to_tsval, tp->ts_recent)) { in tcp_do_segment()
1782 if (tcp_ts_getticks() - tp->ts_recent_age > TCP_PAWS_IDLE) { in tcp_do_segment()
1788 * requirement that zero be placed in the timestamp in tcp_do_segment()
1791 * because we don't want out-of-order segments to be in tcp_do_segment()
1794 tp->ts_recent = 0; in tcp_do_segment()
1803 * In the SYN-RECEIVED state, validate that the packet belongs to in tcp_do_segment()
1809 if (tp->t_state == TCPS_SYN_RECEIVED && SEQ_LT(th->th_seq, tp->irs)) { in tcp_do_segment()
1814 todrop = tp->rcv_nxt - th->th_seq; in tcp_do_segment()
1818 th->th_seq++; in tcp_do_segment()
1819 if (th->th_urp > 1) in tcp_do_segment()
1820 th->th_urp--; in tcp_do_segment()
1823 todrop--; in tcp_do_segment()
1841 tp->t_flags |= TF_ACKNOW; in tcp_do_segment()
1846 th->th_seq += todrop; in tcp_do_segment()
1847 tlen -= todrop; in tcp_do_segment()
1848 if (th->th_urp > todrop) in tcp_do_segment()
1849 th->th_urp -= todrop; in tcp_do_segment()
1852 th->th_urp = 0; in tcp_do_segment()
1863 * do not implement the functionality in the above comment (the code for in tcp_do_segment()
1870 todrop = (th->th_seq + tlen) - (tp->rcv_nxt + tp->rcv_wnd); in tcp_do_segment()
1880 if (tp->rcv_wnd == 0 && th->th_seq == tp->rcv_nxt) { in tcp_do_segment()
1881 tp->t_flags |= TF_ACKNOW; in tcp_do_segment()
1886 * samkumar: I removed a call to m_adj(m, -todrop), which intends in tcp_do_segment()
1887 * to trim the data so it fits in the window. We can just read less in tcp_do_segment()
1888 * when copying into the receive buffer in TCPlp, so we don't need in tcp_do_segment()
1890 * do this later. In FreeBSD, this isn't possible because the mbuf in tcp_do_segment()
1892 * trimmed in order for this to work out. in tcp_do_segment()
1894 tlen -= todrop; in tcp_do_segment()
1912 * limitations as described in Stevens TCP/IP Illustrated in tcp_do_segment()
1913 * Vol. 2 p.869. In such cases, we can still calculate the in tcp_do_segment()
1918 SEQ_LEQ(th->th_seq, tp->last_ack_sent) && in tcp_do_segment()
1919 SEQ_LEQ(tp->last_ack_sent, th->th_seq + tlen + in tcp_do_segment()
1921 tp->ts_recent_age = tcp_ts_getticks(); in tcp_do_segment()
1922 tp->ts_recent = to.to_tsval; in tcp_do_segment()
1926 * If the ACK bit is off: if in SYN-RECEIVED state or SENDSYN in tcp_do_segment()
1927 * flag is on (half-synchronized state), then queue data for in tcp_do_segment()
1931 if (tp->t_state == TCPS_SYN_RECEIVED || in tcp_do_segment()
1932 (tp->t_flags & TF_NEEDSYN)) { in tcp_do_segment()
1933 if (tp->t_state == TCPS_SYN_RECEIVED && in tcp_do_segment()
1934 IS_FASTOPEN(tp->t_flags)) { in tcp_do_segment()
1935 tp->snd_wnd = tiwin; in tcp_do_segment()
1939 } else if (tp->t_flags & TF_ACKNOW) in tcp_do_segment()
1950 switch (tp->t_state) { in tcp_do_segment()
1953 * In SYN_RECEIVED state, the ack ACKs our SYN, so enter in tcp_do_segment()
1963 if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == in tcp_do_segment()
1965 tp->rcv_scale = tp->request_r_scale; in tcp_do_segment()
1966 tp->snd_wnd = tiwin; in tcp_do_segment()
1970 * SYN-RECEIVED -> ESTABLISHED in tcp_do_segment()
1971 * SYN-RECEIVED* -> FIN-WAIT-1 in tcp_do_segment()
1973 tp->t_starttime = ticks; in tcp_do_segment()
1977 if (IS_FASTOPEN(tp->t_flags)/* && tp->t_tfo_pending */) {\ in tcp_do_segment()
1979 tcp_fastopen_decrement_counter(tp->t_tfo_pending); in tcp_do_segment()
1980 tp->t_tfo_pending = NULL; in tcp_do_segment()
1987 tp->snd_una++; in tcp_do_segment()
1989 if (tp->t_flags & TF_NEEDFIN) { in tcp_do_segment()
1991 tp->t_flags &= ~TF_NEEDFIN; in tcp_do_segment()
1995 sig->conn_established = true; in tcp_do_segment()
2003 if (!IS_FASTOPEN(tp->t_flags)) in tcp_do_segment()
2009 * in SYN-RECEIVED indicates that we are in simultaneous open. in tcp_do_segment()
2010 * Therefore, don't ACK the SYN-ACK (unless it contains data or in tcp_do_segment()
2014 tp->t_flags &= ~TF_ACKNOW; in tcp_do_segment()
2018 * accepting a connection, so call the appropriate callback in in tcp_do_segment()
2021 … bool accepted = tcplp_sys_accepted_connection(tp->accepted_from, tp, &ip6->ip6_src, th->th_sport); in tcp_do_segment()
2036 tp->snd_wl1 = th->th_seq - 1; in tcp_do_segment()
2040 * In ESTABLISHED state: drop duplicate ACKs; ACK out of range in tcp_do_segment()
2041 * ACKs. If the ack is in the range in tcp_do_segment()
2042 * tp->snd_una < th->th_ack <= tp->snd_max in tcp_do_segment()
2043 * then advance tp->snd_una to th->th_ack and drop in tcp_do_segment()
2053 if (SEQ_GT(th->th_ack, tp->snd_max)) { in tcp_do_segment()
2057 if ((tp->t_flags & TF_SACK_PERMIT) && in tcp_do_segment()
2059 !TAILQ_EMPTY(&tp->snd_holes))) in tcp_do_segment()
2060 tcp_sack_doack(tp, &to, th->th_ack); in tcp_do_segment()
2062 if (SEQ_LEQ(th->th_ack, tp->snd_una)) { in tcp_do_segment()
2063 if (tlen == 0 && tiwin == tp->snd_wnd) { in tcp_do_segment()
2072 (TCPS_HAVERCVDFIN(tp->t_state) == 0)) { in tcp_do_segment()
2073 tp->t_dupacks = 0; in tcp_do_segment()
2097 * so bump cwnd by the amount in the receiver in tcp_do_segment()
2098 * to keep a constant cwnd packets in the in tcp_do_segment()
2105 th->th_ack != tp->snd_una) in tcp_do_segment()
2106 tp->t_dupacks = 0; in tcp_do_segment()
2107 else if (++tp->t_dupacks > tcprexmtthresh || in tcp_do_segment()
2108 IN_FASTRECOVERY(tp->t_flags)) { in tcp_do_segment()
2110 if ((tp->t_flags & TF_SACK_PERMIT) && in tcp_do_segment()
2111 IN_FASTRECOVERY(tp->t_flags)) { in tcp_do_segment()
2115 * Compute the amount of data in flight first. in tcp_do_segment()
2118 * worth of data in flight. in tcp_do_segment()
2120 awnd = (tp->snd_nxt - tp->snd_fack) + in tcp_do_segment()
2121 tp->sackhint.sack_bytes_rexmit; in tcp_do_segment()
2122 if (awnd < tp->snd_ssthresh) { in tcp_do_segment()
2123 tp->snd_cwnd += tp->t_maxseg; in tcp_do_segment()
2124 if (tp->snd_cwnd > tp->snd_ssthresh) in tcp_do_segment()
2125 tp->snd_cwnd = tp->snd_ssthresh; in tcp_do_segment()
2128 tp->snd_cwnd += tp->t_maxseg; in tcp_do_segment()
2134 } else if (tp->t_dupacks == tcprexmtthresh) { in tcp_do_segment()
2135 tcp_seq onxt = tp->snd_nxt; in tcp_do_segment()
2139 * see if we're already in sack in tcp_do_segment()
2141 * check to see if we're in newreno in tcp_do_segment()
2144 if (tp->t_flags & TF_SACK_PERMIT) { in tcp_do_segment()
2145 if (IN_FASTRECOVERY(tp->t_flags)) { in tcp_do_segment()
2146 tp->t_dupacks = 0; in tcp_do_segment()
2150 if (SEQ_LEQ(th->th_ack, in tcp_do_segment()
2151 tp->snd_recover)) { in tcp_do_segment()
2152 tp->t_dupacks = 0; in tcp_do_segment()
2160 tp->t_rtttime = 0; in tcp_do_segment()
2165 if (tp->t_flags & TF_SACK_PERMIT) { in tcp_do_segment()
2166 tp->sack_newdata = tp->snd_nxt; in tcp_do_segment()
2167 tp->snd_cwnd = tp->t_maxseg; in tcp_do_segment()
2172 tp->snd_nxt = th->th_ack; in tcp_do_segment()
2173 tp->snd_cwnd = tp->t_maxseg; in tcp_do_segment()
2178 * to integer overflow in multiplication. in tcp_do_segment()
2180 tp->snd_cwnd = tp->snd_ssthresh + in tcp_do_segment()
2181 ((uint64_t) tp->t_maxseg) * in tcp_do_segment()
2182 ((uint64_t) (tp->t_dupacks - tp->snd_limited)); in tcp_do_segment()
2184 tcplp_sys_log("TCP SET_cwnd %d", (int) tp->snd_cwnd); in tcp_do_segment()
2186 if (SEQ_GT(onxt, tp->snd_nxt)) in tcp_do_segment()
2187 tp->snd_nxt = onxt; in tcp_do_segment()
2205 oldcwnd = tp->snd_cwnd; in tcp_do_segment()
2206 oldsndmax = tp->snd_max; in tcp_do_segment()
2212 KASSERT(tp->t_dupacks == 1 || in tcp_do_segment()
2213 tp->t_dupacks == 2, in tcp_do_segment()
2216 if (tp->t_dupacks == 1) in tcp_do_segment()
2217 tp->snd_limited = 0; in tcp_do_segment()
2218 tp->snd_cwnd = in tcp_do_segment()
2219 (tp->snd_nxt - tp->snd_una) + in tcp_do_segment()
2220 (tp->t_dupacks - tp->snd_limited) * in tcp_do_segment()
2221 tp->t_maxseg; in tcp_do_segment()
2228 * samkumar: Replace sbavail(&so->so_snd) with the call to in tcp_do_segment()
2231 avail = lbuf_used_space(&tp->sendbuf) - in tcp_do_segment()
2232 (tp->snd_nxt - tp->snd_una); in tcp_do_segment()
2235 sent = tp->snd_max - oldsndmax; in tcp_do_segment()
2236 if (sent > tp->t_maxseg) { in tcp_do_segment()
2237 KASSERT((tp->t_dupacks == 2 && in tcp_do_segment()
2238 tp->snd_limited == 0) || in tcp_do_segment()
2239 (sent == tp->t_maxseg + 1 && in tcp_do_segment()
2240 tp->t_flags & TF_SENTFIN), in tcp_do_segment()
2243 tp->snd_limited = 2; in tcp_do_segment()
2245 ++tp->snd_limited; in tcp_do_segment()
2246 tp->snd_cwnd = oldcwnd; in tcp_do_segment()
2248 tcplp_sys_log("TCP RESET_cwnd %d", (int) tp->snd_cwnd); in tcp_do_segment()
2253 tp->t_dupacks = 0; in tcp_do_segment()
2257 KASSERT(SEQ_GT(th->th_ack, tp->snd_una), in tcp_do_segment()
2264 if (IN_FASTRECOVERY(tp->t_flags)) { in tcp_do_segment()
2265 if (SEQ_LT(th->th_ack, tp->snd_recover)) { in tcp_do_segment()
2266 if (tp->t_flags & TF_SACK_PERMIT) in tcp_do_segment()
2274 tp->t_dupacks = 0; in tcp_do_segment()
2279 if (tp->t_flags & TF_NEEDSYN) { in tcp_do_segment()
2281 * T/TCP: Connection was half-synchronized, and our in tcp_do_segment()
2283 * synchronized). Go to non-starred state, in tcp_do_segment()
2287 tp->t_flags &= ~TF_NEEDSYN; in tcp_do_segment()
2288 tp->snd_una++; in tcp_do_segment()
2290 if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == in tcp_do_segment()
2292 tp->rcv_scale = tp->request_r_scale; in tcp_do_segment()
2304 * to do the retransmit in the first place. Recover our in tcp_do_segment()
2308 if (tp->t_rxtshift == 1 && tp->t_flags & TF_PREVVALID && in tcp_do_segment()
2309 (int)(ticks - tp->t_badrxtwin) < 0) in tcp_do_segment()
2317 * Since we now have an rtt measurement, cancel the in tcp_do_segment()
2330 t = tcp_ts_getticks() - to.to_tsecr; in tcp_do_segment()
2331 if (!tp->t_rttlow || tp->t_rttlow > t) in tcp_do_segment()
2332 tp->t_rttlow = t; in tcp_do_segment()
2334 } else if (tp->t_rtttime && SEQ_GT(th->th_ack, tp->t_rtseq)) { in tcp_do_segment()
2335 if (!tp->t_rttlow || tp->t_rttlow > ticks - tp->t_rtttime) in tcp_do_segment()
2336 tp->t_rttlow = ticks - tp->t_rtttime; in tcp_do_segment()
2337 tcp_xmit_timer(tp, ticks - tp->t_rtttime); in tcp_do_segment()
2344 * timer, using current (possibly backed-off) value. in tcp_do_segment()
2346 if (th->th_ack == tp->snd_max) { in tcp_do_segment()
2350 tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); in tcp_do_segment()
2368 * samkumar: I replaced the calls to sbavail(&so->so_snd) with new in tcp_do_segment()
2371 * sbcut_locked(&so->so_send, (int)sbavail(&so->so_snd)) in the if case in tcp_do_segment()
2372 * and sbcut_locked(&so->so_snd, acked) in the else case, to use the in tcp_do_segment()
2375 if (acked > lbuf_used_space(&tp->sendbuf)) { in tcp_do_segment()
2377 uint32_t usedspace = lbuf_used_space(&tp->sendbuf); in tcp_do_segment()
2378 tp->snd_wnd -= usedspace; in tcp_do_segment()
2379 poppedbytes = lbuf_pop(&tp->sendbuf, usedspace, &sig->links_popped); in tcp_do_segment()
2381 sig->bytes_acked += poppedbytes; in tcp_do_segment()
2384 uint32_t poppedbytes = lbuf_pop(&tp->sendbuf, acked, &sig->links_popped); in tcp_do_segment()
2386 sig->bytes_acked += poppedbytes; in tcp_do_segment()
2387 tp->snd_wnd -= acked; in tcp_do_segment()
2399 if (!IN_RECOVERY(tp->t_flags) && in tcp_do_segment()
2400 SEQ_GT(tp->snd_una, tp->snd_recover) && in tcp_do_segment()
2401 SEQ_LEQ(th->th_ack, tp->snd_recover)) in tcp_do_segment()
2402 tp->snd_recover = th->th_ack - 1; in tcp_do_segment()
2404 if (IN_RECOVERY(tp->t_flags) && in tcp_do_segment()
2405 SEQ_GEQ(th->th_ack, tp->snd_recover)) { in tcp_do_segment()
2406 EXIT_RECOVERY(tp->t_flags); in tcp_do_segment()
2408 tp->snd_una = th->th_ack; in tcp_do_segment()
2409 if (tp->t_flags & TF_SACK_PERMIT) { in tcp_do_segment()
2410 if (SEQ_GT(tp->snd_una, tp->snd_recover)) in tcp_do_segment()
2411 tp->snd_recover = tp->snd_una; in tcp_do_segment()
2413 if (SEQ_LT(tp->snd_nxt, tp->snd_una)) in tcp_do_segment()
2414 tp->snd_nxt = tp->snd_una; in tcp_do_segment()
2416 switch (tp->t_state) { in tcp_do_segment()
2419 * In FIN_WAIT_1 STATE in addition to the processing in tcp_do_segment()
2438 * in so->so_rcv.sb_state with a call to tcpiscantrcv. in tcp_do_segment()
2452 * In CLOSING STATE in addition to the processing for in tcp_do_segment()
2454 * then enter the TIME-WAIT state, otherwise ignore in tcp_do_segment()
2461 * an ACK in the TIME-WAIT state, since we don't want to in tcp_do_segment()
2463 * original FreeBSD code, uses tcpcbs for connections in the in tcp_do_segment()
2464 * TIME-WAIT state (FreeBSD uses a different, smaller in tcp_do_segment()
2467 tp->t_flags &= ~TF_ACKNOW; in tcp_do_segment()
2474 * In LAST_ACK, we may still be waiting for data to drain in tcp_do_segment()
2496 (SEQ_LT(tp->snd_wl1, th->th_seq) || in tcp_do_segment()
2497 (tp->snd_wl1 == th->th_seq && (SEQ_LT(tp->snd_wl2, th->th_ack) || in tcp_do_segment()
2498 (tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd))))) { in tcp_do_segment()
2503 * tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd) and keep in tcp_do_segment()
2506 tp->snd_wnd = tiwin; in tcp_do_segment()
2507 tp->snd_wl1 = th->th_seq; in tcp_do_segment()
2508 tp->snd_wl2 = th->th_ack; in tcp_do_segment()
2509 if (tp->snd_wnd > tp->max_sndwnd) in tcp_do_segment()
2510 tp->max_sndwnd = tp->snd_wnd; in tcp_do_segment()
2519 * urgent-pointer-related processing and buffering. The code below is the in tcp_do_segment()
2520 * code that was in the "else" case that handles no valid urgent data in in tcp_do_segment()
2529 if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) in tcp_do_segment()
2530 tp->rcv_up = tp->rcv_nxt; in tcp_do_segment()
2536 * This process logically involves adjusting tp->rcv_wnd as data in tcp_do_segment()
2537 * is presented to the user (this happens in tcp_usrreq.c, in tcp_do_segment()
2541 tfo_syn = ((tp->t_state == TCPS_SYN_RECEIVED) && in tcp_do_segment()
2542 IS_FASTOPEN(tp->t_flags)); in tcp_do_segment()
2544 TCPS_HAVERCVDFIN(tp->t_state) == 0) { in tcp_do_segment()
2545 tcp_seq save_start = th->th_seq; in tcp_do_segment()
2561 * Set DELACK for segments received in order, but ack in tcp_do_segment()
2566 * samkumar: I replaced LIST_EMPTY(&tp->t_segq) with the calls to in tcp_do_segment()
2569 if (th->th_seq == tp->rcv_nxt && in tcp_do_segment()
2570 (tpiscantrcv(tp) || bmp_isempty(tp->reassbmp, REASSBMP_SIZE(tp))) && in tcp_do_segment()
2571 (TCPS_HAVEESTABLISHED(tp->t_state) || in tcp_do_segment()
2574 tp->t_flags |= TF_DELACK; in tcp_do_segment()
2576 tp->t_flags |= TF_ACKNOW; in tcp_do_segment()
2577 tp->rcv_nxt += tlen; in tcp_do_segment()
2578 thflags = th->th_flags & TH_FIN; in tcp_do_segment()
2583 * on so->so_rcv.sb_state, and otherwise call in tcp_do_segment()
2584 * sbappendstream_locked(&so->so_rcv, m, 0);). in tcp_do_segment()
2587 …cbuf_write(&tp->recvbuf, msg, otMessageGetOffset(msg) + drop_hdrlen, tlen, cbuf_copy_from_message); in tcp_do_segment()
2589 sig->recvbuf_added = true; in tcp_do_segment()
2595 * receiving a FIN. I'm going to drop the connection in this in tcp_do_segment()
2613 * samkumar: We will reach this point if we get out-of-order data in tcp_do_segment()
2628 tp->t_flags |= TF_ACKNOW; in tcp_do_segment()
2631 if (tlen > 0 && (tp->t_flags & TF_SACK_PERMIT)) in tcp_do_segment()
2635 * commented out in the FreeBSD code. in tcp_do_segment()
2640 * our window, in order to estimate the sender's in tcp_do_segment()
2644 if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt)) in tcp_do_segment()
2645 len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt); in tcp_do_segment()
2647 len = so->so_rcv.sb_hiwat; in tcp_do_segment()
2659 if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { in tcp_do_segment()
2663 * If connection is half-synchronized in tcp_do_segment()
2669 if (tp->t_flags & TF_NEEDSYN) in tcp_do_segment()
2670 tp->t_flags |= TF_DELACK; in tcp_do_segment()
2672 tp->t_flags |= TF_ACKNOW; in tcp_do_segment()
2673 tp->rcv_nxt++; in tcp_do_segment()
2676 * samkumar: This -2 state is added by me, so that we do not consider in tcp_do_segment()
2677 * any more FINs in reassembly. in tcp_do_segment()
2679 if (tp->reass_fin_index != -2) { in tcp_do_segment()
2680 sig->rcvd_fin = true; in tcp_do_segment()
2681 tp->reass_fin_index = -2; in tcp_do_segment()
2683 switch (tp->t_state) { in tcp_do_segment()
2686 * In SYN_RECEIVED and ESTABLISHED STATES in tcp_do_segment()
2690 tp->t_starttime = ticks; in tcp_do_segment()
2697 * If still in FIN_WAIT_1 STATE FIN has not been acked so in tcp_do_segment()
2705 * In FIN_WAIT_2 state enter the TIME_WAIT state, in tcp_do_segment()
2706 * starting the time-wait timer, turning off the other in tcp_do_segment()
2716 * samkumar: Remove code for synchronization and debugging, here and in in tcp_do_segment()
2723 if (needoutput || (tp->t_flags & TF_ACKNOW)) in tcp_do_segment()
2727 if (tp->t_flags & TF_DELACK) { in tcp_do_segment()
2728 tp->t_flags &= ~TF_DELACK; in tcp_do_segment()
2742 * In the SYN-RECEIVED state, don't send an ACK unless the in tcp_do_segment()
2743 * segment we received passes the SYN-RECEIVED ACK test. in tcp_do_segment()
2744 * If it fails send a RST. This breaks the loop in the in tcp_do_segment()
2749 if (tp->t_state == TCPS_SYN_RECEIVED && (thflags & TH_ACK) && in tcp_do_segment()
2750 (SEQ_GT(tp->snd_una, th->th_ack) || in tcp_do_segment()
2751 SEQ_GT(th->th_ack, tp->snd_max)) ) { in tcp_do_segment()
2756 tp->t_flags |= TF_ACKNOW; in tcp_do_segment()
2772 * Parse TCP options and place in tcpopt.
2779 to->to_flags = 0; in tcp_dooptions()
2780 for (; cnt > 0; cnt -= optlen, cp += optlen) { in tcp_dooptions()
2799 to->to_flags |= TOF_MSS; in tcp_dooptions()
2801 (char *)&to->to_mss, sizeof(to->to_mss)); in tcp_dooptions()
2802 to->to_mss = ntohs(to->to_mss); in tcp_dooptions()
2809 to->to_flags |= TOF_SCALE; in tcp_dooptions()
2810 to->to_wscale = min(cp[2], TCP_MAX_WINSHIFT); in tcp_dooptions()
2815 to->to_flags |= TOF_TS; in tcp_dooptions()
2817 (char *)&to->to_tsval, sizeof(to->to_tsval)); in tcp_dooptions()
2818 to->to_tsval = ntohl(to->to_tsval); in tcp_dooptions()
2820 (char *)&to->to_tsecr, sizeof(to->to_tsecr)); in tcp_dooptions()
2821 to->to_tsecr = ntohl(to->to_tsecr); in tcp_dooptions()
2825 * XXX In order to reply to a host which has set the in tcp_dooptions()
2826 * TCP_SIGNATURE option in its initial SYN, we have to in tcp_dooptions()
2833 to->to_flags |= TOF_SIGNATURE; in tcp_dooptions()
2834 to->to_signature = cp + 2; in tcp_dooptions()
2844 to->to_flags |= TOF_SACKPERM; in tcp_dooptions()
2847 if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0) in tcp_dooptions()
2851 to->to_flags |= TOF_SACK; in tcp_dooptions()
2852 to->to_nsacks = (optlen - 2) / TCPOLEN_SACK; in tcp_dooptions()
2853 to->to_sacks = cp + 2; in tcp_dooptions()
2866 to->to_flags |= TOF_FASTOPEN; in tcp_dooptions()
2867 to->to_tfo_len = optlen - 2; in tcp_dooptions()
2868 to->to_tfo_cookie = to->to_tfo_len ? cp + 2 : NULL; in tcp_dooptions()
2878 * Collect new round-trip time estimate
2886 tp->t_rttupdated++; in tcp_xmit_timer()
2887 if (tp->t_srtt != 0) { in tcp_xmit_timer()
2891 * is equivalent to the smoothing algorithm in rfc793 with in tcp_xmit_timer()
2892 * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed in tcp_xmit_timer()
2895 delta = ((rtt - 1) << TCP_DELTA_SHIFT) in tcp_xmit_timer()
2896 - (tp->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT)); in tcp_xmit_timer()
2898 if ((tp->t_srtt += delta) <= 0) in tcp_xmit_timer()
2899 tp->t_srtt = 1; in tcp_xmit_timer()
2909 * rfc793's wired-in beta. in tcp_xmit_timer()
2912 delta = -delta; in tcp_xmit_timer()
2913 delta -= tp->t_rttvar >> (TCP_RTTVAR_SHIFT - TCP_DELTA_SHIFT); in tcp_xmit_timer()
2914 if ((tp->t_rttvar += delta) <= 0) in tcp_xmit_timer()
2915 tp->t_rttvar = 1; in tcp_xmit_timer()
2916 if (tp->t_rttbest > tp->t_srtt + tp->t_rttvar) in tcp_xmit_timer()
2917 tp->t_rttbest = tp->t_srtt + tp->t_rttvar; in tcp_xmit_timer()
2920 * No rtt measurement yet - use the unsmoothed rtt. in tcp_xmit_timer()
2924 tp->t_srtt = rtt << TCP_RTT_SHIFT; in tcp_xmit_timer()
2925 tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1); in tcp_xmit_timer()
2926 tp->t_rttbest = tp->t_srtt + tp->t_rttvar; in tcp_xmit_timer()
2928 tp->t_rtttime = 0; in tcp_xmit_timer()
2929 tp->t_rxtshift = 0; in tcp_xmit_timer()
2936 * 1 extra tick because of +-1/2 tick uncertainty in the in tcp_xmit_timer()
2942 TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), in tcp_xmit_timer()
2943 max(tp->t_rttmin, rtt + 2), TCPTV_REXMTMAX); in tcp_xmit_timer()
2946 …er %u %d %d %d", (unsigned int) tcplp_sys_get_millis(), rtt, (int) tp->t_srtt, (int) tp->t_rttvar); in tcp_xmit_timer()
2957 tp->t_softerror = 0; in tcp_xmit_timer()
2965 * as the MSS is clamped at V_tcp_v6mssdflt for connections to non-local
2968 * obviously so---we keep the part of the function that checks for loopback or
2970 * assigned to interfaces. In cases where we return 0 but should have returned
2972 * In fact, the constants are set such that we'll get the right answer whether
2993 * While looking at the routing entry, we also initialize other path-dependent
2994 * parameters from pre-set or cached values in the routing entry.
3000 * data in maxopd.
3004 * settings are handled in tcp_mssopt().
3014 * samkumar: I removed all IPv4-specific logic and cases, including logic in tcp_mss_update()
3023 if (mtuoffer != -1) { in tcp_mss_update()
3024 KASSERT(offer == -1, ("%s: conflict", __func__)); in tcp_mss_update()
3025 offer = mtuoffer - min_protoh; in tcp_mss_update()
3030 tp->t_maxopd = tp->t_maxseg = V_tcp_v6mssdflt; in tcp_mss_update()
3037 * In case we return early we need to initialize metrics in tcp_mss_update()
3051 * segment, in this case we use tcp_mssdflt as in tcp_mss_update()
3054 offer = tp->t_maxopd; in tcp_mss_update()
3057 case -1: in tcp_mss_update()
3059 * Offer == -1 means that we didn't receive SYN yet. in tcp_mss_update()
3079 * If there's a discovered mtu in tcp hostcache, use it. in tcp_mss_update()
3083 mss = min(metrics.rmx_mtu, maxmtu) - min_protoh; in tcp_mss_update()
3085 mss = maxmtu - min_protoh; in tcp_mss_update()
3087 !in6_localaddr(&tp->faddr)) in tcp_mss_update()
3090 * XXX - The above conditional (mss = maxmtu - min_protoh) in tcp_mss_update()
3114 * funny things may happen in tcp_output. in tcp_mss_update()
3125 * in a segment; maxseg is the amount of data in a normal in tcp_mss_update()
3128 * and thus we normally have somewhat less data in segments. in tcp_mss_update()
3130 tp->t_maxopd = mss; in tcp_mss_update()
3133 * origoffer==-1 indicates that no segments were received yet. in tcp_mss_update()
3134 * In this case we just guess. in tcp_mss_update()
3136 if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && in tcp_mss_update()
3137 (origoffer == -1 || in tcp_mss_update()
3138 (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)) in tcp_mss_update()
3139 mss -= TCPOLEN_TSTAMP_APPA; in tcp_mss_update()
3141 tp->t_maxseg = mss; in tcp_mss_update()
3153 tcp_mss_update(tp, offer, -1, &metrics, &cap); in tcp_mss()
3158 * read tp->t_maxseg into the local variable mss, modify mss, and then in tcp_mss()
3159 * reassign tp->t_maxseg to mss. I've kept the assignments, commented out, in tcp_mss()
3162 //mss = tp->t_maxseg; in tcp_mss()
3176 * "sbreserve_locked(&so->so_snd, bufsize, so, NULL);". With TCPlp, we do in tcp_mss()
3187 //tp->t_maxseg = mss; in tcp_mss()
3193 * "sbreserve_locked(&so->so_rcv, bufsize, so, NULL);". In TCPlp, the in tcp_mss()
3198 * Offloading (TSO); I removed it becuase we don't support that in TCPlp. in tcp_mss()
3206 * samkumar: In the signature, changed "struct in_conninfo *inc" to
3230 mss = min(maxmtu, thcmtu) - min_protoh; in tcp_mssopt()
3232 mss = max(maxmtu, thcmtu) - min_protoh; in tcp_mssopt()
3239 * next unacknowledged segment. Do not clear tp->t_dupacks.
3246 tcp_seq onxt = tp->snd_nxt; in tcp_newreno_partial_ack()
3247 uint64_t ocwnd = tp->snd_cwnd; in tcp_newreno_partial_ack()
3250 tp->t_rtttime = 0; in tcp_newreno_partial_ack()
3251 tp->snd_nxt = th->th_ack; in tcp_newreno_partial_ack()
3254 * (tp->snd_una has not yet been updated when this function is called.) in tcp_newreno_partial_ack()
3256 tp->snd_cwnd = tp->t_maxseg + BYTES_THIS_ACK(tp, th); in tcp_newreno_partial_ack()
3257 tp->t_flags |= TF_ACKNOW; in tcp_newreno_partial_ack()
3262 tp->snd_cwnd = ocwnd; in tcp_newreno_partial_ack()
3263 if (SEQ_GT(onxt, tp->snd_nxt)) in tcp_newreno_partial_ack()
3264 tp->snd_nxt = onxt; in tcp_newreno_partial_ack()
3266 * Partial window deflation. Relies on fact that tp->snd_una in tcp_newreno_partial_ack()
3269 if (tp->snd_cwnd > BYTES_THIS_ACK(tp, th)) in tcp_newreno_partial_ack()
3270 tp->snd_cwnd -= BYTES_THIS_ACK(tp, th); in tcp_newreno_partial_ack()
3272 tp->snd_cwnd = 0; in tcp_newreno_partial_ack()
3273 tp->snd_cwnd += tp->t_maxseg; in tcp_newreno_partial_ack()
3275 tcplp_sys_log("TCP Partial_ACK_final %d", (int) tp->snd_cwnd); in tcp_newreno_partial_ack()