fixes for range locking
[unix-history] / usr / src / sys / deprecated / bbnnet / rdp.h
/*
$Log: rdp.h,v $
* Revision 2.13 85/06/18 14:33:36 walsh
* added extern decl.
*
* Revision 2.12 84/11/29 12:50:15 walsh
* changed references to currentrtt into references to srtt, a better
* and less misleading mnemonic.
*
* Revision 2.11 84/11/15 09:55:15 walsh
* redid how we deal with compiler padding in the RDP header structure.
*
* Revision 2.10 84/11/08 16:09:21 walsh
* Added code to gather statistics on RDP traffic. This makes the RDPCB
* too big unles you make mbufs 512 bytes large. RDP_CS should be turned off
* unless you do.
*
* Revision 2.9 84/11/06 15:24:02 walsh
* *** empty log message ***
*
* Revision 2.8 84/11/06 14:29:44 walsh
* intorduced RDP_HLSHIFT
*
* Revision 2.7 84/11/05 12:42:04 walsh
* Set things up so can debug RDP connections just like can debug TCP
* connections.
*
* Revision 2.6 84/11/05 11:14:03 walsh
* *** empty log message ***
*
* Revision 2.5 84/11/05 11:03:55 walsh
* comment and adjust number for rdp_iss in a mathematically correct way
* as a result of benchmarks (cf. operationally correct).
*
* Revision 2.4 84/11/02 18:21:13 walsh
* Protocol specifiers want NULL message to have own sequence number in
* case of slow (t>NULL msg timeout) packets. I don't see this as a problem,
* and even if happened (dubious) would only delay discovery, but I
* didn't win this one. Initially not designed for this, but fixes are
* in almost neatly.
*
* Revision 2.3 84/11/02 15:26:42 walsh
* Allow for RDP header fields not on natural boundries. (Protocol
* specifiers say will be part of next version in 6-12 months).
* Until then, there goes the speed... Yucho modifications.
*
* Revision 2.2 84/11/02 13:12:29 walsh
* use rdp typedefs for packet header fields to reduce lint errors.
*
* Revision 2.1 84/11/02 10:10:49 walsh
* Fixed to include RCS comments in checked out source.
*
* description:
* Reliable Datagram Protocol definitions.
*
* revision 1.10
* date: 84/07/25 09:45:36; author: walsh; state: Exp; lines added/del: 1/1
* RDP finally has an official protocol number assigned by Postel.
*
* revision 1.9
* date: 84/07/19 10:20:37; author: walsh; state: Exp; lines added/del: 1/31
* Organized macros and classified their definitions in rdp_macros.h.
*
* revision 1.8
* date: 84/07/18 18:49:39; author: walsh; state: Exp; lines added/del: 7/1
* Added provision for sending of NULL messages. These are sent on an idle
* connection to determine that the other side still exists.
*
* revision 1.7
* date: 84/07/18 13:51:54; author: walsh; state: Exp; lines added/del: 1/0
* constant RDP_MAXTIMERVAL to go with type rdptimerval.
*
* revision 1.6
* date: 84/07/18 13:27:06; author: walsh; state: Exp; lines added/del: 11/4
* Bouncing datagrams off goonhilly-echo eventually causes RTTL timeout. So,
* have re-worked:
* 1. rxtime = 1.5 srtt, not factor of 2 used before
* 2. max rxtime now 20 sec, not 30 seconds
* 3. provisions for user definition of RTTL period.
*
* revision 1.5
* date: 84/07/12 13:44:12; author: walsh; state: Exp; lines added/del: 26/19
* Rather than in-line stuffing of IP/RDP headers, at least half of which are
* constant, copy headers in from a template of what the headers are like. The
* bcopy() call is turned into a movc3 instruction on the VAX by a sed script
* run over the assembler output of the C compiler. Marginal speed-up.
*
* revision 1.4
* date: 84/07/10 14:42:34; author: walsh; state: Exp; lines added/del: 20/23
* simplified check for if debugging on in RDP_ACTION, since rdpcb, inpcb,
* and socket structure all last equally as long.
*
* revision 1.3
* date: 84/07/09 14:23:00; author: walsh; state: Exp; lines added/del: 2/1
* Added ACK-delay timer.
*
* revision 1.2
* date: 84/07/06 09:46:45; author: walsh; state: Exp; lines added/del: 36/1
* This version seems to run bug-free.
*
* revision 1.1
* date: 84/06/26 14:16:27; author: walsh; state: Exp;
* Initial revision
*
*/
/*
* Here's how I've tried to name things to keep them consistent.
* For RDP_?..., the ? means:
*
* f flag (in packet header)
* i input event
* o option (in syn packet header)
* p port number
* s state (of connection in rdpcb)
* t timer
* tv timer value
*/
typedef char boolean;
typedef u_char rdpstate;
typedef u_long rdpsequence; /* sequence # or ack # */
typedef u_long rdpchecksum;
typedef u_char rdptimerval;
#define RDP_MAXTIMERVAL 255
typedef u_char rdpportnum;
typedef struct inpcb INPCB; /* belongs in in_pcb.h */
typedef struct mbuf MBUF; /* belongs in mbuf.h */
typedef struct rdphdr {
char rh_ver:2, /* version of packet header */
rh_flags:6;
u_char rh_hdrlen; /* in units of 2 bytes */
rdpportnum rh_sport; /* source port */
rdpportnum rh_dport; /* destination port */
u_short rh_dlen; /* amount of data following the header */
rdpsequence rh_seqno;
rdpsequence rh_ackno; /* valid iff ACK set */
rdpchecksum rh_cksum;
} RDPHDR;
#define RDP_VERSION 1 /* rh_ver */
#define RDP_fNULL 0x02 /* rh_flags */
#define RDP_fRST 0x04
#define RDP_fEACK 0x08
#define RDP_fACK 0x10
#define RDP_fSYN 0x20
#define RDP_HLSHIFT 1 /* Header Length SHIFT */
#define hdrlen(x) ((x)->rh_hdrlen << RDP_HLSHIFT)
/*
* RDP port numbers 1-63 for servers, 64-255 assigned to clients
*/
#define RDP_pANY 0
#define RDP_RESERVED 63
#define RDP_USERRESERVED 63
#define RDP_MAXPORT 255
/*
* Due to the compiler aligning header fields on natural boundries,
* the rdp header is 18 bytes on the network, but sizeof(RDPHDR) = 20
* So, skip sizeof and define macros to access fields after the gap.
*/
#define RDPHDRSZ 18 /* on the network */
#define RDP_SEQNO(pkt) (* ((u_long *) (&((char *) (pkt))[6])))
#define RDP_ACKNO(pkt) (* ((u_long *) (&((char *) (pkt))[10])))
#define RDP_CKSUM(pkt) (* ((u_long *) (&((char *) (pkt))[14])))
#define RDP_OPT(pkt, type) ((type) (&((char *) (pkt))[RDPHDRSZ]))
/*
* In a SYN packet, this will immediately follow the rdphdr
*/
typedef struct synoptions {
short rh_nbuf; /* # dgrams he can buffer */
u_short rh_maxlen; /* max length of a dgram */
short rh_options;
#define RDP_oSEQUENTIAL 1
} SYNOPTIONS;
/*
* For an established connection, a variable length array of these
* may immediately follow the rdphdr
*/
typedef struct eackoptions {
rdpsequence rh_eackno;
} EACKOPTIONS;
/*
* RDP connection states
*/
#define RDP_sSAME 0 /* no state transition for this input to fsm */
#define RDP_sUNOPENED 1 /* after socket(2), before listen or connect */
#define RDP_sLISTEN 2 /* after listen(2) */
#define RDP_sSYNSENT 3 /* after connect(2) */
#define RDP_sLSYNRCVD 4 /* child socket after SYN gets to LISTENer */
#define RDP_sSYNRCVD 5 /* after SYN gets to SYNSENT */
#define RDP_sESTAB 6 /* after get both SYN and ACK */
#define RDP_sCLOSEWAIT 7 /* after send or receive RST */
#define RDP_sCLOSED 8 /* after CLOSEWAIT timeout */
#define RDP_NSTATES 9
/*
* Inputs that (possibly) cause state transition
*/
#define RDP_iCONNECT 0 /* user connect(2) request == active open */
#define RDP_iLISTEN 1 /* user listen(2) request == passive open */
#define RDP_iNETR 2 /* network reception of packet */
#define RDP_iUCLOSE 3 /* user close(2) request */
#define RDP_iTIMER 4 /* a timer went off */
#define RDP_iRCV 5 /* user has picked up a packet */
#define RDP_iSEND 6 /* user send request */
#define RDP_NINPUTS 7
/*
* rq_maxqlen = MIN(desired, RDP_MAXDGRAMS)
*/
#define RDP_MAXDGRAMS 40
/*
* In rq_msgs, pointers follow:
* sendq:: NULL x PRU_SEND ->
* ptr x (E)ACK ->
* RDP_DELIVERED x move front -> NULL
*
* rcvq:: NULL x net reception ->
* ptr x pass to user ->
* RDP_DELIVERED x (PRU_RECV + move front) -> NULL
*
* on last transition, we also (E)ACK the packet.
*/
#define RDP_DELIVERED ((struct mbuf *) (-1))
#define RDP_NULLMSG ((struct mbuf *) (-2))
/*
* rq_msgs points into an mbuf that we use for an array of pointers to
* mbuf chains. On input, each mbuf chain holds an RDP packet (header and
* data). On output, each mbuf chain holds the data portion of the packet
* in case it is needed for re-transmission.
* +---------------+
* rq_msgs --> | |
* | o-----------|---> mbuf chain (== packet or data)
* | RDP_DELIVERED |
* | RDP_NULLMSG |
* | |
* +---------------+
* array in mbuf
*/
typedef struct rdp_msgq {
int rq_maxqlen; /* 1...RDP_MAXDGRAMS inclusive */
int rq_maxiplen; /* max IP length of dgram can put on q*/
int rq_front; /* 0...(rq_maxqlen-1) inclusive */
rdpsequence rq_baseseq; /* RDP seq # of rq_msgs[rq_front] */
MBUF **rq_msgs; /* -> into mbuf holding array of ptrs*/
} RDP_MSGQ;
typedef struct rdpcb {
struct inpcb *r_inpcb;
rdpstate r_state; /* state of connection */
rdpsequence r_iss; /* initial sequence # sent (in SYN) */
rdpsequence r_irs; /* initial sequence # rcvd (in SYN) */
rdpsequence r_sndnxt; /* seq # for next datagram we send */
struct rdp_msgq r_sendq, r_rcvq;
#define r_hisnbuf r_sendq.rq_maxqlen /* # RDP messages he can buffer */
#define r_hismaxlen r_sendq.rq_maxiplen /* biggest IP datagram he'll take */
#define r_snduna r_sendq.rq_baseseq /* seq # of oldest unacked dgram sent */
#define r_ournbuf r_rcvq.rq_maxqlen /* # RDP messages we can buffer */
#define r_ourmaxlen r_rcvq.rq_maxiplen /* biggest RDP data length we'll take */
boolean r_synrcvd; /* have we rcvd his SYN? */
boolean r_synacked; /* has he ACKed our SYN? */
boolean r_usrclosed; /* has user process close(2)ed yet? */
boolean r_sendrst; /* set reset in outgoing packet */
boolean r_sendnull; /* set null in outgoing packet */
boolean r_sequential; /* sequential delivery? */
boolean r_rttiming; /* are we measuring rtt? */
rdptimerval r_closewait; /* # 0.5 sec units before destroy *cb */
#define RDP_tvCLOSEWAIT 120 /* default idea of CLOSEWAIT timer */
rdptimerval r_rttl; /* error if dgram unacked in this time*/
#define RDP_tvRTTL 120 /* default idea of RTTL timer */
rdptimerval r_tvnull; /* for testing connection existence */
#define RDP_tvNULL 240 /* default idea time to 1st NULL */
char r_nullsent; /* # successive null messages sent */
#define RDP_MAXNULL 5
/*
* For now, each retransmission of a packet will take the same
* amount of time.
*/
rdptimerval r_rxmitime; /* current idea of re-xmission time */
#define RDP_tvRXMAX 40 /* max value of re-xmit timer (20 sec)*/
#define RDP_tvRXMIN 4 /* min value of re-xmit timer ( 2 sec)*/
/*
* (3 * (RDP_tvRXMIN = 4)) / 2 = 6
* So, allows AT LEAST one second of variance from srtt until
* hits RDP_tvRXMAX ceiling.
*/
#define update_rxmitime(r) \
(r)->r_rxmitime = MAX(RDP_tvRXMIN, \
MIN(RDP_tvRXMAX, (3 * (r)->r_srtt) / 2));
/*
* if we're measuring the round trip time, (r_rttiming == TRUE),
* then r_rtt counts time til get ack of dgram # r_rttimed.
* r_rtt starts at 0 when send packet # r_rttimed, and is incremented
* each 0.5 second. r_srtt is updated when r_rttimed is acked.
* At that time, r_rxmitime should also be updated. srtt represents
* a weighted average of the recent round trip times.
*/
rdpsequence r_rttimed; /* seq # of dgram finding rtt for */
rdptimerval r_rtt; /* round trip time (in 0.5 sec units)*/
rdptimerval r_srtt; /* smoothed round trip time */
#define ALPHA 4
#define BETA 1
#ifdef RDP_CS
#define update_rttestimate(r) \
{ \
(r)->r_srtt = (ALPHA*(r)->r_srtt + BETA*(r)->r_rtt) / (ALPHA+BETA) \
(r)->r_nrtt ++; \
(r)->r_totalrtt += (r)->r_rtt; \
if ((r)->r_nrtt == 1) \
(r)->r_minrtt = (r)->r_maxrtt = (r)->r_rtt; \
else if ((r)->r_rtt < (r)->r_minrtt) \
(r)->r_minrtt = (r)->r_rtt; \
else if ((r)->r_rtt > (r)->r_maxrtt) \
(r)->r_maxrtt = (r)->r_rtt; \
}
#else
#define update_rttestimate(r) \
(r)->r_srtt = (ALPHA*(r)->r_srtt + BETA*(r)->r_rtt) / (ALPHA+BETA)
#endif
/*
* if we have at least one packet being timed for re-transmission,
* then we have a "retransmit took too long" timer also set. One such
* timer suffices. This timer is associated with rxtimers[rttlindex]
* and r_sendq.rq_msgs[rttlindex]
*/
int r_rttlindex;
#define RDP_tCLOSEWAIT 0
#define RDP_tRTTL 1 /* retransmit took too long (not in spec) */
#define RDP_tRXMIT 2 /* if set, check rxtimers */
#define RDP_tACKDELAY 3
#define RDP_tNULL 4
#define RDP_NTIMERS 5
rdptimerval r_timers[RDP_NTIMERS];
/*
* The re-transmission timer array is parallel to r_sendq.rq_msgs
*/
rdptimerval r_rxtimers[RDP_MAXDGRAMS]; /* send retransmit timers */
#define RDP_tvRXCHECK 1 /* check per-pkt rxmit timers every 0.5 sec */
/*
* and for a (minor) speedup, just byte copy the constant header fields
*/
#define RDP_TEMPLSIZE (sizeof(struct ip) + RDPHDRSZ)
char r_template[RDP_TEMPLSIZE];
#ifdef RDP_CS
rdptimerval r_minrtt; /* minimum rtt observed */
rdptimerval r_maxrtt; /* maximum rtt observed */
int r_totalrtt; /* total of all rtt packets */
int r_nrtt; /* # rtt packets measured */
u_long r_entered[RDP_NSTATES]; /* .001 sec */
struct {
int r_total;
int r_nullpkts;
int r_synpkts;
int r_rstpkts;
int r_retrans;
int r_nbytes; /* to/from user */
} r_sent, r_rcvd;
#endif
} RDPCB;
#define rdpcbtoso(r) ((r)->r_inpcb->inp_socket)
/*
* RDP desires control over the IP length. We really only have good
* control on the RDP data length in the UNIX socket code. Use the following
* as the difference between the two.
*
* Allow how much space for eacks?
* (Don't care on input. Can drop eack options on output.)
*/
#define HDRSLOP (RDPHDRSZ + sizeof(struct ip))
/*
* Active opens (connect) and children of listener can time out via RDP_tRTTL.
* Is a timeout for passive opens (LISTEN state) desireable? Prob not
* since user can always use alarm(2) system call.
*/
typedef struct r_debug {
u_long rd_iptime; /* 0.001 second units */
int rd_input;
rdpstate rd_newstate;
RDPCB rd_rdpcb;
int rd_timer; /* iff input == RDP_iTIMER */
struct ip rd_iphdr; /* iff input == RDP_iNETR */
RDPHDR rd_rdphdr; /* iff input == RDP_iNETR */
} R_DEBUG;
#define RCDBLEN ((CLBYTES/sizeof(R_DEBUG)) * sizeof(R_DEBUG))
#define RDBLEN ((MLEN /sizeof(R_DEBUG)) * sizeof(R_DEBUG))
#define inptordpcb(i) ((RDPCB *) ((i)->inp_ppcb))
struct rdp_stat {
struct in_stat r_in;
#define r_total r_in.in_total
#define r_badsum r_in.in_badsum
#define r_tooshort r_in.in_tooshort
#define r_drops r_in.in_drops
};
#ifdef KERNEL
/*
* Each host chooses the starting point of the packet numbering for a
* connection so that datagrams from different incarnations of a
* connection have no sequence numbers in common. SYN packets are used
* by each side to make the other aware of the starting point. If we
* can send N packets per slow timeout, then if we update rdp_iss
* by RDP_ISSINCR > N every slow timeout (one connection bangs away
* all timeout period) and by RDP_ISSINCR every time we make a connection
* (many incarnations of same connection per timeout period), then we're
* o.k.
*/
extern rdpsequence rdp_iss;
/* vax can send 180 packets/second */
#define RDP_ISSINCR ((200/PR_SLOWHZ) +1)
extern struct dfilter rdp_dfilter;
extern struct inpcb rdp;
extern struct rdp_stat rdpstat;
extern rdp_pcbdisconnect();
extern struct mbuf *rdp_qremove();
extern rdpchecksum rdp_cksum();
extern char *rdp_conn_used();
#define rdp_action(input, rdpcb, arg) rdpaction(input, rdpcb, (int) arg)
/*
* RDP finite state machine
*/
#ifdef RDPDEBUG
extern char *rdpstates[RDP_NSTATES]; /* rdpstate -> string */
extern char *rdpinputs[RDP_NINPUTS];
extern char *rdptimers[RDP_NTIMERS];
#endif
extern int (*rdp_action_table[RDP_NSTATES][RDP_NINPUTS])();
#endif