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