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