1*8407Swnj /* nsp_input.c 1.3 82/10/09 */
26826Ssam
36826Ssam #include "../h/param.h"
46826Ssam #include "../h/systm.h"
56826Ssam #include "../h/mbuf.h"
66826Ssam #include "../h/protosw.h"
76826Ssam #include "../h/socket.h"
86826Ssam #include "../h/socketvar.h"
9*8407Swnj #include "../netdecnet/dn_systm.h"
10*8407Swnj #include "../netdecnet/nsp.h"
11*8407Swnj #include "../netdecnet/nsp_var.h"
12*8407Swnj #include <errno.h>
136826Ssam
146826Ssam int nspidebug = 1;
156826Ssam #define printd if(nspidebug)printf
166826Ssam /*
176826Ssam * NSP input routine: decode incoming packet and dispatch
186826Ssam * to appropriate socket. Called from the software interrupt
196826Ssam * at splnet.
206826Ssam *
216826Ssam * TODO:
226826Ssam * count occurances of various error conditions.
236826Ssam */
246826Ssam
nspintr()256826Ssam nspintr()
266826Ssam {
276826Ssam struct mbuf *m;
286826Ssam struct tprh *t;
296826Ssam int s, bom, eom;
306826Ssam u_short srcnode;
316826Ssam char *p;
326826Ssam struct nspcb *np;
336826Ssam
346826Ssam /*
356826Ssam * Loop pulling packets off the interrupt queue.
366826Ssam */
376826Ssam next:
386826Ssam s = splimp();
396826Ssam IF_DEQUEUE(&nspintrq, m);
406826Ssam splx(s);
416826Ssam printd("nsp_input: m 0x%x", m);
426826Ssam if (m == 0)
436826Ssam return;
446826Ssam t = mtod(m, struct tprh *);
456826Ssam srcnode = t->tprh_srcnode;
466826Ssam m->m_len -= sizeof (struct tprh); /* use m_adj??? */
476826Ssam m->m_off += sizeof (struct tprh);
486826Ssam printd(", srcnode %d, len %d", srcnode, m->m_len);
496826Ssam if (m->m_len <= 0) {
506826Ssam m_freem(m);
516826Ssam goto next;
526826Ssam }
536826Ssam
546826Ssam /*
556826Ssam * Switch on the type of the message.
566826Ssam */
576826Ssam p = mtod(m, char *);
586826Ssam switch (*p) {
596826Ssam
606826Ssam /*
616826Ssam * Got a Data message, possibly with EOM and
626826Ssam * BOM flags set. Call nsp_chkaddr to do ack
636826Ssam * and flow controll processing, then pass the
646826Ssam * data to the user.
656826Ssam */
666826Ssam case NSP_DATA|NSP_EOM|NSP_BOM:
676826Ssam eom = bom = 1;
686826Ssam goto data;
696826Ssam
706826Ssam case NSP_DATA|NSP_EOM:
716826Ssam eom = 1;
726826Ssam goto data;
736826Ssam
746826Ssam case NSP_DATA|NSP_BOM:
756826Ssam bom = 1;
766826Ssam
776826Ssam case NSP_DATA:
786826Ssam data:
796826Ssam printd(", DATA (%d,%d)", bom, eom);
806826Ssam np = nsp_chkaddr(m, srcnode, NSP_DATA, &segnum);
816826Ssam if (np == 0) {
826826Ssam m_freem(m);
836826Ssam goto next;
846826Ssam }
856826Ssam
866826Ssam /*
876826Ssam * Data messages only valid in Run state
886826Ssam */
896826Ssam if (np->n_state != NS_RUN) {
906826Ssam printf(", !RUN (%d)\n", np->n_state);
916826Ssam m_freem(m);
926826Ssam goto next;
936826Ssam }
946826Ssam if (SEQ_GTR(segnum, np->na_xmtdat)) {
956826Ssam /* SHOULD DO SEGMENT RECONSTRUCTION HERE */
966826Ssam printd(", got data!");
976826Ssam sbpappend(m, &np->n_socket->sb_rcv);
986826Ssam } else
996826Ssam np->n_flags |= NF_DATACK;
1006826Ssam break;
1016826Ssam
1026826Ssam /*
1036826Ssam * Got an interrupt message. Call nsp_chkaddr
1046826Ssam * (as usual). Save the interrupt data for the
1056826Ssam * user.
1066826Ssam * GENERATE A SIGNAL OF SOME SORT???
1076826Ssam */
1086826Ssam case NSP_INTR:
1096826Ssam printd(", INTR");
1106826Ssam np = nsp_chkaddr(m, srcnode, NSP_INTR, &segnum);
1116826Ssam if (np == 0) {
1126826Ssam m_freem(m);
1136826Ssam goto next;
1146826Ssam }
1156826Ssam
1166826Ssam /*
1176826Ssam * If we are in the Connect Confirm state then
1186826Ssam * this Interrupt packet causes the transition
1196826Ssam * to the Run state. Otherwise we better be in
1206826Ssam * the Run state already.
1216826Ssam */
1226826Ssam if (np->n_state == NS_CC)
1236826Ssam np->n_state = NS_RUN;
1246826Ssam else if (np->n_state != NS_RUN) {
1256826Ssam printf(", !RUN %d\n", np->n_state);
1266826Ssam m_freem(m);
1276826Ssam goto next;
1286826Ssam }
1296826Ssam
1306826Ssam /*
1316826Ssam * If this segment is the one after the last
1326826Ssam * other data segment we acked, and there is
1336826Ssam * no waiting interrupt message, then queue
1346826Ssam * this one up.
1356826Ssam */
1366826Ssam if (segnum == SEQ_ADD(np->na_xmtoth, 1) &&
1376826Ssam np->nf_locint == NFL_EMPTY) {
1386826Ssam if (np->nb_rcv) {
1396826Ssam printd(", flush old intr data");
1406826Ssam m_freem(np->nb_rcv);
1416826Ssam }
1426826Ssam if (m->m_len > 16) {
1436826Ssam printd(", intr data too long\n");
1446826Ssam m_freem(m);
1456826Ssam goto next;
1466826Ssam }
1476826Ssam np->nb_rcv = m;
1486826Ssam np->nf_locint = NFL_INTR;
1496826Ssam np->na_xmtoth = segnum; /* really += 1 */
1506826Ssam np->n_flags |= NF_OTHACK;
1516826Ssam } else if (SEQ_LEQ(segnum, np->na_xmtoth))
1526826Ssam np->n_flags |= NF_OTHACK;
1536826Ssam break;
1546826Ssam
1556826Ssam /*
1566826Ssam * Got a Link Service message. Process options
1576826Ssam * to modify flow control values.
1586826Ssam */
1596826Ssam case NSP_LS:
1606826Ssam printd(", LS");
1616826Ssam np = nsp_chkaddr(m, srcnode, NSP_LS, &segnum);
1626826Ssam if (np == 0) {
1636826Ssam m_freem(m);
1646826Ssam goto next;
1656826Ssam }
1666826Ssam
1676826Ssam /*
1686826Ssam * If we are in the Connect Confirm state then
1696826Ssam * this Link Service packet causes the transition
1706826Ssam * to the Run state. Otherwise we better be in
1716826Ssam * the Run state already.
1726826Ssam */
1736826Ssam if (np->n_state == NS_CC)
1746826Ssam np->n_state = NS_RUN;
1756826Ssam else if (np->n_state != NS_RUN) {
1766826Ssam printd(", !RUN %d\n", np->n_state);
1776826Ssam m_freem(m);
1786826Ssam goto next;
1796826Ssam }
1806826Ssam p = mtod(m, char *);
1816826Ssam lsf = *p++;
1826826Ssam fcval = *p;
1836826Ssam printd(", lsf 0x%x, fcval %d", lsf, fcval);
1846826Ssam switch (lsf & NSPLS_FCVALINT) {
1856826Ssam case NSPLS_DATREQ:
1866826Ssam if (seqnum == SEQ_ADD(np->na_xmtoth, 1)) {
1876826Ssam if (np->nf_remdat + fcval >= -128 &&
1886826Ssam np->nf_remdat + fcval <= 127) {
1896826Ssam np->nf_remdat += fcval;
1906826Ssam np->na_xmtoth = segnum;
1916826Ssam np->n_flags |= NF_OTHACK;
1926826Ssam switch (lsf & NSPLS_FCMOD) {
1936826Ssam case NSPLS_NOCHANGE:
1946826Ssam break;
1956826Ssam case NSPLS_ON:
1966826Ssam np->n_flags &= ~NF_DATOFF;
1976826Ssam break;
1986826Ssam case NSPLS_OFF:
1996826Ssam np->n_flags |= NF_DATOFF;
2006826Ssam break;
2016826Ssam default:
2026826Ssam printd(", bad fcmod");
2036826Ssam }
2046826Ssam }
2056826Ssam } else if (SEQ_LEQ(segnum, np->na_xmtoth))
2066826Ssam np->n_flags |= NF_OTHACK;
2076826Ssam break;
2086826Ssam
2096826Ssam case NSPLS_INTREQ:
2106826Ssam if (seqnum == SEQ_ADD(np->na_xmtoth, 1)) {
2116826Ssam if (fcval >= 0 && np->nf_remint+fcval <= 127) {
2126826Ssam np->nf_remint += fcval;
2136826Ssam np->na_xmtoth = segnum;
2146826Ssam np->n_flags |= NF_OTHACK;
2156826Ssam } else if (SEQ_LEQ(segnum, np->na_xmtoth))
2166826Ssam np->n_flags |= NF_OTHACK;
2176826Ssam break;
2186826Ssam
2196826Ssam default:
2206826Ssam printd(", bad fcvalint");
2216826Ssam }
2226826Ssam break;
2236826Ssam
2246826Ssam /*
2256826Ssam * Got an acknowledgement for a Data message.
2266826Ssam * Nsp_chkaddr processes the ack, nothing else
2276826Ssam * to do.
2286826Ssam */
2296826Ssam case NSP_DATACK:
2306826Ssam printd(", DATACK");
2316826Ssam np = nsp_chkaddr(m, srcnode, NSP_DATACK, &segnum);
2326826Ssam if (np == 0) {
2336826Ssam m_freem(m);
2346826Ssam goto next;
2356826Ssam }
2366826Ssam break;
2376826Ssam
2386826Ssam /*
2396826Ssam * Got an acknowledgement for an Other Data message.
2406826Ssam * Nsp_chkaddr processes the ack, nothing else to do.
2416826Ssam */
2426826Ssam case NSP_OTHACK:
2436826Ssam printd(", OTHACK");
2446826Ssam np = nsp_chkaddr(m, srcnode, NSP_OTHACK, &segnum);
2456826Ssam if (np == 0) {
2466826Ssam m_freem(m);
2476826Ssam goto next;
2486826Ssam }
2496826Ssam break;
2506826Ssam
2516826Ssam /*
2526826Ssam * Got a Connect Acknowledgement. Just verify
2536826Ssam * the address and perform the state transition.
2546826Ssam */
2556826Ssam case NSP_CONACK:
2566826Ssam DOIT
2576826Ssam break;
2586826Ssam
2596826Ssam /*
2606826Ssam * Got an unknown message, count it and flush it.
2616826Ssam */
2626826Ssam default:
2636826Ssam printd(", UNKNOWN!!!");
2646826Ssam m_freem(m);
2656826Ssam break;
2666826Ssam }
2676826Ssam printd("\n");
2686826Ssam goto next;
2696826Ssam }
270