125202Skarels /*
225202Skarels $Log: rdp_subr.c,v $
325202Skarels * Revision 2.7 84/11/21 12:06:30 walsh
425202Skarels * *** empty log message ***
525202Skarels *
625202Skarels * Revision 2.6 84/11/08 16:12:53 walsh
725202Skarels * Added code to gather statistics on RDP traffic. This makes the RDPCB
825202Skarels * too big unles you make mbufs 512 bytes large. RDP_CS should be turned off
925202Skarels * unless you do.
1025202Skarels *
1125202Skarels * Revision 2.5 84/11/06 13:54:21 walsh
1225202Skarels * *** empty log message ***
1325202Skarels *
1425202Skarels * Revision 2.4 84/11/05 16:25:18 walsh
1525202Skarels * tied rdp to icmp source quenches. See icmp_quench and rdp_quench.
1625202Skarels *
1725202Skarels * Revision 2.3 84/11/05 15:55:13 walsh
1825202Skarels * update_nulltimer() macro began to look inappropriate with recent
1925202Skarels * changes, so its been stripped out and put in-line.
2025202Skarels *
2125202Skarels * Revision 2.2 84/11/02 18:25:47 walsh
2225202Skarels * Protocol specifiers want NULL message to have own sequence number in
2325202Skarels * case of slow (t>NULL msg timeout) packets. I don't see this as a problem,
2425202Skarels * and even if happened (dubious) would only delay discovery, but I
2525202Skarels * didn't win this one. Initially not designed for this, but fixes are
2625202Skarels * in almost neatly.
2725202Skarels *
2825202Skarels * Revision 2.1 84/11/02 10:15:35 walsh
2925202Skarels * Fixed to include RCS comments in checked out source.
3025202Skarels *
3125202Skarels *
3225202Skarels * description:
3325202Skarels * Some subroutines for manipulating the datagram q's for RDP.
3425202Skarels *
3525202Skarels * revision 1.11
3625202Skarels * date: 84/07/20 10:30:42; author: walsh; state: Exp; lines added/del: 21/1
3725202Skarels * Tied RDP acknowledgements to ping reduction, just like TCP.
3825202Skarels *
3925202Skarels * revision 1.10
4025202Skarels * date: 84/07/19 10:22:33; author: walsh; state: Exp; lines added/del: 1/17
4125202Skarels * Organized macros and classified their definitions in rdp_macros.h.
4225202Skarels *
4325202Skarels * revision 1.9
4425202Skarels * date: 84/07/17 22:35:26; author: walsh; state: Exp; lines added/del: 3/0
4525202Skarels * Ensure cannot bind port number greater than RDP_pMAX.
4625202Skarels *
4725202Skarels * revision 1.8
4825202Skarels * date: 84/07/12 10:12:48; author: walsh; state: Exp; lines added/del: 14/18
4925202Skarels * some small optimizations.
5025202Skarels *
5125202Skarels * revision 1.7
5225202Skarels * date: 84/07/12 09:39:06; author: walsh; state: Exp; lines added/del: 2/4
5325202Skarels * small optimizations. ( a = (a+1)%b quicker than a++; a %= b)
5425202Skarels *
5525202Skarels * revision 1.6
5625202Skarels * date: 84/07/10 14:58:24; author: walsh; state: Exp; lines added/del: 10/3
5725202Skarels * Now no unecessary wakeups of the user process are done.
5825202Skarels *
5925202Skarels * revision 1.5
6025202Skarels * date: 84/07/10 10:38:24; author: walsh; state: Exp; lines added/del: 13/13
6125202Skarels * added register declarations.
6225202Skarels *
6325202Skarels * revision 1.4
6425202Skarels * date: 84/07/06 14:28:53; author: wjacobso; state: Exp; lines added/del: 6/6
6525202Skarels * *** empty log message ***
6625202Skarels *
6725202Skarels * revision 1.3
6825202Skarels * date: 84/07/06 14:17:02; author: wjacobso; state: Exp; lines added/del: 8/8
6925202Skarels * added register var definitions
7025202Skarels *
7125202Skarels * revision 1.2
7225202Skarels * date: 84/07/06 09:51:12; author: root; state: Exp; lines added/del: 2/1
7325202Skarels * This version seems to run bug-free.
7425202Skarels *
7525202Skarels * revision 1.1
7625202Skarels * date: 84/06/26 14:18:30; author: walsh; state: Exp;
7725202Skarels * Initial revision
7825202Skarels */
7925202Skarels
8025202Skarels
8125202Skarels #ifdef RDP
8225202Skarels #include "../h/param.h"
8325202Skarels #include "../h/dir.h"
8425202Skarels #include "../h/user.h"
8525202Skarels #include "../h/kernel.h"
8625202Skarels #include "../h/inode.h"
8725202Skarels #include "../h/mbuf.h"
8825202Skarels #include "../h/socket.h"
8925202Skarels #include "../h/socketvar.h"
9025202Skarels #include "../h/syslog.h"
9125202Skarels
9225202Skarels #include "../net/if.h"
9325202Skarels #include "../net/route.h"
9425202Skarels
9525202Skarels #include "../bbnnet/in.h"
9625202Skarels #include "../bbnnet/net.h"
9725202Skarels #include "../bbnnet/in_pcb.h"
9825202Skarels #include "../bbnnet/in_var.h"
9925202Skarels #include "../bbnnet/ip.h"
10025202Skarels #include "../bbnnet/icmp.h"
10125202Skarels #include "../bbnnet/rdp.h"
10225202Skarels #include "../bbnnet/seq.h"
10325202Skarels #include "../bbnnet/rdp_macros.h"
10425202Skarels
10525202Skarels /*
10625202Skarels * Called on ACK of a message we sent.
10725202Skarels */
he_acked(rdpcb,msgnum)10825202Skarels he_acked(rdpcb, msgnum)
10925202Skarels register RDPCB *rdpcb;
11025202Skarels rdpsequence msgnum;
11125202Skarels {
11225202Skarels register int index;
11325202Skarels register int i;
11425202Skarels register MBUF *m;
11525202Skarels
11625202Skarels index = msgnum - rdpcb->r_sendq.rq_baseseq;
11725202Skarels if (index < 0 || index >= rdpcb->r_sendq.rq_maxqlen)
11825202Skarels return;
11925202Skarels
12025202Skarels /*
12125202Skarels * an ACK is cumulative and may be for more than one message
12225202Skarels */
12325202Skarels for (i=0; i<=index; i++)
12425202Skarels {
12525202Skarels register int j;
12625202Skarels
12725202Skarels j = (rdpcb->r_sendq.rq_front + i) % rdpcb->r_sendq.rq_maxqlen;
12825202Skarels m = rdpcb->r_sendq.rq_msgs[j];
12925202Skarels /*
13025202Skarels * ignore redundant ACKs. May have been EACKed (RDP_DELIVERED).
13125202Skarels */
13225202Skarels if (m)
13325202Skarels {
13425202Skarels if (m == RDP_NULLMSG)
13525202Skarels {
13625202Skarels /* and restart connection loss detection */
13725202Skarels rdpcb->r_nullsent = 0;
13825202Skarels rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull;
13925202Skarels }
14025202Skarels else if (m != RDP_DELIVERED)
14125202Skarels {
14225202Skarels #ifdef RDP_CS
14325202Skarels /* count when acked, not queued */
14425202Skarels rdpcb->r_sent.r_nbytes += (int) m->m_act;
14525202Skarels #endif
14625202Skarels m_freem(m);
14725202Skarels }
14825202Skarels rdpcb->r_sendq.rq_msgs[j] = NULL;
14925202Skarels }
15025202Skarels clear_rxtimer (rdpcb, j);
15125202Skarels }
15225202Skarels
15325202Skarels /*
15425202Skarels * Ensure front is always NULL or an undelivered (unacked) message.
15525202Skarels */
15625202Skarels rdpcb->r_sendq.rq_front += (index +1);
15725202Skarels rdpcb->r_sendq.rq_front %= rdpcb->r_sendq.rq_maxqlen;
15825202Skarels rdpcb->r_sendq.rq_baseseq += (index +1); /* bumps r_snduna */
15925202Skarels
16025202Skarels /*
16125202Skarels * and, did this ack allow us to measure current round trip time?
16225202Skarels */
16325202Skarels if (rdpcb->r_rttiming)
16425202Skarels {
16525202Skarels if (SEQ_GT(rdpcb->r_sendq.rq_baseseq, rdpcb->r_rttimed))
16625202Skarels {
16725202Skarels update_rttestimate(rdpcb);
16825202Skarels update_rxmitime(rdpcb);
16925202Skarels rdpcb->r_rttiming = FALSE;
17025202Skarels }
17125202Skarels }
17225202Skarels
17325202Skarels #ifdef BBNPING
17425202Skarels /*
17525202Skarels * We've sent him NEW data, perhaps by a gateway, that he
17625202Skarels * has successfully received. If that's the case, then
17725202Skarels * we know the route works and we don't have to ping that
17825202Skarels * gateway.
17925202Skarels *
18025202Skarels * see check_ping()
18125202Skarels */
18225202Skarels {
18325202Skarels register struct rtentry *rt;
18425202Skarels
18525202Skarels if (rt = rdpcb->r_inpcb->inp_route.ro_rt)
18625202Skarels if (rt->rt_flags & RTF_GATEWAY)
18725202Skarels rt->irt_pings = (-1);
18825202Skarels }
18925202Skarels #endif
19025202Skarels
19125202Skarels /*
19225202Skarels * and let sender send more pkts now that we have space.
19325202Skarels */
19425202Skarels sendbufhasspace(rdpcb);
19525202Skarels }
19625202Skarels
19725202Skarels /*
19825202Skarels * Called on EACK of a message we sent.
19925202Skarels */
he_eacked(rdpcb,msgnum)20025202Skarels he_eacked(rdpcb, msgnum)
20125202Skarels register RDPCB *rdpcb;
20225202Skarels rdpsequence msgnum;
20325202Skarels {
20425202Skarels register int index;
20525202Skarels register MBUF *m;
20625202Skarels
20725202Skarels index = msgnum - rdpcb->r_sendq.rq_baseseq;
20825202Skarels if (index < 0 || index >= rdpcb->r_sendq.rq_maxqlen)
20925202Skarels return;
21025202Skarels
21125202Skarels index = (index + rdpcb->r_sendq.rq_front) % rdpcb->r_sendq.rq_maxqlen;
21225202Skarels m = rdpcb->r_sendq.rq_msgs[index];
21325202Skarels /*
21425202Skarels * ignore redundant EACKs
21525202Skarels */
21625202Skarels if (m && (m != RDP_DELIVERED))
21725202Skarels {
21825202Skarels if (m == RDP_NULLMSG)
21925202Skarels {
22025202Skarels /* and restart connection loss detection */
22125202Skarels rdpcb->r_nullsent = 0;
22225202Skarels rdpcb->r_timers[RDP_tNULL] = rdpcb->r_tvnull;
223*25209Skarels log(LOG_INFO, "Incorrect ACK strategy on rdpcb 0x%x\n", rdpcb);
22425202Skarels }
22525202Skarels else
22625202Skarels {
22725202Skarels #ifdef RDP_CS
22825202Skarels rdpcb->r_sent.r_nbytes += (int) m->m_act;
22925202Skarels #endif
23025202Skarels m_freem(m);
23125202Skarels }
23225202Skarels rdpcb->r_sendq.rq_msgs[index] = RDP_DELIVERED;
23325202Skarels clear_rxtimer(rdpcb, index);
23425202Skarels
23525202Skarels /*
23625202Skarels * did this eack allow us to measure current round trip time?
23725202Skarels */
23825202Skarels if (rdpcb->r_rttiming)
23925202Skarels {
24025202Skarels if (msgnum == rdpcb->r_rttimed)
24125202Skarels {
24225202Skarels update_rttestimate(rdpcb);
24325202Skarels update_rxmitime(rdpcb);
24425202Skarels rdpcb->r_rttiming = FALSE;
24525202Skarels }
24625202Skarels }
24725202Skarels }
24825202Skarels }
24925202Skarels
25025202Skarels
25125202Skarels /*
25225202Skarels * Grab a message for passing to the user. msgq is our rcvq.
25325202Skarels * Called on net reception if user recv q is empty.
25425202Skarels * Called on PRU_RECV after user picks up current packet on socket.
25525202Skarels * Only one packet is attached to the socket at a time.
25625202Skarels */
rdp_qremove(msgq,async)25725202Skarels MBUF *rdp_qremove(msgq, async)
25825202Skarels register RDP_MSGQ *msgq;
25925202Skarels {
26025202Skarels MBUF *m;
26125202Skarels int index;
26225202Skarels int pass;
26325202Skarels
26425202Skarels index = msgq->rq_front;
26525202Skarels pass = msgq->rq_maxqlen;
26625202Skarels do
26725202Skarels {
26825202Skarels m = msgq->rq_msgs[index];
26925202Skarels if (m && m != RDP_DELIVERED)
27025202Skarels {
27125202Skarels msgq->rq_msgs[index] = RDP_DELIVERED;
27225202Skarels return (m);
27325202Skarels }
27425202Skarels index = (index +1) % msgq->rq_maxqlen;
27525202Skarels }
27625202Skarels while (async && (--pass > 0));
27725202Skarels
27825202Skarels return (NULL);
27925202Skarels }
28025202Skarels
28125202Skarels /*
28225202Skarels * rdp_qremove() grabbed a message to pass to the user. When he picks it up,
28325202Skarels * PRU_RCVD occurs. At that point, we bump front and we send an ACK.
28425202Skarels */
rdp_received(msgq)28525202Skarels rdp_received(msgq)
28625202Skarels register RDP_MSGQ *msgq;
28725202Skarels {
28825202Skarels register MBUF *m;
28925202Skarels register int index;
29025202Skarels
29125202Skarels do
29225202Skarels {
29325202Skarels index = msgq->rq_front;
29425202Skarels m = msgq->rq_msgs[index];
29525202Skarels if (m == RDP_DELIVERED)
29625202Skarels {
29725202Skarels msgq->rq_front = (msgq->rq_front +1) % msgq->rq_maxqlen;
29825202Skarels msgq->rq_baseseq ++;
29925202Skarels msgq->rq_msgs[index] = NULL;
30025202Skarels }
30125202Skarels }
30225202Skarels while (m == RDP_DELIVERED);
30325202Skarels }
30425202Skarels
30525202Skarels /*
30625202Skarels * Put a message on our send or rcv q.
30725202Skarels *
30825202Skarels * 0 internal error somewhere
30925202Skarels * 1 new message
31025202Skarels * -1 duplicate message
31125202Skarels */
rdp_qinsert(msgq,m,msgnum)31225202Skarels rdp_qinsert(msgq, m, msgnum)
31325202Skarels register RDP_MSGQ *msgq;
31425202Skarels MBUF *m;
31525202Skarels rdpsequence msgnum;
31625202Skarels {
31725202Skarels register int index;
31825202Skarels int isdup;
31925202Skarels
32025202Skarels index = msgnum - msgq->rq_baseseq;
32125202Skarels if ((index < 0) || (index >= msgq->rq_maxqlen))
32225202Skarels {
32325202Skarels m_freem(m);
32425202Skarels return(0);
32525202Skarels }
32625202Skarels
32725202Skarels index = (index + msgq->rq_front) % msgq->rq_maxqlen;
32825202Skarels if (msgq->rq_msgs[index] == RDP_DELIVERED)
32925202Skarels {
33025202Skarels /* rcvd duplicate of a message the user already has on socket */
33125202Skarels m_freem(m);
33225202Skarels isdup = -1;
33325202Skarels }
33425202Skarels else
33525202Skarels {
33625202Skarels if (msgq->rq_msgs[index])
33725202Skarels {
33825202Skarels m_freem(msgq->rq_msgs[index]);
33925202Skarels isdup = -1;
34025202Skarels }
34125202Skarels else
34225202Skarels isdup = 1;
34325202Skarels msgq->rq_msgs[index] = m;
34425202Skarels }
34525202Skarels return(isdup);
34625202Skarels }
34725202Skarels #endif
348