#ifndef _NETINET_TCP_VAR_H_
#define _NETINET_TCP_VAR_H_
#ifndef _NETINET_IN_PCB_H_
#include <netinet/in_pcb.h>
#endif
#ifndef _NETINET_TCP_H_
#include <netinet/tcp.h>
#endif
extern int tcp_do_rfc1323;
extern int tcp_low_rtobase;
extern int tcp_ncr_linklocal;
extern int tcp_ncr_rxtthresh_max;
extern int tcp_do_sack;
extern int tcp_do_smartsack;
extern int tcp_do_rescuesack;
extern int tcp_aggressive_rescuesack;
extern int tcp_do_rfc6675;
extern int tcp_rfc6675_rxt;
extern int tcp_aggregate_acks;
extern int tcp_eifel_rtoinc;
extern int tcp_prio_synack;
struct tseg_qent {
TAILQ_ENTRY(tseg_qent) tqe_q;
int tqe_len;
struct tcphdr *tqe_th;
struct mbuf *tqe_m;
};
TAILQ_HEAD(tsegqe_head, tseg_qent);
extern int tcp_reass_maxseg;
extern int tcp_reass_qsize;
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_TSEGQ);
#endif
struct tcptemp {
u_char tt_ipgen[40];
struct tcphdr tt_t;
};
#define tcp6cb tcpcb
struct raw_sackblock {
tcp_seq rblk_start;
tcp_seq rblk_end;
};
#define MAX_SACK_REPORT_BLOCKS 4
TAILQ_HEAD(sackblock_list, sackblock);
struct scoreboard {
int nblocks;
struct sackblock_list sackblocks;
tcp_seq lostseq;
struct sackblock *lastfound;
struct sackblock *freecache;
};
struct netmsg_tcp_timer;
struct netmsg_base;
struct tcp_pcbport {
struct inpcbport t_phd;
} __cachealign;
struct tcpcb {
struct tsegqe_head t_segq;
int t_dupacks;
int t_rxtthresh;
int tt_cpu;
struct tcp_pcbport *t_pcbport;
struct tcp_callout *tt_rexmt;
struct tcp_callout *tt_persist;
struct tcp_callout *tt_keep;
struct tcp_callout *tt_2msl;
struct tcp_callout *tt_delack;
struct netmsg_tcp_timer *tt_msg;
struct netmsg_base *tt_sndmore;
struct inpcb *t_inpcb;
int t_state;
u_int t_flags;
#define TF_ACKNOW 0x00000001
#define TF_DELACK 0x00000002
#define TF_NODELAY 0x00000004
#define TF_NOOPT 0x00000008
#define TF_SENTFIN 0x00000010
#define TF_REQ_SCALE 0x00000020
#define TF_RCVD_SCALE 0x00000040
#define TF_REQ_TSTMP 0x00000080
#define TF_RCVD_TSTMP 0x00000100
#define TF_SACK_PERMITTED 0x00000200
#define TF_NEEDSYN 0x00000400
#define TF_NEEDFIN 0x00000800
#define TF_NOPUSH 0x00001000
#define TF_LISTEN 0x00002000
#define TF_SIGNATURE 0x00004000
#define TF_NCR 0x00008000
#define TF_MORETOCOME 0x00010000
#define TF_SAWFIN 0x00020000
#define TF_LASTIDLE 0x00040000
#define TF_RXWIN0SENT 0x00080000
#define TF_FASTRECOVERY 0x00100000
#define TF_QUEDFIN 0x00200000
#define TF_XMITNOW 0x00400000
#define TF_UNUSED008 0x00800000
#define TF_UNUSED009 0x01000000
#define TF_FORCE 0x02000000
#define TF_ONOUTPUTQ 0x04000000
#define TF_FAIRSEND 0x08000000
#define TF_UNUSED003 0x10000000
#define TF_UNUSED004 0x20000000
#define TF_KEEPALIVE 0x40000000
#define TF_RXRESIZED 0x80000000
tcp_seq snd_up;
u_long snd_last;
tcp_seq snd_una;
tcp_seq snd_recover;
tcp_seq snd_max;
tcp_seq snd_nxt;
tcp_seq snd_wl1;
tcp_seq snd_wl2;
tcp_seq iss;
tcp_seq irs;
tcp_seq rcv_nxt;
tcp_seq rcv_adv;
u_long rcv_wnd;
tcp_seq rcv_up;
u_long snd_wnd;
u_long snd_cwnd;
u_long snd_wacked;
u_long snd_ssthresh;
int t_rxtcur;
u_int t_maxseg;
int t_srtt;
int t_rttvar;
u_int t_maxopd;
u_long t_rcvtime;
u_long t_starttime;
int t_rtttime;
tcp_seq t_rtseq;
int t_rxtshift;
u_int t_rttmin;
u_int t_rttbest;
u_long t_rttupdated;
u_long max_sndwnd;
int t_softerror;
char t_oobflags;
char t_iobc;
#define TCPOOB_HAVEDATA 0x01
#define TCPOOB_HADDATA 0x02
u_char snd_scale;
u_char rcv_scale;
u_char request_r_scale;
u_long ts_recent;
u_long ts_recent_age;
tcp_seq last_ack_sent;
u_int rxt_flags;
#define TRXT_F_REBASERTO 0x0001
#define TRXT_F_WASFRECOVERY 0x0002
#define TRXT_F_FIRSTACCACK 0x0004
#define TRXT_F_FASTREXMT 0x0008
#define TRXT_F_EARLYREXMT 0x0010
int t_srtt_prev;
int t_rttvar_prev;
int t_rxtcur_prev;
tcp_seq snd_max_prev;
u_long snd_cwnd_prev;
u_long snd_wacked_prev;
u_long snd_ssthresh_prev;
tcp_seq snd_recover_prev;
u_long t_badrxtwin;
u_long t_rexmtTS;
u_char snd_limited;
u_int sack_flags;
#define TSACK_F_SACKRESCUED 0x0001
#define TSACK_F_DUPSEG 0x0002
#define TSACK_F_ENCLOSESEG 0x0004
#define TSACK_F_SACKLEFT 0x0008
tcp_seq rexmt_high;
tcp_seq rexmt_rescue;
tcp_seq snd_max_rexmt;
struct scoreboard scb;
struct raw_sackblock reportblk;
struct raw_sackblock encloseblk;
int nsackhistory;
struct raw_sackblock sackhistory[MAX_SACK_REPORT_BLOCKS];
TAILQ_ENTRY(tcpcb) t_outputq;
u_long snd_bandwidth;
u_long snd_bwnd;
int t_bw_rtttime;
tcp_seq t_bw_rtseq;
u_long rcv_second;
u_long rcv_pps;
u_long rcv_byps;
u_int32_t rfbuf_ts;
int rfbuf_cnt;
int t_keepinit;
int t_keepidle;
int t_keepintvl;
int t_keepcnt;
int t_maxidle;
int t_rxtsyn;
};
#define IN_FASTRECOVERY(tp) (tp->t_flags & TF_FASTRECOVERY)
#define ENTER_FASTRECOVERY(tp) tp->t_flags |= TF_FASTRECOVERY
#define EXIT_FASTRECOVERY(tp) tp->t_flags &= ~TF_FASTRECOVERY
#ifdef TCP_SIGNATURE
#define TCP_SIGLEN 16
#define TCP_KEYLEN_MIN 1
#define TCP_KEYLEN_MAX 80
#define TCP_SIG_SPI 0x1000
#endif
struct tcp_stats {
u_long tcps_connattempt;
u_long tcps_accepts;
u_long tcps_connects;
u_long tcps_drops;
u_long tcps_conndrops;
u_long tcps_minmssdrops;
u_long tcps_closed;
u_long tcps_segstimed;
u_long tcps_rttupdated;
u_long tcps_delack;
u_long tcps_timeoutdrop;
u_long tcps_rexmttimeo;
u_long tcps_persisttimeo;
u_long tcps_keeptimeo;
u_long tcps_keepprobe;
u_long tcps_keepdrops;
u_long tcps_sndtotal;
u_long tcps_sndpack;
u_long tcps_sndbyte;
u_long tcps_sndrexmitpack;
u_long tcps_sndrexmitbyte;
u_long tcps_sndsackrtopack;
u_long tcps_sndsackrtobyte;
u_long tcps_sndfastrexmit;
u_long tcps_sndearlyrexmit;
u_long tcps_sndlimited;
u_long tcps_sndrtobad;
u_long tcps_sndfastrexmitbad;
u_long tcps_sndearlyrexmitbad;
u_long tcps_eifeldetected;
u_long tcps_rttcantdetect;
u_long tcps_rttdetected;
u_long tcps_sndacks;
u_long tcps_sndprobe;
u_long tcps_sndurg;
u_long tcps_sndwinup;
u_long tcps_sndctrl;
u_long tcps_sndsackpack;
u_long tcps_sndsackbyte;
u_long tcps_snduna3;
u_long tcps_snduna1;
u_long tcps_sndsackopt;
u_long tcps_snddsackopt;
u_long tcps_sndidle;
u_long tcps_sackrescue;
u_long tcps_sackrescue_try;
u_long tcps_eifelresponse;
u_long tcps_rcvtotal;
u_long tcps_rcvpack;
u_long tcps_rcvbyte;
u_long tcps_rcvbadsum;
u_long tcps_rcvbadoff;
u_long tcps_rcvmemdrop;
u_long tcps_rcvshort;
u_long tcps_rcvduppack;
u_long tcps_rcvdupbyte;
u_long tcps_rcvpartduppack;
u_long tcps_rcvpartdupbyte;
u_long tcps_rcvoopack;
u_long tcps_rcvoobyte;
u_long tcps_rcvpackafterwin;
u_long tcps_rcvbyteafterwin;
u_long tcps_rcvafterclose;
u_long tcps_rcvwinprobe;
u_long tcps_rcvdupack;
u_long tcps_rcvacktoomuch;
u_long tcps_rcvackpack;
u_long tcps_rcvackbyte;
u_long tcps_rcvwinupd;
u_long tcps_pawsdrop;
u_long tcps_pawsaccept;
u_long tcps_predack;
u_long tcps_preddat;
u_long tcps_pcbcachemiss;
u_long tcps_cachedrtt;
u_long tcps_cachedrttvar;
u_long tcps_cachedssthresh;
u_long tcps_usedrtt;
u_long tcps_usedrttvar;
u_long tcps_usedssthresh;
u_long tcps_persistdrop;
u_long tcps_badsyn;
u_long tcps_mturesent;
u_long tcps_listendrop;
u_long tcps_rcvbadsackopt;
u_long tcps_sackrenege;
u_long tcps_sacksbupdate;
u_long tcps_sacksboverflow;
u_long tcps_sacksbreused;
u_long tcps_sacksbfailed;
u_long tcps_sacksbfast;
u_long tcps_sc_added;
u_long tcps_sc_retransmitted;
u_long tcps_sc_dupsyn;
u_long tcps_sc_dropped;
u_long tcps_sc_completed;
u_long tcps_sc_bucketoverflow;
u_long tcps_sc_cacheoverflow;
u_long tcps_sc_reset;
u_long tcps_sc_stale;
u_long tcps_sc_aborted;
u_long tcps_sc_badack;
u_long tcps_sc_unreach;
u_long tcps_sc_zonefail;
u_long tcps_sc_sendcookie;
u_long tcps_sc_recvcookie;
u_long tcps_pad[6];
};
#ifdef _KERNEL
CTASSERT((sizeof(struct tcp_stats) & __VM_CACHELINE_MASK) == 0);
#endif
#ifdef _KERNEL
#ifndef _NETINET_TCP_FSM_H_
#include <netinet/tcp_fsm.h>
#endif
struct tcp_state_count {
u_long tcps_count[TCP_NSTATES];
} __cachealign;
#define tcpstat tcpstats_percpu[mycpuid]
struct sockopt;
extern struct tcp_stats tcpstats_percpu[MAXCPU];
extern struct tcp_state_count tcpstate_count[MAXCPU];
static const int tcprexmtthresh = 3;
#endif
struct tcpopt {
u_int to_flags;
#define TOF_TS 0x0001
#define TOF_MSS 0x0010
#define TOF_SCALE 0x0020
#define TOF_SACK_PERMITTED 0x0040
#define TOF_SACK 0x0080
#define TOF_SIGNATURE 0x0100
#define TOF_SIGLEN 0x0200
#define TOF_DSACK 0x0400
#define TOF_SACK_REDUNDANT 0x0800
u_int32_t to_tsval;
u_int32_t to_tsecr;
u_int16_t to_mss;
u_int8_t to_requested_s_scale;
u_int8_t to_nsackblocks;
struct raw_sackblock *to_sackblocks;
};
struct syncache {
inp_gen_t sc_inp_gencnt;
struct tcpcb *sc_tp;
struct mbuf *sc_ipopts;
struct in_conninfo sc_inc;
#define sc_route sc_inc.inc_route
#define sc_route6 sc_inc.inc6_route
u_int32_t sc_tsrecent;
uint16_t sc_hashval;
uint16_t sc_pad;
tcp_seq sc_irs;
tcp_seq sc_iss;
u_long sc_rxttime;
u_int16_t sc_rxtslot;
u_int16_t sc_peer_mss;
u_int16_t sc_wnd;
u_int8_t sc_requested_s_scale:4,
sc_request_r_scale:4;
u_int8_t sc_flags;
#define SCF_NOOPT 0x01
#define SCF_WINSCALE 0x02
#define SCF_TIMESTAMP 0x04
#define SCF_HASH 0x08
#define SCF_UNREACH 0x10
#define SCF_SACK_PERMITTED 0x20
#define SCF_SIGNATURE 0x40
int sc_rxtused;
u_long sc_sndwnd;
TAILQ_ENTRY(syncache) sc_hash;
TAILQ_ENTRY(syncache) sc_timerq;
};
struct syncache_head {
TAILQ_HEAD(, syncache) sch_bucket;
u_int sch_length;
};
#define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_ppcb)
#define sototcpcb(so) (intotcpcb(sotoinpcb(so)))
#define TCP_RTT_SCALE 32
#define TCP_RTT_SHIFT 5
#define TCP_RTTVAR_SCALE 16
#define TCP_RTTVAR_SHIFT 4
#define TCP_DELTA_SHIFT 2
#define TCP_REXMTVAL(tp) \
max((tp)->t_rttmin, (((tp)->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT)) \
+ (tp)->t_rttvar) >> TCP_DELTA_SHIFT)
#if defined(_NETINET_IN_PCB_H_) && defined(_SYS_SOCKETVAR_H_)
struct xtcpcb {
size_t xt_len;
struct inpcb xt_inp;
struct tcpcb xt_tp;
struct xsocket xt_socket;
u_quad_t xt_alignment_hack;
};
#endif
#define TCPCTL_DO_RFC1323 1
#define TCPCTL_MSSDFLT 3
#define TCPCTL_STATS 4
#define TCPCTL_RTTDFLT 5
#define TCPCTL_KEEPIDLE 6
#define TCPCTL_KEEPINTVL 7
#define TCPCTL_SENDSPACE 8
#define TCPCTL_RECVSPACE 9
#define TCPCTL_KEEPINIT 10
#define TCPCTL_PCBLIST 11
#define TCPCTL_DELACKTIME 12
#define TCPCTL_V6MSSDFLT 13
#define TCPCTL_MAXID 14
#ifdef _KERNEL
#ifdef SYSCTL_DECL
SYSCTL_DECL(_net_inet_tcp);
#endif
#define TCP_DO_SACK(tp) ((tp)->t_flags & TF_SACK_PERMITTED)
#define TCP_DO_NCR(tp) (((tp)->t_flags & TF_NCR) && TCP_DO_SACK((tp)))
#define TCP_SACK_BLKEND(len, thflags) \
((len) + (((thflags) & TH_FIN) != 0))
struct tcpcbackq {
TAILQ_HEAD(, tcpcb) head;
} __cachealign;
extern struct inpcbinfo tcbinfo[];
extern struct tcpcbackq tcpcbackq[];
extern int tcp_mssdflt;
extern int tcp_minmss;
extern int tcp_delack_enabled;
extern int path_mtu_discovery;
struct ip;
union netmsg;
int tcp_addrcpu(in_addr_t faddr, in_port_t fport,
in_addr_t laddr, in_port_t lport);
int tcp_addrhash(in_addr_t faddr, in_port_t fport,
in_addr_t laddr, in_port_t lport);
struct lwkt_port *
tcp_addrport(in_addr_t faddr, in_port_t fport,
in_addr_t laddr, in_port_t lport);
struct lwkt_port *tcp_addrport0(void);
void tcp_canceltimers (struct tcpcb *);
struct tcpcb *
tcp_close (struct tcpcb *);
void tcp_ctlinput(union netmsg *);
void tcp_ctloutput(union netmsg *);
struct netmsg_pr_ctloutput *tcp_ctloutmsg(struct sockopt *);
inp_notify_t tcp_get_inpnotify(int cmd, const struct sockaddr *sa,
int *arg, struct ip **ip0, int *cpuid);
struct tcpcb *
tcp_drop (struct tcpcb *, int);
void tcp_drain (void);
void tcp_init (void);
void tcp_thread_init (void);
int tcp_input (struct mbuf **, int *, int);
void tcp_rmx_init (struct tcpcb *, int);
int tcp_mssopt (struct tcpcb *);
void tcp_drop_syn_sent (struct inpcb *, int);
void tcp_mtudisc (struct inpcb *, int);
void tcp_newtcpcb (struct inpcb *);
int tcp_output(struct tcpcb *);
int tcp_output_fair(struct tcpcb *);
void tcp_output_init(struct tcpcb *);
void tcp_output_cancel(struct tcpcb *);
boolean_t
tcp_output_pending(struct tcpcb *);
void tcp_quench (struct inpcb *, int);
void tcp_respond (struct tcpcb *, void *,
struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int);
struct rtentry *
tcp_rtlookup (struct in_conninfo *);
int tcp_sack_bytes_below(const struct scoreboard *scb, tcp_seq seq);
void tcp_sack_destroy(struct scoreboard *scb);
void tcp_sack_discard(struct tcpcb *tp);
void tcp_sack_report_cleanup(struct tcpcb *tp);
boolean_t
tcp_sack_report_needed(const struct tcpcb *tp);
int tcp_sack_ndsack_blocks(const struct raw_sackblock *blocks,
const int numblocks, tcp_seq snd_una);
void tcp_sack_fill_report(struct tcpcb *tp, u_char *opt, u_int *plen);
boolean_t
tcp_sack_has_sacked(const struct scoreboard *scb, u_int amount);
void tcp_sack_tcpcb_init(struct tcpcb *tp);
uint32_t tcp_sack_compute_pipe(const struct tcpcb *tp);
boolean_t
tcp_sack_nextseg(struct tcpcb *tp, tcp_seq *nextrexmt, uint32_t *len,
boolean_t *rescue);
boolean_t
tcp_sack_islost(const struct scoreboard *scb, tcp_seq seq);
void tcp_sack_update_lostseq(struct scoreboard *scb, tcp_seq snd_una,
u_int maxseg, int rxtthresh);
#ifdef later
void tcp_sack_revert_scoreboard(struct scoreboard *scb, tcp_seq snd_una,
u_int maxseg);
void tcp_sack_save_scoreboard(struct scoreboard *scb);
#endif
void tcp_sack_skip_sacked(struct scoreboard *scb, tcp_seq *prexmt);
uint32_t tcp_sack_first_unsacked_len(const struct tcpcb *tp);
void tcp_sack_update_scoreboard(struct tcpcb *tp, struct tcpopt *to);
void tcp_save_congestion_state(struct tcpcb *tp);
void tcp_revert_congestion_state(struct tcpcb *tp);
void tcp_setpersist (struct tcpcb *);
struct tcptemp *tcp_maketemplate (struct tcpcb *);
void tcp_freetemplate (struct tcptemp *);
void tcp_fillheaders (struct tcpcb *, void *, void *, boolean_t);
struct lwkt_port *
tcp_soport(struct socket *, struct sockaddr *, struct mbuf **);
struct lwkt_port *
tcp_ctlport(int, struct sockaddr *, void *, int *);
struct lwkt_port *
tcp_initport(void);
struct tcpcb *
tcp_timers (struct tcpcb *, int);
void tcp_trace (short, short, struct tcpcb *, void *, struct tcphdr *,
int);
void tcp_xmit_bandwidth_limit(struct tcpcb *tp, tcp_seq ack_seq);
u_long tcp_initial_window(struct tcpcb *tp);
void tcp_timer_keep_activity(struct tcpcb *tp, int thflags);
void syncache_init(void);
void syncache_unreach(struct in_conninfo *, const struct tcphdr *);
int syncache_expand(struct in_conninfo *, struct tcphdr *,
struct socket **, struct mbuf *);
int syncache_add(struct in_conninfo *, struct tcpopt *,
struct tcphdr *, struct socket *, struct mbuf *);
void syncache_chkrst(struct in_conninfo *, struct tcphdr *);
void syncache_badack(struct in_conninfo *);
void syncache_destroy(struct tcpcb *tp, struct tcpcb *new_tp);
#ifdef TCP_SIGNATURE
int tcpsignature_apply(void *fstate, void *data, unsigned int len);
int tcpsignature_compute(struct mbuf *m, int len, int tcpoptlen,
u_char *buf, u_int direction);
#endif
extern struct pr_usrreqs tcp_usrreqs;
extern u_long tcp_sendspace;
extern u_long tcp_recvspace;
tcp_seq tcp_new_isn (struct tcpcb *);
void tcp_pcbport_create(struct tcpcb *);
void tcp_pcbport_destroy(struct tcpcb *);
void tcp_pcbport_merge_oncpu(struct tcpcb *);
static __inline void
tcp_pcbport_insert(struct tcpcb *ltp, struct inpcb *inp)
{
struct inpcbport *phd;
int cpu;
if (inp->inp_lport != ltp->t_inpcb->inp_lport) {
in_pcbinsporthash_lport(inp);
return;
}
cpu = mycpuid;
KASSERT(cpu < netisr_ncpus, ("invalid cpu%d", cpu));
phd = <p->t_pcbport[cpu].t_phd;
inp->inp_porthash = NULL;
inp->inp_phd = phd;
LIST_INSERT_HEAD(&phd->phd_pcblist, inp, inp_portlist);
}
static __inline void
tcp_pcbport_remove(struct inpcb *inp)
{
if (inp->inp_porthash == NULL && inp->inp_phd != NULL) {
LIST_REMOVE(inp, inp_portlist);
inp->inp_phd = NULL;
}
}
static __inline void
_TCP_STATE_INC(const struct tcpcb *tp)
{
tcpstate_count[mycpuid].tcps_count[tp->t_state]++;
}
static __inline void
_TCP_STATE_DEC(const struct tcpcb *tp)
{
tcpstate_count[mycpuid].tcps_count[tp->t_state]--;
}
static __inline void
_TCP_STATE_SET(struct tcpcb *tp, int state)
{
tp->t_state = state;
_TCP_STATE_INC(tp);
}
static __inline void
TCP_STATE_INIT(struct tcpcb *tp)
{
_TCP_STATE_SET(tp, TCPS_CLOSED);
}
static __inline void
TCP_STATE_TERM(struct tcpcb *tp)
{
KASSERT(tp->t_state != TCPS_TERMINATING, ("tcpcb was terminated"));
_TCP_STATE_DEC(tp);
tp->t_state = TCPS_TERMINATING;
}
static __inline void
TCP_STATE_CHANGE(struct tcpcb *tp, int state)
{
_TCP_STATE_DEC(tp);
_TCP_STATE_SET(tp, state);
}
static __inline void
TCP_STATE_MIGRATE_START(const struct tcpcb *tp)
{
_TCP_STATE_DEC(tp);
}
static __inline void
TCP_STATE_MIGRATE_END(const struct tcpcb *tp)
{
_TCP_STATE_INC(tp);
}
#endif
#endif