xref: /original-bsd/sys/deprecated/bbnnet/rdp.h (revision 6fcea464)
1 /*
2  $Log:	rdp.h,v $
3  * Revision 2.13  85/06/18  14:33:36  walsh
4  * added extern decl.
5  *
6  * Revision 2.12  84/11/29  12:50:15  walsh
7  * changed references to currentrtt into references to srtt, a better
8  * and less misleading mnemonic.
9  *
10  * Revision 2.11  84/11/15  09:55:15  walsh
11  * redid how we deal with compiler padding in the RDP header structure.
12  *
13  * Revision 2.10  84/11/08  16:09:21  walsh
14  * Added code to gather statistics on RDP traffic.  This makes the RDPCB
15  * too big unles you make mbufs 512 bytes large.  RDP_CS should be turned off
16  * unless you do.
17  *
18  * Revision 2.9  84/11/06  15:24:02  walsh
19  * *** empty log message ***
20  *
21  * Revision 2.8  84/11/06  14:29:44  walsh
22  * intorduced RDP_HLSHIFT
23  *
24  * Revision 2.7  84/11/05  12:42:04  walsh
25  * Set things up so can debug RDP connections just like can debug TCP
26  * connections.
27  *
28  * Revision 2.6  84/11/05  11:14:03  walsh
29  * *** empty log message ***
30  *
31  * Revision 2.5  84/11/05  11:03:55  walsh
32  * comment and adjust number for rdp_iss in a mathematically correct way
33  * as a result of benchmarks (cf. operationally correct).
34  *
35  * Revision 2.4  84/11/02  18:21:13  walsh
36  * Protocol specifiers want NULL message to have own sequence number in
37  * case of slow (t>NULL msg timeout) packets.  I don't see this as a problem,
38  * and even if happened (dubious) would only delay discovery, but I
39  * didn't win this one.  Initially not designed for this, but fixes are
40  * in almost neatly.
41  *
42  * Revision 2.3  84/11/02  15:26:42  walsh
43  * Allow for RDP header fields not on natural boundries.  (Protocol
44  * specifiers say will be part of next version in 6-12 months).
45  * Until then, there goes the speed...  Yucho modifications.
46  *
47  * Revision 2.2  84/11/02  13:12:29  walsh
48  * use rdp typedefs for packet header fields to reduce lint errors.
49  *
50  * Revision 2.1  84/11/02  10:10:49  walsh
51  * Fixed to include RCS comments in checked out source.
52  *
53 
54  * description:
55  * Reliable Datagram Protocol definitions.
56  *
57  * revision 1.10
58  * date: 84/07/25 09:45:36;  author: walsh;  state: Exp;  lines added/del: 1/1
59  * RDP finally has an official protocol number assigned by Postel.
60  *
61  * revision 1.9
62  * date: 84/07/19 10:20:37;  author: walsh;  state: Exp;  lines added/del: 1/31
63  * Organized macros and classified their definitions in rdp_macros.h.
64  *
65  * revision 1.8
66  * date: 84/07/18 18:49:39;  author: walsh;  state: Exp;  lines added/del: 7/1
67  * Added provision for sending of NULL messages.  These are sent on an idle
68  * connection to determine that the other side still exists.
69  *
70  * revision 1.7
71  * date: 84/07/18 13:51:54;  author: walsh;  state: Exp;  lines added/del: 1/0
72  * constant RDP_MAXTIMERVAL to go with type rdptimerval.
73  *
74  * revision 1.6
75  * date: 84/07/18 13:27:06;  author: walsh;  state: Exp;  lines added/del: 11/4
76  * Bouncing datagrams off goonhilly-echo eventually causes RTTL timeout.  So,
77  * have re-worked:
78  * 	1.  rxtime = 1.5 srtt, not factor of 2 used before
79  * 	2.  max rxtime now 20 sec, not 30 seconds
80  * 	3.  provisions for user definition of RTTL period.
81  *
82  * revision 1.5
83  * date: 84/07/12 13:44:12;  author: walsh;  state: Exp;  lines added/del: 26/19
84  * Rather than in-line stuffing of IP/RDP headers, at least half of which are
85  * constant, copy headers in from a template of what the headers are like.  The
86  * bcopy() call is turned into a movc3 instruction on the VAX by a sed script
87  * run over the assembler output of the C compiler.  Marginal speed-up.
88  *
89  * revision 1.4
90  * date: 84/07/10 14:42:34;  author: walsh;  state: Exp;  lines added/del: 20/23
91  * simplified check for if debugging on in RDP_ACTION, since rdpcb, inpcb,
92  * and socket structure all last equally as long.
93  *
94  * revision 1.3
95  * date: 84/07/09 14:23:00;  author: walsh;  state: Exp;  lines added/del: 2/1
96  * Added ACK-delay timer.
97  *
98  * revision 1.2
99  * date: 84/07/06 09:46:45;  author: walsh;  state: Exp;  lines added/del: 36/1
100  * This version seems to run bug-free.
101  *
102  * revision 1.1
103  * date: 84/06/26 14:16:27;  author: walsh;  state: Exp;
104  * Initial revision
105  *
106  */
107 
108 
109 /*
110  * Here's how I've tried to name things to keep them consistent.
111  * For RDP_?..., the ? means:
112  *
113  *	f	flag (in packet header)
114  *	i	input event
115  *	o	option (in syn packet header)
116  *	p	port number
117  *	s	state (of connection in rdpcb)
118  *	t	timer
119  *	tv	timer value
120  */
121 
122 typedef char	boolean;
123 typedef u_char	rdpstate;
124 typedef u_long	rdpsequence;	/* sequence # or ack # */
125 typedef u_long	rdpchecksum;
126 typedef u_char	rdptimerval;
127 #define RDP_MAXTIMERVAL	255
128 typedef u_char	rdpportnum;
129 
130 typedef struct inpcb	INPCB;	/* belongs in in_pcb.h */
131 typedef struct mbuf	MBUF;	/* belongs in mbuf.h */
132 
133 
134 typedef struct rdphdr {
135 	char		rh_ver:2,	/* version of packet header */
136 	        	rh_flags:6;
137 	u_char		rh_hdrlen;	/* in units of 2 bytes */
138 	rdpportnum	rh_sport;	/* source port */
139 	rdpportnum	rh_dport;	/* destination port */
140 	u_short		rh_dlen;	/* amount of data following the header */
141 	rdpsequence	rh_seqno;
142 	rdpsequence	rh_ackno;	/* valid iff ACK set */
143 	rdpchecksum	rh_cksum;
144 } RDPHDR;
145 
146 #define RDP_VERSION	1		/* rh_ver */
147 
148 #define RDP_fNULL	0x02		/* rh_flags */
149 #define RDP_fRST	0x04
150 #define RDP_fEACK	0x08
151 #define RDP_fACK	0x10
152 #define RDP_fSYN	0x20
153 
154 #define RDP_HLSHIFT 1	/* Header Length SHIFT */
155 #define hdrlen(x) ((x)->rh_hdrlen << RDP_HLSHIFT)
156 
157 /*
158  * RDP port numbers 1-63 for servers, 64-255 assigned to clients
159  */
160 
161 #define RDP_pANY		  0
162 #define RDP_RESERVED		 63
163 #define RDP_USERRESERVED	 63
164 #define RDP_MAXPORT		255
165 
166 /*
167  * Due to the compiler aligning header fields on natural boundries,
168  * the rdp header is 18 bytes on the network, but sizeof(RDPHDR) = 20
169  * So, skip sizeof and define macros to access fields after the gap.
170  */
171 #define RDPHDRSZ	18	/* on the network */
172 
173 #define RDP_SEQNO(pkt)		(* ((u_long *) (&((char *) (pkt))[6])))
174 #define RDP_ACKNO(pkt)		(* ((u_long *) (&((char *) (pkt))[10])))
175 #define RDP_CKSUM(pkt)		(* ((u_long *) (&((char *) (pkt))[14])))
176 #define RDP_OPT(pkt, type)	((type) (&((char *) (pkt))[RDPHDRSZ]))
177 
178 /*
179  * In a SYN packet, this will immediately follow the rdphdr
180  */
181 typedef struct synoptions {
182 	short	rh_nbuf;	/* # dgrams he can buffer */
183 	u_short	rh_maxlen;	/* max length of a dgram */
184 	short	rh_options;
185 #define RDP_oSEQUENTIAL	1
186 } SYNOPTIONS;
187 
188 /*
189  * For an established connection, a variable length array of these
190  * may immediately follow the rdphdr
191  */
192 typedef struct eackoptions {
193 	rdpsequence	rh_eackno;
194 } EACKOPTIONS;
195 
196 
197 
198 /*
199  * RDP connection states
200  */
201 #define RDP_sSAME	0	/* no state transition for this input to fsm */
202 #define RDP_sUNOPENED	1	/* after socket(2), before listen or connect */
203 #define RDP_sLISTEN	2	/* after listen(2) */
204 #define RDP_sSYNSENT	3	/* after connect(2) */
205 #define RDP_sLSYNRCVD	4	/* child socket after SYN gets to LISTENer */
206 #define RDP_sSYNRCVD	5	/* after SYN gets to SYNSENT */
207 #define RDP_sESTAB	6	/* after get both SYN and ACK */
208 #define RDP_sCLOSEWAIT	7	/* after send or receive RST */
209 #define RDP_sCLOSED	8	/* after CLOSEWAIT timeout */
210 
211 #define RDP_NSTATES	9
212 
213 /*
214  * Inputs that (possibly) cause state transition
215  */
216 #define RDP_iCONNECT	0	/* user connect(2) request == active open */
217 #define RDP_iLISTEN	1	/* user listen(2) request == passive open */
218 #define RDP_iNETR	2	/* network reception of packet */
219 #define RDP_iUCLOSE	3	/* user close(2) request */
220 #define RDP_iTIMER	4	/* a timer went off */
221 #define RDP_iRCV	5	/* user has picked up a packet */
222 #define RDP_iSEND	6	/* user send request */
223 #define RDP_NINPUTS	7
224 
225 
226 
227 /*
228  * rq_maxqlen = MIN(desired, RDP_MAXDGRAMS)
229  */
230 #define RDP_MAXDGRAMS	40
231 
232 /*
233  * In rq_msgs, pointers follow:
234  *	sendq:: NULL x PRU_SEND ->
235  *		ptr x (E)ACK ->
236  *		RDP_DELIVERED x move front -> NULL
237  *
238  *	rcvq::	NULL x net reception ->
239  *		ptr x pass to user ->
240  *		RDP_DELIVERED x (PRU_RECV + move front) -> NULL
241  *
242  *		on last transition, we also (E)ACK the packet.
243  */
244 #define RDP_DELIVERED	((struct mbuf *) (-1))
245 #define RDP_NULLMSG	((struct mbuf *) (-2))
246 
247 /*
248  * rq_msgs points into an mbuf that we use for an array of pointers to
249  * mbuf chains.  On input, each mbuf chain holds an RDP packet (header and
250  * data).  On output, each mbuf chain holds the data portion of the packet
251  * in case it is needed for re-transmission.
252  *			+---------------+
253  *	rq_msgs -->	|		|
254  *			|   o-----------|---> mbuf chain (== packet or data)
255  *			| RDP_DELIVERED	|
256  *			| RDP_NULLMSG	|
257  *			|		|
258  *			+---------------+
259  *			array in mbuf
260  */
261 typedef struct rdp_msgq {
262 	int		 rq_maxqlen;	/* 1...RDP_MAXDGRAMS inclusive */
263 	int		 rq_maxiplen;	/* max IP length of dgram can put on q*/
264 	int		 rq_front;	/* 0...(rq_maxqlen-1) inclusive */
265 	rdpsequence	 rq_baseseq;	/* RDP seq # of rq_msgs[rq_front] */
266 	MBUF	       **rq_msgs;	/* -> into mbuf holding array of ptrs*/
267 } RDP_MSGQ;
268 
269 
270 typedef struct rdpcb {
271 	struct inpcb	*r_inpcb;
272 
273 	rdpstate	 r_state;	/* state of connection */
274 	rdpsequence	 r_iss;		/* initial sequence # sent (in SYN) */
275 	rdpsequence	 r_irs;		/* initial sequence # rcvd (in SYN) */
276 	rdpsequence	 r_sndnxt;	/* seq # for next datagram we send */
277 
278 	struct rdp_msgq	r_sendq, r_rcvq;
279 
280 #define r_hisnbuf r_sendq.rq_maxqlen	/* # RDP messages he can buffer */
281 #define r_hismaxlen r_sendq.rq_maxiplen /* biggest IP datagram he'll take */
282 #define r_snduna r_sendq.rq_baseseq	/* seq # of oldest unacked dgram sent */
283 #define r_ournbuf r_rcvq.rq_maxqlen	/* # RDP messages we can buffer */
284 #define r_ourmaxlen r_rcvq.rq_maxiplen  /* biggest RDP data length we'll take */
285 
286 	boolean		 r_synrcvd;	/* have we rcvd his SYN? */
287 	boolean		 r_synacked;	/* has he ACKed our SYN? */
288 	boolean		 r_usrclosed;	/* has user process close(2)ed yet? */
289 	boolean		 r_sendrst;	/* set reset in outgoing packet */
290 	boolean		 r_sendnull;	/* set null in outgoing packet */
291 	boolean		 r_sequential;	/* sequential delivery? */
292 	boolean		 r_rttiming;	/* are we measuring rtt? */
293 
294 	rdptimerval	 r_closewait;	/* # 0.5 sec units before destroy *cb */
295 #define RDP_tvCLOSEWAIT	120		/* default idea of CLOSEWAIT timer */
296 	rdptimerval	 r_rttl;	/* error if dgram unacked in this time*/
297 #define RDP_tvRTTL	120		/* default idea of RTTL timer */
298 	rdptimerval	 r_tvnull;	/* for testing connection existence */
299 #define RDP_tvNULL	240		/* default idea time to 1st NULL */
300 	char		 r_nullsent;	/* # successive null messages sent */
301 #define RDP_MAXNULL	  5
302 
303 	/*
304 	 * For now, each retransmission of a packet will take the same
305 	 * amount of time.
306 	 */
307 	rdptimerval	 r_rxmitime;	/* current idea of re-xmission time */
308 #define RDP_tvRXMAX	40		/* max value of re-xmit timer (20 sec)*/
309 #define RDP_tvRXMIN	 4		/* min value of re-xmit timer ( 2 sec)*/
310 	/*
311 	 * (3 * (RDP_tvRXMIN = 4)) / 2 = 6
312 	 * So, allows AT LEAST one second of variance from srtt until
313 	 * hits RDP_tvRXMAX ceiling.
314 	 */
315 #define update_rxmitime(r) \
316   (r)->r_rxmitime = MAX(RDP_tvRXMIN, \
317 			MIN(RDP_tvRXMAX, (3 * (r)->r_srtt) / 2));
318 
319 	/*
320 	 * if we're measuring the round trip time, (r_rttiming == TRUE),
321 	 * then r_rtt counts time til get ack of dgram # r_rttimed.
322 	 * r_rtt starts at 0 when send packet # r_rttimed, and is incremented
323 	 * each 0.5 second.  r_srtt is updated when r_rttimed is acked.
324 	 * At that time, r_rxmitime should also be updated.  srtt represents
325 	 * a weighted average of the recent round trip times.
326 	 */
327 	rdpsequence	 r_rttimed;	/* seq # of dgram finding rtt for */
328 	rdptimerval	 r_rtt;		/* round trip time (in 0.5 sec units)*/
329 	rdptimerval	 r_srtt;	/* smoothed round trip time */
330 #define ALPHA	4
331 #define BETA	1
332 #ifdef RDP_CS
333 #define update_rttestimate(r) \
334   { \
335   (r)->r_srtt = (ALPHA*(r)->r_srtt + BETA*(r)->r_rtt) / (ALPHA+BETA) \
336   (r)->r_nrtt ++;					\
337   (r)->r_totalrtt += (r)->r_rtt;			\
338   if ((r)->r_nrtt == 1)					\
339 	(r)->r_minrtt = (r)->r_maxrtt = (r)->r_rtt;	\
340   else if ((r)->r_rtt < (r)->r_minrtt)			\
341 	(r)->r_minrtt = (r)->r_rtt;			\
342   else if ((r)->r_rtt > (r)->r_maxrtt)			\
343 	(r)->r_maxrtt = (r)->r_rtt;			\
344   }
345 #else
346 #define update_rttestimate(r) \
347   (r)->r_srtt = (ALPHA*(r)->r_srtt + BETA*(r)->r_rtt) / (ALPHA+BETA)
348 #endif
349 
350 	/*
351 	 * if we have at least one packet being timed for re-transmission,
352 	 * then we have a "retransmit took too long" timer also set.  One such
353 	 * timer suffices.  This timer is associated with rxtimers[rttlindex]
354 	 * and r_sendq.rq_msgs[rttlindex]
355 	 */
356 	int		 r_rttlindex;
357 
358 #define RDP_tCLOSEWAIT	0
359 #define RDP_tRTTL	1	/* retransmit took too long (not in spec) */
360 #define RDP_tRXMIT	2	/* if set, check rxtimers */
361 #define RDP_tACKDELAY	3
362 #define RDP_tNULL	4
363 #define RDP_NTIMERS	5
364 	rdptimerval	 r_timers[RDP_NTIMERS];
365 
366 	/*
367 	 * The re-transmission timer array is parallel to r_sendq.rq_msgs
368 	 */
369 	rdptimerval	 r_rxtimers[RDP_MAXDGRAMS]; /* send retransmit timers */
370 #define RDP_tvRXCHECK	1	/* check per-pkt rxmit timers every 0.5 sec   */
371 
372 	/*
373 	 * and for a (minor) speedup, just byte copy the constant header fields
374 	 */
375 #define RDP_TEMPLSIZE	(sizeof(struct ip) + RDPHDRSZ)
376 	char		 r_template[RDP_TEMPLSIZE];
377 
378 #ifdef RDP_CS
379 	rdptimerval	r_minrtt;	/* minimum rtt observed */
380 	rdptimerval	r_maxrtt;	/* maximum rtt observed */
381 	int		r_totalrtt;	/* total of all rtt packets */
382 	int		r_nrtt;		/* # rtt packets measured */
383 
384 	u_long		r_entered[RDP_NSTATES]; /* .001 sec */
385 
386 	struct {
387 		int	r_total;
388 		int	r_nullpkts;
389 		int	r_synpkts;
390 		int	r_rstpkts;
391 		int	r_retrans;
392 		int	r_nbytes;	/* to/from user */
393 	} r_sent, r_rcvd;
394 #endif
395 } RDPCB;
396 
397 #define rdpcbtoso(r)	((r)->r_inpcb->inp_socket)
398 
399 /*
400  * RDP desires control over the IP length.  We really only have good
401  * control on the RDP data length in the UNIX socket code.  Use the following
402  * as the difference between the two.
403  *
404  * Allow how much space for eacks?
405  * (Don't care on input.  Can drop eack options on output.)
406  */
407 #define HDRSLOP (RDPHDRSZ + sizeof(struct ip))
408 
409 /*
410  * Active opens (connect) and children of listener can time out via RDP_tRTTL.
411  * Is a timeout for passive opens (LISTEN state) desireable?  Prob not
412  * since user can always use alarm(2) system call.
413  */
414 
415 
416 
417 typedef struct r_debug {
418 	u_long		rd_iptime;	/* 0.001 second units */
419 	int		rd_input;
420 	rdpstate	rd_newstate;
421 	RDPCB		rd_rdpcb;
422 
423 	int		rd_timer;	/* iff input == RDP_iTIMER */
424 	struct ip	rd_iphdr;	/* iff input == RDP_iNETR */
425 	RDPHDR		rd_rdphdr;	/* iff input == RDP_iNETR */
426 } R_DEBUG;
427 
428 #define RCDBLEN ((CLBYTES/sizeof(R_DEBUG)) * sizeof(R_DEBUG))
429 #define RDBLEN	((MLEN   /sizeof(R_DEBUG)) * sizeof(R_DEBUG))
430 
431 #define inptordpcb(i)	((RDPCB *) ((i)->inp_ppcb))
432 
433 struct rdp_stat {
434 	struct in_stat r_in;
435 #define r_total		r_in.in_total
436 #define r_badsum	r_in.in_badsum
437 #define r_tooshort	r_in.in_tooshort
438 #define r_drops		r_in.in_drops
439 };
440 
441 
442 #ifdef KERNEL
443 /*
444  * Each host chooses the starting point of the packet numbering for a
445  * connection so that datagrams from different incarnations of a
446  * connection have no sequence numbers in common.  SYN packets are used
447  * by each side to make the other aware of the starting point.  If we
448  * can send N packets per slow timeout, then if we update rdp_iss
449  * by RDP_ISSINCR > N every slow timeout (one connection bangs away
450  * all timeout period) and by RDP_ISSINCR every time we make a connection
451  * (many incarnations of same connection per timeout period), then we're
452  * o.k.
453  */
454 extern rdpsequence rdp_iss;
455 
456 /* vax can send 180 packets/second */
457 #define RDP_ISSINCR ((200/PR_SLOWHZ) +1)
458 
459 extern struct dfilter rdp_dfilter;
460 extern struct inpcb rdp;
461 extern struct rdp_stat rdpstat;
462 extern rdp_pcbdisconnect();
463 extern struct mbuf *rdp_qremove();
464 extern rdpchecksum rdp_cksum();
465 extern char *rdp_conn_used();
466 
467 #define rdp_action(input, rdpcb, arg) rdpaction(input, rdpcb, (int) arg)
468 
469 
470 /*
471  * RDP finite state machine
472  */
473 #ifdef RDPDEBUG
474 extern char	*rdpstates[RDP_NSTATES];	/* rdpstate -> string */
475 extern char	*rdpinputs[RDP_NINPUTS];
476 extern char	*rdptimers[RDP_NTIMERS];
477 #endif
478 extern int	(*rdp_action_table[RDP_NSTATES][RDP_NINPUTS])();
479 #endif
480