/* * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Author: Venkata N. Padmanabhan (padmanab@cs.berkeley.edu) */ #ifndef _NETINET_TCP_SESSION_H_ #define _NETINET_TCP_SESSION_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef TCP_STATS #include extern struct timeval time; #endif extern int tcprexmtthresh; /* TRUE if TCP session is enabled for this connection */ #define SESSION(tp) ((tp)->t_xflags & TXF_SESSION_ENABLE) /* TRUE if tcp_output() has been called from session_output() */ #define SESSION_OUTPUT(tp) ((tp)->t_xflags & TXF_SESSION_OUTPUT) /* TRUE if session cwnd should be incremented each time a new conn is added */ #define SESSION_INCR_CWND(tp) ((tp)->t_xflags & TXF_SESSION_INCR_CWND) /* all connections between a pair of hosts are in the same session */ #define CONN_IN_SESSION(tp,sp) \ ((((sp)->inp_laddr.s_addr == (tp)->t_inpcb->inp_laddr.s_addr) && \ ((sp)->inp_faddr.s_addr == (tp)->t_inpcb->inp_faddr.s_addr)) ? 1 : 0) /* make it clear that tcp_output() has been called from session_output() */ #define TCP_OUTPUT(tp) { \ (tp)->t_xflags |= TXF_SESSION_OUTPUT; \ tcp_output((tp)); \ (tp)->t_xflags &= ~TXF_SESSION_OUTPUT; \ } /* tests for per-session flags */ /* * TRUE if ack is not the next expected in sequence (such as a * dupack or a partial ack). In such a case, session_opencwnd() * is not called. */ #define SESSION_LOSS_SUSPECTED(sp) ((sp)->flags & SSF_LOSS_SUSPECTED) /* * TRUE if multiple losses are detected in a loss window. In such cases, * ownd is not adjusted when an ack that doesn't acknowledge any new * data (e.g., a dupack) is received. */ #define SESSION_DONT_ADJUST_OWND(sp) ((sp)->flags & SSF_DONT_ADJUST_OWND) /* tests for per-segment flags */ /* TRUE if partial new ack received for this segment */ #define SEG_PARTIALACK(seg) ((seg)->flags & SGF_PARTIALACK) /* TRUE if this is a retransmission */ #define SEG_RXMITTED(seg) ((seg)->flags & SGF_RXMITTED) /* * TRUE if there are at least a threshold number (by default 3) of dupacks/later * acks for this segment */ #define SEG_THRESH_DUPACK(seg) ((seg)->flags & SGF_THRESH_DUPACK) /* compare timestamps */ #define TSTMP_GT(t1,t2) SEQ_GT(t1,t2) /* * These macros check if a delayed ack is long overdue. The threshold * is set to 2*(1/PR_FASTHZ) seconds. However, in general is undesirable * to make any assumptions about the extent to which an ack can get * delayed, so this macro is deprecated. */ #ifdef FINE_GRAINED_TSTAMP /* we set delack threshold to 2*200ms = 400ms */ #define DELACK_THRESH_GEQ(t1,t2) \ ((((u_long) ((t1)-(t2))) >= 2*EXACT_HZ/PR_FASTHZ) ? 1:0) #else #define DELACK_THRESH_GEQ(t1,t2) \ ((((u_long) ((t1)-(t2))) >= 1) ? 1:0) #endif #define TIMEOUT 1 #define FAST_REXMT 2 struct tcpcb; /* * The TCP session protocol control block. "tp" points to a tcpcb that * is used to store certain session-wide state variables (e.g., snd_cwnd, * srtt, etc.). "connlist" points to the list of connections in the session. * "seglist" points to the list of unacked segments belonging to connections * in the session. */ struct sessionpcb { u_short flags; #define SSF_LOSS_SUSPECTED 0x0001 #define SSF_DONT_ADJUST_OWND 0x0002 struct in_addr inp_faddr; struct in_addr inp_laddr; int numconn; int numseg; short dupack_ok; long ownd; long ownd_correction; u_long highest_echoed_ts; tcp_seq session_seqno; tcp_seq recover; u_long max_bytes_snd; struct tcpcb *tp; struct tcpcb *curconn; LIST_HEAD(connlist,tcpcb) connlist; TAILQ_HEAD(seglist,segment) seglist; LIST_ENTRY(sessionpcb) next_session; }; /* * For each unacked segment in the session, this structure stores its * sequence number within its connection, session-wide sequence number, * send timestamp, number of dupacks/later acks, and a pointer to its * connections tcpcb. All the segments are linked together in a list * sorted by the order of transmission. */ struct segment { u_short flags; #define SGF_PARTIALACK 0x0001 #define SGF_RXMITTED 0x0002 #define SGF_THRESH_DUPACK 0x0004 tcp_seq startseq; tcp_seq endseq; tcp_seq session_seqno; u_long ts; short dupacks; /* on same connection */ short later_acks; /* on other connections */ struct tcpcb *tp; TAILQ_ENTRY(segment) nextseg; }; /* list of all TCP sessions */ LIST_HEAD(session_list,sessionpcb) session_list; /* TCP session functions */ void session_init __P(()); struct sessionpcb * session_newpcb __P((struct tcpcb *)); struct sessionpcb * session_addconn __P((struct tcpcb *)); void session_delconn __P((struct tcpcb *)); void session_opencwnd __P((struct sessionpcb *, int)); void session_closecwnd __P((struct sessionpcb *, int)); void session_adjust_ownd __P((struct sessionpcb *, u_long)); void session_xmit_timer __P((struct tcpcb *, short)); void session_xmit_timer_exact __P((struct tcpcb *, u_long)); struct segment * session_rexmt_oneseg __P((struct sessionpcb *, struct segment *)); void session_rexmt __P((struct sessionpcb *)); void session_clean_segs __P((struct sessionpcb *, struct tcpcb *, struct tcpiphdr *, struct tcp_opt_info *, int)); void session_timeout __P((struct sessionpcb *)); struct segment * session_output_oneseg __P((struct sessionpcb *, struct tcpcb *, int)); void session_output __P((struct sessionpcb *)); void session_input __P((struct tcpcb *, struct tcpiphdr *, struct tcp_opt_info *, int)); void session_rcvd_syn_ack __P((struct tcpcb *, struct tcpiphdr *)); #endif /* _NETINET_TCP_SESSION_H_ */