Commit | Line | Data |
---|---|---|
17efd7fe MK |
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 |