X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/a2cd4df767910f9e0027c19e429d75826e5eb021..961945a80c6f995f4567dbce8881af0bbdee211c:/usr/src/sys/deprecated/netimp/if_imp.c diff --git a/usr/src/sys/deprecated/netimp/if_imp.c b/usr/src/sys/deprecated/netimp/if_imp.c index 1fafca9d83..7e39b50610 100644 --- a/usr/src/sys/deprecated/netimp/if_imp.c +++ b/usr/src/sys/deprecated/netimp/if_imp.c @@ -1,38 +1,39 @@ -/* if_imp.c 4.4 82/02/12 */ +/* if_imp.c 4.46 82/12/17 */ #include "imp.h" #if NIMP > 0 /* - * ARPAnet IMP interface driver. + * ARPANET IMP interface driver. * * The IMP-host protocol is handled here, leaving * hardware specifics to the lower level interface driver. - * - * TODO: - * rethink coupling between this module and device driver - * pass more error indications up to protocol modules - * test raw imp interface */ +#include "../machine/pte.h" + #include "../h/param.h" #include "../h/systm.h" #include "../h/mbuf.h" -#include "../h/pte.h" #include "../h/buf.h" #include "../h/protosw.h" #include "../h/socket.h" -#include "../h/ubareg.h" -#include "../h/ubavar.h" -#include "../h/cpu.h" -#include "../h/mtpr.h" #include "../h/vmmac.h" -#include "../net/in.h" -#include "../net/in_systm.h" + +#include "../vax/cpu.h" +#include "../vax/mtpr.h" +#include "../vaxuba/ubareg.h" +#include "../vaxuba/ubavar.h" + #include "../net/if.h" -#define IMPLEADERS -#include "../net/if_imp.h" -#include "../net/host.h" -#include "../net/ip.h" -#include "../net/ip_var.h" +#include "../net/route.h" +#include "../net/netisr.h" +#include "../netinet/in.h" +#include "../netinet/in_systm.h" +#include "../netinet/ip.h" +#include "../netinet/ip_var.h" +/* define IMPLEADERS here to get leader printing code */ +#include "../netimp/if_imp.h" +#include "../netimp/if_imphost.h" +#include /* * IMP software status per interface. @@ -60,7 +61,7 @@ struct imp_softc { * Messages from IMP regarding why * it's going down. */ -static char *impmsg[] = { +static char *impmessage[] = { "in 30 seconds", "for hardware PM", "to reload software", @@ -76,27 +77,28 @@ int impdown(), impinit(), impoutput(); * structures. This is then used by the device's attach routine * set up its back pointers. */ -impattach(ui) +impattach(ui, reset) struct uba_device *ui; + int (*reset)(); { struct imp_softc *sc = &imp_softc[ui->ui_unit]; register struct ifnet *ifp = &sc->imp_if; + struct sockaddr_in *sin; -COUNT(IMPATTACH); /* UNIT COULD BE AMBIGUOUS */ ifp->if_unit = ui->ui_unit; ifp->if_name = "imp"; - ifp->if_mtu = IMP_MTU; + ifp->if_mtu = IMPMTU - sizeof(struct imp_leader); ifp->if_net = ui->ui_flags; -#ifdef notdef - /* this should get cleaned after we talk to the imp */ - ifp->if_addr = if_makeaddr(ifp->if_net, ifp->if_host); -#endif + ifp->if_reset = reset; + /* the host and imp fields will be filled in by the imp */ + sin = (struct sockaddr_in *)&ifp->if_addr; + sin->sin_family = AF_INET; + sin->sin_addr = if_makeaddr(ifp->if_net, 0); ifp->if_init = impinit; ifp->if_output = impoutput; /* reset is handled at the hardware level */ if_attach(ifp); - /* kludge to hand pointers back to hardware attach routine */ return ((int)&sc->imp_if); } @@ -108,20 +110,26 @@ COUNT(IMPATTACH); impinit(unit) int unit; { + int s = splimp(); register struct imp_softc *sc = &imp_softc[unit]; if ((*sc->imp_cb.ic_init)(unit) == 0) { sc->imp_state = IMPS_DOWN; + sc->imp_if.if_flags &= ~IFF_UP; + splx(s); return; } sc->imp_state = IMPS_INIT; - sc->imp_dropcnt = IMP_DROPCNT; impnoops(sc); + splx(s); } struct sockproto impproto = { PF_IMPLINK }; struct sockaddr_in impdst = { AF_IMPLINK }; struct sockaddr_in impsrc = { AF_IMPLINK }; +#ifdef IMPLEADERS +int impprintfs = 0; +#endif /* * ARPAnet 1822 input routine. @@ -134,23 +142,16 @@ impinput(unit, m) int unit; register struct mbuf *m; { - int s; register struct imp_leader *ip; register struct imp_softc *sc = &imp_softc[unit]; register struct host *hp; register struct ifqueue *inq; struct control_leader *cp; struct in_addr addr; + struct mbuf *next; + struct sockaddr_in *sin; -COUNT(IMP_INPUT); -printf("impinput(%d, %x), len=%d\n", unit, m, m->m_len); -printleader("impinput", mtod(m, struct imp_leader *)); - /* - * Verify leader length. Be careful with control - * message which don't get a length included. - * We should generate a "bad leader" message - * to the IMP about messages too short. - */ + /* verify leader length. */ if (m->m_len < sizeof(struct control_leader) && (m = m_pullup(m, sizeof(struct control_leader))) == 0) return; @@ -160,45 +161,29 @@ printleader("impinput", mtod(m, struct imp_leader *)); (m = m_pullup(m, sizeof(struct imp_leader))) == 0) return; ip = mtod(m, struct imp_leader *); +#ifdef IMPLEADERS + if (impprintfs) + printleader("impinput", ip); +#endif - /* - * Check leader type -- should notify IMP - * in case of failure... - */ + /* check leader type */ if (ip->il_format != IMP_NFF) { sc->imp_if.if_collisions++; /* XXX */ goto drop; } - /* - * Certain messages require a host structure. - * Do this in one shot here. - */ - switch (ip->il_mtype) { - - case IMPTYPE_RFNM: - case IMPTYPE_INCOMPLETE: - case IMPTYPE_HOSTDEAD: - case IMPTYPE_HOSTUNREACH: - case IMPTYPE_BADDATA: + if (ip->il_mtype != IMPTYPE_DATA) { +#ifdef notdef addr.s_net = ip->il_network; +#else + addr.s_net = sc->imp_if.if_net; +#endif addr.s_imp = ip->il_imp; addr.s_host = ip->il_host; - hp = hostlookup(addr); - break; } - switch (ip->il_mtype) { - /* - * Data for a protocol. Dispatch to the appropriate - * protocol routine (running at software interrupt). - * If this isn't a raw interface, advance pointer - * into mbuf past leader (done below). - */ case IMPTYPE_DATA: - ip->il_length = - (ntohs(ip->il_length) >> 3) - sizeof(struct imp_leader); break; /* @@ -212,8 +197,8 @@ printleader("impinput", mtod(m, struct imp_leader *)); * the host resets the IMP interface. */ if (sc->imp_state != IMPS_INIT) { - imperr(sc, "leader error"); - hostreset(sc->imp_if.if_net); /* XXX */ + impmsg(sc, "leader error"); + hostreset(sc->imp_if.if_net); impnoops(sc); } goto drop; @@ -224,11 +209,14 @@ printleader("impinput", mtod(m, struct imp_leader *)); * appropriate time. */ case IMPTYPE_DOWN: + if (sc->imp_state < IMPS_INIT) + goto drop; if ((ip->il_link & IMP_DMASK) == 0) { sc->imp_state = IMPS_GOINGDOWN; - timeout(impdown, sc, 30 * hz); + timeout(impdown, (caddr_t)sc, 30 * hz); } - imperr(sc, "going down %s", impmsg[ip->il_link & IMP_DMASK]); + impmsg(sc, "going down %s", + (u_int)impmessage[ip->il_link&IMP_DMASK]); goto drop; /* @@ -236,90 +224,77 @@ printleader("impinput", mtod(m, struct imp_leader *)); * Compare the local address with that in the message. * Reset the local address notion if it doesn't match. */ - case IMPTYPE_NOOP: { - register struct in_addr *sin; - + case IMPTYPE_NOOP: if (sc->imp_state == IMPS_DOWN) { sc->imp_state = IMPS_INIT; sc->imp_dropcnt = IMP_DROPCNT; } - if (sc->imp_state != IMPS_INIT) - goto drop; - if (--sc->imp_dropcnt > 0) + if (sc->imp_state == IMPS_INIT && --sc->imp_dropcnt > 0) goto drop; + sin = (struct sockaddr_in *)&sc->imp_if.if_addr; + if (sin->sin_addr.s_host != ip->il_host || + sin->sin_addr.s_imp != ip->il_imp) { + sc->imp_if.if_host[0] = + sin->sin_addr.s_host = ip->il_host; + sin->sin_addr.s_imp = ip->il_imp; + impmsg(sc, "reset (host %d/imp %d)", (u_int)ip->il_host, + ntohs(ip->il_imp)); + } sc->imp_state = IMPS_UP; - sin = &sc->imp_if.if_addr; - sc->imp_if.if_host[0] = sin->s_host = ip->il_host; - sin->s_imp = ip->il_imp; - imperr(sc, "reset (host %d/imp %d)", ip->il_host, - ntohs(ip->il_imp)); - /* restart output in case something was q'd */ - (*sc->imp_cb.ic_start)(sc->imp_if.if_unit); + sc->imp_if.if_flags |= IFF_UP; + if_rtinit(&sc->imp_if, RTF_UP); goto drop; - } /* - * RFNM or INCOMPLETE message, record in - * host table and prime output routine. - * - * SHOULD NOTIFY PROTOCOL ABOUT INCOMPLETES. + * RFNM or INCOMPLETE message, send next + * message on the q. We could pass incomplete's + * up to the next level, but this currently isn't + * needed. */ case IMPTYPE_RFNM: case IMPTYPE_INCOMPLETE: - if (hp && hp->h_rfnm) { - register struct mbuf *n; - - hp->h_rfnm--; - /* poke holding queue */ - if (n = hp->h_q) { - if (n->m_next == n) - hp->h_q = 0; - else { - n = n->m_next; - hp->h_q->m_next = n->m_next; - } - (void) impsnd(sc, n); - break; - } + if (hp = hostlookup(addr)) { if (hp->h_rfnm == 0) - hostfree(hp); + hp->h_flags &= ~HF_INUSE; + else if (next = hostdeque(hp)) + (void) impsnd(&sc->imp_if, next); } - break; + goto drop; /* * Host or IMP can't be reached. Flush any packets * awaiting transmission and release the host structure. - * - * TODO: NOTIFY THE PROTOCOL */ case IMPTYPE_HOSTDEAD: - imperr(sc, "host dead"); /* XXX */ - goto common; /* XXX */ - - /* SHOULD SIGNAL ROUTING DAEMON */ - case IMPTYPE_HOSTUNREACH: - imperr(sc, "host unreachable"); /* XXX */ - common: - if (hp) - hostfree(hp); /* won't work right */ - break; + case IMPTYPE_HOSTUNREACH: { + int s = splnet(); + impnotify((int)ip->il_mtype, (struct control_leader *)ip, + hostlookup(addr)); + splx(s); + goto rawlinkin; + } /* * Error in data. Clear RFNM status for this host and send * noops to the IMP to clear the interface. */ - case IMPTYPE_BADDATA: - imperr(sc, "data error"); - if (hp) + case IMPTYPE_BADDATA: { + int s; + + impmsg(sc, "data error"); + s = splnet(); + if (hp = hostlookup(addr)) hp->h_rfnm = 0; + splx(s); impnoops(sc); - break; + goto drop; + } /* * Interface reset. */ case IMPTYPE_RESET: - imperr(sc, "interface reset"); + impmsg(sc, "interface reset"); impnoops(sc); goto drop; @@ -329,7 +304,10 @@ printleader("impinput", mtod(m, struct imp_leader *)); } /* - * Queue on protocol's input queue. + * Data for a protocol. Dispatch to the appropriate + * protocol routine (running at software interrupt). + * If this isn't a raw interface, advance pointer + * into mbuf past leader. */ switch (ip->il_link) { @@ -337,20 +315,27 @@ printleader("impinput", mtod(m, struct imp_leader *)); case IMPLINK_IP: m->m_len -= sizeof(struct imp_leader); m->m_off += sizeof(struct imp_leader); - setipintr(); + schednetisr(NETISR_IP); inq = &ipintrq; break; #endif default: + rawlinkin: impproto.sp_protocol = ip->il_link; - impdst.sin_addr = sc->imp_if.if_addr; + sin = (struct sockaddr_in *)&sc->imp_if.if_addr; + impdst.sin_addr = sin->sin_addr;; impsrc.sin_addr.s_net = ip->il_network; impsrc.sin_addr.s_host = ip->il_host; impsrc.sin_addr.s_imp = ip->il_imp; - raw_input(m, &impproto, &impdst, &impsrc); + raw_input(m, &impproto, (struct sockaddr *)&impsrc, + (struct sockaddr *)&impdst); return; } + if (IF_QFULL(inq)) { + IF_DROP(inq); + goto drop; + } IF_ENQUEUE(inq, m); return; @@ -364,67 +349,99 @@ drop: impdown(sc) struct imp_softc *sc; { + sc->imp_state = IMPS_DOWN; - imperr(sc, "marked down"); - /* notify protocols with messages waiting? */ + impmsg(sc, "marked down"); + hostreset(sc->imp_if.if_net); + if_down(&sc->imp_if); } /*VARARGS*/ -imperr(sc, fmt, a1, a2) +impmsg(sc, fmt, a1, a2) struct imp_softc *sc; char *fmt; + u_int a1; { + printf("imp%d: ", sc->imp_if.if_unit); printf(fmt, a1, a2); printf("\n"); } +/* + * Process an IMP "error" message, passing this + * up to the higher level protocol. + */ +impnotify(what, cp, hp) + int what; + struct control_leader *cp; + struct host *hp; +{ + struct in_addr in; + +#ifdef notdef + in.s_net = cp->dl_network; +#else + in.s_net = 10; /* XXX */ +#endif + in.s_host = cp->dl_host; + in.s_imp = cp->dl_imp; + if (cp->dl_link != IMPLINK_IP) + raw_ctlinput(what, (caddr_t)&in); + else + ip_ctlinput(what, (caddr_t)&in); + if (hp) { + hp->h_flags |= (1 << what); + hostfree(hp); + } +} + /* * ARPAnet 1822 output routine. * Called from higher level protocol routines to set up messages for * transmission to the imp. Sets up the header and calls impsnd to * enqueue the message for this IMP's hardware driver. */ -impoutput(ifp, m0, pf) +impoutput(ifp, m0, dst) register struct ifnet *ifp; struct mbuf *m0; + struct sockaddr *dst; { register struct imp_leader *imp; register struct mbuf *m = m0; - int x, dhost, dimp, dlink, len, dnet; - -COUNT(IMPOUTPUT); -printf("impoutput(%x, %x, %x)\n", ifp, m0, pf); + int dhost, dimp, dlink, len, dnet; + int error = 0; -#ifdef notdef /* * Don't even try if the IMP is unavailable. */ - x = imp_softc[ifp->if_unit].imp_state; - if (x == IMPS_DOWN || x == IMPS_GOINGDOWN) + if (imp_softc[ifp->if_unit].imp_state != IMPS_UP) { + error = ENETDOWN; goto drop; -#endif + } - switch (pf) { + switch (dst->sa_family) { #ifdef INET - case PF_INET: { - register struct ip *ip = mtod(m0, struct ip *); + case AF_INET: { + struct ip *ip = mtod(m0, struct ip *); + struct sockaddr_in *sin = (struct sockaddr_in *)dst; - dnet = ip->ip_dst.s_net; - dhost = ip->ip_dst.s_host; - dimp = ip->ip_dst.s_imp; + dhost = sin->sin_addr.s_host; + dimp = sin->sin_addr.s_impno; dlink = IMPLINK_IP; - len = ntohs(ip->ip_len); -printf("impoutput: net=%d,host=%d,imp=%d,len=%d\n",dnet,dhost,dimp,len); + dnet = 0; + len = ntohs((u_short)ip->ip_len); break; } #endif - case PF_IMPLINK: + case AF_IMPLINK: goto leaderexists; default: - printf("imp%d: can't encapsulate pf%d\n", ifp->if_unit, pf); + printf("imp%d: can't handle af%d\n", ifp->if_unit, + dst->sa_family); + error = EAFNOSUPPORT; goto drop; } @@ -435,11 +452,12 @@ printf("impoutput: net=%d,host=%d,imp=%d,len=%d\n",dnet,dhost,dimp,len); */ if (m->m_off > MMAXOFF || MMINOFF + sizeof(struct imp_leader) > m->m_off) { - m = m_get(M_DONTWAIT); - if (m == 0) + m = m_get(M_DONTWAIT, MT_HEADER); + if (m == 0) { + error = ENOBUFS; goto drop; + } m->m_next = m0; - m->m_off = MMINOFF; m->m_len = sizeof(struct imp_leader); } else { m->m_off -= sizeof(struct imp_leader); @@ -447,21 +465,20 @@ printf("impoutput: net=%d,host=%d,imp=%d,len=%d\n",dnet,dhost,dimp,len); } imp = mtod(m, struct imp_leader *); imp->il_format = IMP_NFF; + imp->il_mtype = IMPTYPE_DATA; imp->il_network = dnet; imp->il_host = dhost; - imp->il_imp = dimp; - imp->il_length = htons((len + sizeof(struct imp_leader)) << 3); + imp->il_imp = htons((u_short)dimp); + imp->il_length = + htons((u_short)(len + sizeof(struct imp_leader)) << 3); imp->il_link = dlink; + imp->il_flags = imp->il_htype = imp->il_subtype = 0; leaderexists: - /* - * Hand message to impsnd to perform RFNM counting - * and eventual transmission. - */ return (impsnd(ifp, m)); drop: m_freem(m0); - return (0); + return (error); } /* @@ -476,74 +493,66 @@ impsnd(ifp, m) register struct imp_leader *ip; register struct host *hp; struct impcb *icp; - int x; + int s, error; -COUNT(IMPSND); -printf("impsnd(%x, %x)\n", ifp, m); ip = mtod(m, struct imp_leader *); /* * Do RFNM counting for data messages * (no more than 8 outstanding to any host) */ + s = splimp(); if (ip->il_mtype == IMPTYPE_DATA) { struct in_addr addr; +#ifdef notdef addr.s_net = ip->il_network; +#else + addr.s_net = ifp->if_net; /* XXX */ +#endif addr.s_host = ip->il_host; addr.s_imp = ip->il_imp; if ((hp = hostlookup(addr)) == 0) hp = hostenter(addr); + if (hp && (hp->h_flags & (HF_DEAD|HF_UNREACH))) { + error = hp->h_flags&HF_DEAD ? EHOSTDOWN : EHOSTUNREACH; + hp->h_timer = HOSTTIMER; + hp->h_flags &= ~HF_INUSE; + goto bad; + } /* * If IMP would block, queue until RFNM */ if (hp) { - register struct mbuf *n; - int cnt; - if (hp->h_rfnm < 8) { hp->h_rfnm++; goto enque; } - /* - * Keeping the count in the host structure - * causes the packing scheme to lose too much. - */ - cnt = 0; - if (n = hp->h_q) - for (; n != hp->h_q; n = n->m_next) - cnt++; - if (cnt >= 8) - goto drop; - - /* - * Q is kept as circular list with h_q - * (head) pointing to the last entry. - */ - if ((n = hp->h_q) == 0) - hp->h_q = m->m_next = m; - else { - m->m_next = n->m_next; - hp->h_q = n->m_next = m; + if (hp->h_qcnt < 8) { /* high water mark */ + HOST_ENQUE(hp, m); + goto start; } - goto start; } -drop: - m_freem(m); - return (0); + error = ENOBUFS; + goto bad; } enque: -printleader("impsnd", mtod(m, struct imp_leader *)); - x = splimp(); + if (IF_QFULL(&ifp->if_snd)) { + IF_DROP(&ifp->if_snd); + error = ENOBUFS; +bad: + m_freem(m); + splx(s); + return (error); + } IF_ENQUEUE(&ifp->if_snd, m); - splx(x); - start: icp = &imp_softc[ifp->if_unit].imp_cb; if (icp->ic_oactive == 0) (*icp->ic_start)(ifp->if_unit); - return (1); + splx(s); + return (0); } /* @@ -551,6 +560,8 @@ start: * Part of host-IMP initialization procedure. * (Should return success/failure, but noone knows * what to do with this, so why bother?) + * This routine is always called at splimp, so we don't + * protect the call to IF_PREPEND. */ impnoops(sc) register struct imp_softc *sc; @@ -558,34 +569,23 @@ impnoops(sc) register i; register struct mbuf *m; register struct control_leader *cp; - int x; -COUNT(IMPNOOPS); - sc->imp_state = IMPS_INIT; sc->imp_dropcnt = IMP_DROPCNT; for (i = 0; i < IMP_DROPCNT + 1; i++ ) { - if ((m = m_getclr(M_DONTWAIT)) == 0) + if ((m = m_getclr(M_DONTWAIT, MT_HEADER)) == 0) return; - m->m_off = MMINOFF; m->m_len = sizeof(struct control_leader); cp = mtod(m, struct control_leader *); cp->dl_format = IMP_NFF; cp->dl_link = i; cp->dl_mtype = IMPTYPE_NOOP; -#ifdef notdef - cp->dl_network = sc->imp_if.if_net; /* XXX */ - cp->dl_host = sc->imp_if.if_addr.s_host;/* XXX */ - cp->dl_imp = sc->imp_if.if_addr.s_imp; /* XXX */ -#endif -printleader("impnoops", cp); - x = splimp(); IF_PREPEND(&sc->imp_if.if_snd, m); - splx(x); } if (sc->imp_cb.ic_oactive == 0) (*sc->imp_cb.ic_start)(sc->imp_if.if_unit); } +#ifdef IMPLEADERS printleader(routine, ip) char *routine; register struct imp_leader *ip; @@ -599,7 +599,7 @@ printleader(routine, ip) else printf("%x,", ip->il_mtype); printf("htype=%x,host=%x,imp=%x,link=", ip->il_htype, ip->il_host, - ip->il_impno); + ntohs(ip->il_imp)); if (ip->il_link == IMPLINK_IP) printf("ip,"); else @@ -622,3 +622,4 @@ printbyte(cp, n) putchar('\n'); } #endif +#endif