from BBN
[unix-history] / usr / src / sys / deprecated / bbnnet / rdp_subr.c
/*
$Log: rdp_subr.c,v $
* Revision 2.7 84/11/21 12:06:30 walsh
* *** empty log message ***
*
* Revision 2.6 84/11/08 16:12:53 walsh
* Added code to gather statistics on RDP traffic. This makes the RDPCB
* too big unles you make mbufs 512 bytes large. RDP_CS should be turned off
* unless you do.
*
* Revision 2.5 84/11/06 13:54:21 walsh
* *** empty log message ***
*
* Revision 2.4 84/11/05 16:25:18 walsh
* tied rdp to icmp source quenches. See icmp_quench and rdp_quench.
*
* Revision 2.3 84/11/05 15:55:13 walsh
* update_nulltimer() macro began to look inappropriate with recent
* changes, so its been stripped out and put in-line.
*
* Revision 2.2 84/11/02 18:25:47 walsh
* Protocol specifiers want NULL message to have own sequence number in
* case of slow (t>NULL msg timeout) packets. I don't see this as a problem,
* and even if happened (dubious) would only delay discovery, but I
* didn't win this one. Initially not designed for this, but fixes are
* in almost neatly.
*
* Revision 2.1 84/11/02 10:15:35 walsh
* Fixed to include RCS comments in checked out source.
*
*
* description:
* Some subroutines for manipulating the datagram q's for RDP.
*
* revision 1.11
* date: 84/07/20 10:30:42; author: walsh; state: Exp; lines added/del: 21/1
* Tied RDP acknowledgements to ping reduction, just like TCP.
*
* revision 1.10
* date: 84/07/19 10:22:33; author: walsh; state: Exp; lines added/del: 1/17
* Organized macros and classified their definitions in rdp_macros.h.
*
* revision 1.9
* date: 84/07/17 22:35:26; author: walsh; state: Exp; lines added/del: 3/0
* Ensure cannot bind port number greater than RDP_pMAX.
*
* revision 1.8
* date: 84/07/12 10:12:48; author: walsh; state: Exp; lines added/del: 14/18
* some small optimizations.
*
* revision 1.7
* date: 84/07/12 09:39:06; author: walsh; state: Exp; lines added/del: 2/4
* small optimizations. ( a = (a+1)%b quicker than a++; a %= b)
*
* revision 1.6
* date: 84/07/10 14:58:24; author: walsh; state: Exp; lines added/del: 10/3
* Now no unecessary wakeups of the user process are done.
*
* revision 1.5
* date: 84/07/10 10:38:24; author: walsh; state: Exp; lines added/del: 13/13
* added register declarations.
*
* revision 1.4
* date: 84/07/06 14:28:53; author: wjacobso; state: Exp; lines added/del: 6/6
* *** empty log message ***
*
* revision 1.3
* date: 84/07/06 14:17:02; author: wjacobso; state: Exp; lines added/del: 8/8
* added register var definitions
*
* revision 1.2
* date: 84/07/06 09:51:12; author: root; state: Exp; lines added/del: 2/1
* This version seems to run bug-free.
*
* revision 1.1
* date: 84/06/26 14:18:30; author: walsh; state: Exp;
* Initial revision
*/
#ifdef RDP
#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/kernel.h"
#include "../h/inode.h"
#include "../h/mbuf.h"
#include "../h/socket.h"
#include "../h/socketvar.h"
#include "../h/syslog.h"
#include "../net/if.h"
#include "../net/route.h"
#include "../bbnnet/in.h"
#include "../bbnnet/net.h"
#include "../bbnnet/in_pcb.h"
#include "../bbnnet/in_var.h"
#include "../bbnnet/ip.h"
#include "../bbnnet/icmp.h"
#include "../bbnnet/rdp.h"
#include "../bbnnet/seq.h"
#include "../bbnnet/rdp_macros.h"
/*
* Called on ACK of a message we sent.
*/
he_acked(rdpcb, msgnum)
register RDPCB *rdpcb;
rdpsequence msgnum;
{
register int index;
register int i;
register MBUF *m;
index = msgnum - rdpcb->r_sendq.rq_baseseq;
if (index < 0 || index >= rdpcb->r_sendq.rq_maxqlen)
return;
/*
* an ACK is cumulative and may be for more than one message
*/
for (i=0; i<=index; i++)
{
register int j;
j = (rdpcb->r_sendq.rq_front + i) % rdpcb->r_sendq.rq_maxqlen;
m = rdpcb->r_sendq.rq_msgs[j];
/*
* ignore redundant ACKs. May have been EACKed (RDP_DELIVERED).
*/
if (m)
{
if (m == RDP_NULLMSG)
{
/* and restart connection loss detection */
rdpcb->r_nullsent = 0;
rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull;
}
else if (m != RDP_DELIVERED)
{
#ifdef RDP_CS
/* count when acked, not queued */
rdpcb->r_sent.r_nbytes += (int) m->m_act;
#endif
m_freem(m);
}
rdpcb->r_sendq.rq_msgs[j] = NULL;
}
clear_rxtimer (rdpcb, j);
}
/*
* Ensure front is always NULL or an undelivered (unacked) message.
*/
rdpcb->r_sendq.rq_front += (index +1);
rdpcb->r_sendq.rq_front %= rdpcb->r_sendq.rq_maxqlen;
rdpcb->r_sendq.rq_baseseq += (index +1); /* bumps r_snduna */
/*
* and, did this ack allow us to measure current round trip time?
*/
if (rdpcb->r_rttiming)
{
if (SEQ_GT(rdpcb->r_sendq.rq_baseseq, rdpcb->r_rttimed))
{
update_rttestimate(rdpcb);
update_rxmitime(rdpcb);
rdpcb->r_rttiming = FALSE;
}
}
#ifdef BBNPING
/*
* We've sent him NEW data, perhaps by a gateway, that he
* has successfully received. If that's the case, then
* we know the route works and we don't have to ping that
* gateway.
*
* see check_ping()
*/
{
register struct rtentry *rt;
if (rt = rdpcb->r_inpcb->inp_route.ro_rt)
if (rt->rt_flags & RTF_GATEWAY)
rt->irt_pings = (-1);
}
#endif
/*
* and let sender send more pkts now that we have space.
*/
sendbufhasspace(rdpcb);
}
/*
* Called on EACK of a message we sent.
*/
he_eacked(rdpcb, msgnum)
register RDPCB *rdpcb;
rdpsequence msgnum;
{
register int index;
register MBUF *m;
index = msgnum - rdpcb->r_sendq.rq_baseseq;
if (index < 0 || index >= rdpcb->r_sendq.rq_maxqlen)
return;
index = (index + rdpcb->r_sendq.rq_front) % rdpcb->r_sendq.rq_maxqlen;
m = rdpcb->r_sendq.rq_msgs[index];
/*
* ignore redundant EACKs
*/
if (m && (m != RDP_DELIVERED))
{
if (m == RDP_NULLMSG)
{
/* and restart connection loss detection */
rdpcb->r_nullsent = 0;
rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull;
log(KERN_RECOV, "Incorrect ACK strategy on rdpcb 0x%x\n", rdpcb);
}
else
{
#ifdef RDP_CS
rdpcb->r_sent.r_nbytes += (int) m->m_act;
#endif
m_freem(m);
}
rdpcb->r_sendq.rq_msgs[index] = RDP_DELIVERED;
clear_rxtimer(rdpcb, index);
/*
* did this eack allow us to measure current round trip time?
*/
if (rdpcb->r_rttiming)
{
if (msgnum == rdpcb->r_rttimed)
{
update_rttestimate(rdpcb);
update_rxmitime(rdpcb);
rdpcb->r_rttiming = FALSE;
}
}
}
}
/*
* Grab a message for passing to the user. msgq is our rcvq.
* Called on net reception if user recv q is empty.
* Called on PRU_RECV after user picks up current packet on socket.
* Only one packet is attached to the socket at a time.
*/
MBUF *rdp_qremove(msgq, async)
register RDP_MSGQ *msgq;
{
MBUF *m;
int index;
int pass;
index = msgq->rq_front;
pass = msgq->rq_maxqlen;
do
{
m = msgq->rq_msgs[index];
if (m && m != RDP_DELIVERED)
{
msgq->rq_msgs[index] = RDP_DELIVERED;
return (m);
}
index = (index +1) % msgq->rq_maxqlen;
}
while (async && (--pass > 0));
return (NULL);
}
/*
* rdp_qremove() grabbed a message to pass to the user. When he picks it up,
* PRU_RCVD occurs. At that point, we bump front and we send an ACK.
*/
rdp_received(msgq)
register RDP_MSGQ *msgq;
{
register MBUF *m;
register int index;
do
{
index = msgq->rq_front;
m = msgq->rq_msgs[index];
if (m == RDP_DELIVERED)
{
msgq->rq_front = (msgq->rq_front +1) % msgq->rq_maxqlen;
msgq->rq_baseseq ++;
msgq->rq_msgs[index] = NULL;
}
}
while (m == RDP_DELIVERED);
}
/*
* Put a message on our send or rcv q.
*
* 0 internal error somewhere
* 1 new message
* -1 duplicate message
*/
rdp_qinsert(msgq, m, msgnum)
register RDP_MSGQ *msgq;
MBUF *m;
rdpsequence msgnum;
{
register int index;
int isdup;
index = msgnum - msgq->rq_baseseq;
if ((index < 0) || (index >= msgq->rq_maxqlen))
{
m_freem(m);
return(0);
}
index = (index + msgq->rq_front) % msgq->rq_maxqlen;
if (msgq->rq_msgs[index] == RDP_DELIVERED)
{
/* rcvd duplicate of a message the user already has on socket */
m_freem(m);
isdup = -1;
}
else
{
if (msgq->rq_msgs[index])
{
m_freem(msgq->rq_msgs[index]);
isdup = -1;
}
else
isdup = 1;
msgq->rq_msgs[index] = m;
}
return(isdup);
}
#endif