1 /* 2 $Log: rdp_subr.c,v $ 3 * Revision 2.7 84/11/21 12:06:30 walsh 4 * *** empty log message *** 5 * 6 * Revision 2.6 84/11/08 16:12:53 walsh 7 * Added code to gather statistics on RDP traffic. This makes the RDPCB 8 * too big unles you make mbufs 512 bytes large. RDP_CS should be turned off 9 * unless you do. 10 * 11 * Revision 2.5 84/11/06 13:54:21 walsh 12 * *** empty log message *** 13 * 14 * Revision 2.4 84/11/05 16:25:18 walsh 15 * tied rdp to icmp source quenches. See icmp_quench and rdp_quench. 16 * 17 * Revision 2.3 84/11/05 15:55:13 walsh 18 * update_nulltimer() macro began to look inappropriate with recent 19 * changes, so its been stripped out and put in-line. 20 * 21 * Revision 2.2 84/11/02 18:25:47 walsh 22 * Protocol specifiers want NULL message to have own sequence number in 23 * case of slow (t>NULL msg timeout) packets. I don't see this as a problem, 24 * and even if happened (dubious) would only delay discovery, but I 25 * didn't win this one. Initially not designed for this, but fixes are 26 * in almost neatly. 27 * 28 * Revision 2.1 84/11/02 10:15:35 walsh 29 * Fixed to include RCS comments in checked out source. 30 * 31 * 32 * description: 33 * Some subroutines for manipulating the datagram q's for RDP. 34 * 35 * revision 1.11 36 * date: 84/07/20 10:30:42; author: walsh; state: Exp; lines added/del: 21/1 37 * Tied RDP acknowledgements to ping reduction, just like TCP. 38 * 39 * revision 1.10 40 * date: 84/07/19 10:22:33; author: walsh; state: Exp; lines added/del: 1/17 41 * Organized macros and classified their definitions in rdp_macros.h. 42 * 43 * revision 1.9 44 * date: 84/07/17 22:35:26; author: walsh; state: Exp; lines added/del: 3/0 45 * Ensure cannot bind port number greater than RDP_pMAX. 46 * 47 * revision 1.8 48 * date: 84/07/12 10:12:48; author: walsh; state: Exp; lines added/del: 14/18 49 * some small optimizations. 50 * 51 * revision 1.7 52 * date: 84/07/12 09:39:06; author: walsh; state: Exp; lines added/del: 2/4 53 * small optimizations. ( a = (a+1)%b quicker than a++; a %= b) 54 * 55 * revision 1.6 56 * date: 84/07/10 14:58:24; author: walsh; state: Exp; lines added/del: 10/3 57 * Now no unecessary wakeups of the user process are done. 58 * 59 * revision 1.5 60 * date: 84/07/10 10:38:24; author: walsh; state: Exp; lines added/del: 13/13 61 * added register declarations. 62 * 63 * revision 1.4 64 * date: 84/07/06 14:28:53; author: wjacobso; state: Exp; lines added/del: 6/6 65 * *** empty log message *** 66 * 67 * revision 1.3 68 * date: 84/07/06 14:17:02; author: wjacobso; state: Exp; lines added/del: 8/8 69 * added register var definitions 70 * 71 * revision 1.2 72 * date: 84/07/06 09:51:12; author: root; state: Exp; lines added/del: 2/1 73 * This version seems to run bug-free. 74 * 75 * revision 1.1 76 * date: 84/06/26 14:18:30; author: walsh; state: Exp; 77 * Initial revision 78 */ 79 80 81 #ifdef RDP 82 #include "../h/param.h" 83 #include "../h/dir.h" 84 #include "../h/user.h" 85 #include "../h/kernel.h" 86 #include "../h/inode.h" 87 #include "../h/mbuf.h" 88 #include "../h/socket.h" 89 #include "../h/socketvar.h" 90 #include "../h/syslog.h" 91 92 #include "../net/if.h" 93 #include "../net/route.h" 94 95 #include "../bbnnet/in.h" 96 #include "../bbnnet/net.h" 97 #include "../bbnnet/in_pcb.h" 98 #include "../bbnnet/in_var.h" 99 #include "../bbnnet/ip.h" 100 #include "../bbnnet/icmp.h" 101 #include "../bbnnet/rdp.h" 102 #include "../bbnnet/seq.h" 103 #include "../bbnnet/rdp_macros.h" 104 105 /* 106 * Called on ACK of a message we sent. 107 */ 108 he_acked(rdpcb, msgnum) 109 register RDPCB *rdpcb; 110 rdpsequence msgnum; 111 { 112 register int index; 113 register int i; 114 register MBUF *m; 115 116 index = msgnum - rdpcb->r_sendq.rq_baseseq; 117 if (index < 0 || index >= rdpcb->r_sendq.rq_maxqlen) 118 return; 119 120 /* 121 * an ACK is cumulative and may be for more than one message 122 */ 123 for (i=0; i<=index; i++) 124 { 125 register int j; 126 127 j = (rdpcb->r_sendq.rq_front + i) % rdpcb->r_sendq.rq_maxqlen; 128 m = rdpcb->r_sendq.rq_msgs[j]; 129 /* 130 * ignore redundant ACKs. May have been EACKed (RDP_DELIVERED). 131 */ 132 if (m) 133 { 134 if (m == RDP_NULLMSG) 135 { 136 /* and restart connection loss detection */ 137 rdpcb->r_nullsent = 0; 138 rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull; 139 } 140 else if (m != RDP_DELIVERED) 141 { 142 #ifdef RDP_CS 143 /* count when acked, not queued */ 144 rdpcb->r_sent.r_nbytes += (int) m->m_act; 145 #endif 146 m_freem(m); 147 } 148 rdpcb->r_sendq.rq_msgs[j] = NULL; 149 } 150 clear_rxtimer (rdpcb, j); 151 } 152 153 /* 154 * Ensure front is always NULL or an undelivered (unacked) message. 155 */ 156 rdpcb->r_sendq.rq_front += (index +1); 157 rdpcb->r_sendq.rq_front %= rdpcb->r_sendq.rq_maxqlen; 158 rdpcb->r_sendq.rq_baseseq += (index +1); /* bumps r_snduna */ 159 160 /* 161 * and, did this ack allow us to measure current round trip time? 162 */ 163 if (rdpcb->r_rttiming) 164 { 165 if (SEQ_GT(rdpcb->r_sendq.rq_baseseq, rdpcb->r_rttimed)) 166 { 167 update_rttestimate(rdpcb); 168 update_rxmitime(rdpcb); 169 rdpcb->r_rttiming = FALSE; 170 } 171 } 172 173 #ifdef BBNPING 174 /* 175 * We've sent him NEW data, perhaps by a gateway, that he 176 * has successfully received. If that's the case, then 177 * we know the route works and we don't have to ping that 178 * gateway. 179 * 180 * see check_ping() 181 */ 182 { 183 register struct rtentry *rt; 184 185 if (rt = rdpcb->r_inpcb->inp_route.ro_rt) 186 if (rt->rt_flags & RTF_GATEWAY) 187 rt->irt_pings = (-1); 188 } 189 #endif 190 191 /* 192 * and let sender send more pkts now that we have space. 193 */ 194 sendbufhasspace(rdpcb); 195 } 196 197 /* 198 * Called on EACK of a message we sent. 199 */ 200 he_eacked(rdpcb, msgnum) 201 register RDPCB *rdpcb; 202 rdpsequence msgnum; 203 { 204 register int index; 205 register MBUF *m; 206 207 index = msgnum - rdpcb->r_sendq.rq_baseseq; 208 if (index < 0 || index >= rdpcb->r_sendq.rq_maxqlen) 209 return; 210 211 index = (index + rdpcb->r_sendq.rq_front) % rdpcb->r_sendq.rq_maxqlen; 212 m = rdpcb->r_sendq.rq_msgs[index]; 213 /* 214 * ignore redundant EACKs 215 */ 216 if (m && (m != RDP_DELIVERED)) 217 { 218 if (m == RDP_NULLMSG) 219 { 220 /* and restart connection loss detection */ 221 rdpcb->r_nullsent = 0; 222 rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull; 223 log(LOG_INFO, "Incorrect ACK strategy on rdpcb 0x%x\n", rdpcb); 224 } 225 else 226 { 227 #ifdef RDP_CS 228 rdpcb->r_sent.r_nbytes += (int) m->m_act; 229 #endif 230 m_freem(m); 231 } 232 rdpcb->r_sendq.rq_msgs[index] = RDP_DELIVERED; 233 clear_rxtimer(rdpcb, index); 234 235 /* 236 * did this eack allow us to measure current round trip time? 237 */ 238 if (rdpcb->r_rttiming) 239 { 240 if (msgnum == rdpcb->r_rttimed) 241 { 242 update_rttestimate(rdpcb); 243 update_rxmitime(rdpcb); 244 rdpcb->r_rttiming = FALSE; 245 } 246 } 247 } 248 } 249 250 251 /* 252 * Grab a message for passing to the user. msgq is our rcvq. 253 * Called on net reception if user recv q is empty. 254 * Called on PRU_RECV after user picks up current packet on socket. 255 * Only one packet is attached to the socket at a time. 256 */ 257 MBUF *rdp_qremove(msgq, async) 258 register RDP_MSGQ *msgq; 259 { 260 MBUF *m; 261 int index; 262 int pass; 263 264 index = msgq->rq_front; 265 pass = msgq->rq_maxqlen; 266 do 267 { 268 m = msgq->rq_msgs[index]; 269 if (m && m != RDP_DELIVERED) 270 { 271 msgq->rq_msgs[index] = RDP_DELIVERED; 272 return (m); 273 } 274 index = (index +1) % msgq->rq_maxqlen; 275 } 276 while (async && (--pass > 0)); 277 278 return (NULL); 279 } 280 281 /* 282 * rdp_qremove() grabbed a message to pass to the user. When he picks it up, 283 * PRU_RCVD occurs. At that point, we bump front and we send an ACK. 284 */ 285 rdp_received(msgq) 286 register RDP_MSGQ *msgq; 287 { 288 register MBUF *m; 289 register int index; 290 291 do 292 { 293 index = msgq->rq_front; 294 m = msgq->rq_msgs[index]; 295 if (m == RDP_DELIVERED) 296 { 297 msgq->rq_front = (msgq->rq_front +1) % msgq->rq_maxqlen; 298 msgq->rq_baseseq ++; 299 msgq->rq_msgs[index] = NULL; 300 } 301 } 302 while (m == RDP_DELIVERED); 303 } 304 305 /* 306 * Put a message on our send or rcv q. 307 * 308 * 0 internal error somewhere 309 * 1 new message 310 * -1 duplicate message 311 */ 312 rdp_qinsert(msgq, m, msgnum) 313 register RDP_MSGQ *msgq; 314 MBUF *m; 315 rdpsequence msgnum; 316 { 317 register int index; 318 int isdup; 319 320 index = msgnum - msgq->rq_baseseq; 321 if ((index < 0) || (index >= msgq->rq_maxqlen)) 322 { 323 m_freem(m); 324 return(0); 325 } 326 327 index = (index + msgq->rq_front) % msgq->rq_maxqlen; 328 if (msgq->rq_msgs[index] == RDP_DELIVERED) 329 { 330 /* rcvd duplicate of a message the user already has on socket */ 331 m_freem(m); 332 isdup = -1; 333 } 334 else 335 { 336 if (msgq->rq_msgs[index]) 337 { 338 m_freem(msgq->rq_msgs[index]); 339 isdup = -1; 340 } 341 else 342 isdup = 1; 343 msgq->rq_msgs[index] = m; 344 } 345 return(isdup); 346 } 347 #endif 348