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