X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/a0b7c7fb19b3c0f54cdd3c30d33b8c0c2348dfbe..e431883ee1aad86d532240efa0da8b7de0e591f3:/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 455c31a23d..223dafdea1 100644 --- a/usr/src/sys/deprecated/netimp/if_imp.c +++ b/usr/src/sys/deprecated/netimp/if_imp.c @@ -1,4 +1,4 @@ -/* if_imp.c 4.3 82/02/01 */ +/* if_imp.c 4.19 82/03/19 */ #include "imp.h" #if NIMP > 0 @@ -7,6 +7,10 @@ * * 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 */ #include "../h/param.h" #include "../h/systm.h" @@ -24,7 +28,7 @@ #include "../net/in_systm.h" #include "../net/if.h" #include "../net/if_imp.h" -#include "../net/host.h" +#include "../net/if_imphost.h" #include "../net/ip.h" #include "../net/ip_var.h" @@ -37,8 +41,9 @@ * This structure contains the output queue for the interface, its * address, ... IMP specific structures used in connecting the * IMP software modules to the hardware specific interface routines - * are also stored here. These structures are visible in the interface - * driver through back pointers set up in the hardware's attach routine. + * are stored here. The common structures are made visible to the + * interface driver by passing a pointer to the hardware routine + * at "attach" time. * * NOTE: imp_if and imp_cb are assumed adjacent in hardware code. */ @@ -47,20 +52,21 @@ struct imp_softc { struct impcb imp_cb; /* hooks to hardware module */ u_char imp_state; /* current state of IMP */ char imp_dropcnt; /* used during initialization */ - short imp_timer; /* going down timer */ } imp_softc[NIMP]; /* * Messages from IMP regarding why * it's going down. */ -static char *impmsg[] = { +static char *impmessage[] = { "in 30 seconds", "for hardware PM", "to reload software", "for emergency reset" }; +int impdown(), impinit(), impoutput(); + /* * IMP attach routine. Called from hardware device attach routine * at configuration time with a pointer to the UNIBUS device structure. @@ -78,15 +84,41 @@ 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; -/* ifp->if_host = ... */ -/* ifp->if_addr = if_makeaddr(ifp->if_net, ifp->if_host); */ + /* the host and imp fields will be filled in by the imp */ + ifp->if_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); } +#ifdef notdef +/* + * Timer routine to keep priming the IMP until it sends + * us the noops we need. Since we depend on the host and + * imp values returned in the noop messages, we must wait + * for them before we allow any outgoing traffic. + */ +imptimer(sc) + register struct imp_softc *sc; +{ + int s = splimp(); + + if (sc->imp_state != IMPS_INIT) { + splx(s); + return; + } + sc->imp_dropcnt = IMP_DROPCNT; + impnoops(sc); + timeout(imptimer, (caddr_t)sc, 30 * hz); + splx(s); +} +#endif + /* * IMP initialization routine: call hardware module to * setup UNIBUS resources, init state and get ready for @@ -97,9 +129,17 @@ impinit(unit) { register struct imp_softc *sc = &imp_softc[unit]; - (*sc->imp_cb.ic_init)(unit); + if ((*sc->imp_cb.ic_init)(unit) == 0) { + sc->imp_state = IMPS_DOWN; + return; + } sc->imp_state = IMPS_INIT; +#ifdef notdef + imptimer(sc); +#else sc->imp_dropcnt = IMP_DROPCNT; + impnoops(sc); +#endif } struct sockproto impproto = { PF_IMPLINK }; @@ -113,36 +153,35 @@ struct sockaddr_in impsrc = { AF_IMPLINK }; * passed to higher level protocol processors on the basis * of link number. Other type messages (control) are handled here. */ -impinput(unit, m0) +impinput(unit, m) int unit; - struct mbuf *m0; -{ - int s; register struct mbuf *m; +{ 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; -COUNT(IMP_INPUT); - m = m0; - - /* - * We should generate a "bad leader" message - * to the IMP about messages too short. - */ - if (m->m_len < sizeof(struct imp_leader) && - m_pullup(m, sizeof(struct imp_leader)) == 0) - goto drop; +COUNT(IMPINPUT); + /* verify leader length. */ + if (m->m_len < sizeof(struct control_leader) && + (m = m_pullup(m, sizeof(struct control_leader))) == 0) + return; + cp = mtod(m, struct control_leader *); + if (cp->dl_mtype == IMPTYPE_DATA) + if (m->m_len < sizeof(struct imp_leader) && + (m = m_pullup(m, sizeof(struct imp_leader))) == 0) + return; ip = mtod(m, struct imp_leader *); - /* - * Check leader type -- should notify IMP - * in case of failure... - */ - if (ip->il_format != IMP_NFF) + /* check leader type */ + if (ip->il_format != IMP_NFF) { + sc->imp_if.if_collisions++; /* XXX */ goto drop; + } /* * Certain messages require a host structure. @@ -155,21 +194,20 @@ COUNT(IMP_INPUT); case IMPTYPE_HOSTDEAD: case IMPTYPE_HOSTUNREACH: case IMPTYPE_BADDATA: - addr.s_host = ntohs(ip->il_host); /* XXX */ - hp = h_lookup(addr); +#ifdef notdef + addr.s_net = ip->il_network; +#else + addr.s_net = 0; +#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; break; /* @@ -182,12 +220,12 @@ COUNT(IMP_INPUT); * first noop sent to the IMP after * the host resets the IMP interface. */ - if (sc->imp_state != IMPS_RESET) { - imperr(sc, "leader error"); - h_reset(sc->imp_if.if_net); /* XXX */ + if (sc->imp_state != IMPS_INIT) { + impmsg(sc, "leader error"); + hostreset(sc->imp_if.if_net); /* XXX */ impnoops(sc); } - goto drop; + goto rawlinkin; /* * IMP going down. Print message, and if not immediate, @@ -197,34 +235,36 @@ COUNT(IMP_INPUT); case IMPTYPE_DOWN: if ((ip->il_link & IMP_DMASK) == 0) { sc->imp_state = IMPS_GOINGDOWN; - timeout(impdown, sc, 30 * 60 * HZ); + timeout(impdown, (caddr_t)sc, 30 * hz); } - imperr(sc, "going down %s", impmsg[ip->il_link & IMP_DMASK]); - goto drop; + impmsg(sc, "going down %s", + (u_int)impmessage[ip->il_link&IMP_DMASK]); + goto rawlinkin; /* * A NOP usually seen during the initialization sequence. * Compare the local address with that in the message. * Reset the local address notion if it doesn't match. */ - case IMPTYPE_NOOP: + case IMPTYPE_NOOP: { + register struct in_addr *sin; + if (sc->imp_state == IMPS_DOWN) { sc->imp_state = IMPS_INIT; sc->imp_dropcnt = IMP_DROPCNT; } - if (sc->imp_state == IMPS_INIT && --sc->imp_dropcnt == 0) { - sc->imp_state = IMPS_UP; - /* restart output in case something was q'd */ - (*sc->imp_cb.ic_start)(sc->imp_if.if_unit); - } - if (ip->il_host != sc->imp_if.if_addr.s_host || - ip->il_impno != sc->imp_if.if_addr.s_imp) { - sc->imp_if.if_addr.s_host = ip->il_host; - sc->imp_if.if_addr.s_imp = ip->il_imp; - imperr(sc, "imp%d: address set to %d/%d\n", - ip->il_host, ip->il_impno); - } + if (sc->imp_state != IMPS_INIT || --sc->imp_dropcnt > 0) + goto drop; + 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; + impmsg(sc, "reset (host %d/imp %d)", (u_int)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); goto drop; + } /* * RFNM or INCOMPLETE message, record in @@ -234,63 +274,58 @@ COUNT(IMP_INPUT); */ 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_act == n) - hp->h_q = 0; - else { - n = n->m_act; - hp->h_q->m_act = n->m_act; - } - (void) impsnd(n, sc); - } - } - break; + if (hp && hp->h_rfnm) + if (next = hostdeque(hp)) + (void) impsnd(&sc->imp_if, next); + goto drop; /* * Host or IMP can't be reached. Flush any packets * awaiting transmission and release the host structure. * - * HOW DO WE NOTIFY THE PROTOCOL? - * HOW DO WE AGE THE HOST STRUCTURE TO SAVE STATUS? + * TODO: NOTIFY THE PROTOCOL */ case IMPTYPE_HOSTDEAD: + impmsg(sc, "host dead"); /* XXX */ + goto common; /* XXX */ + + /* SHOULD SIGNAL ROUTING DAEMON */ case IMPTYPE_HOSTUNREACH: + impmsg(sc, "host unreachable"); /* XXX */ + common: if (hp) - h_free(hp); /* won't work right */ - break; + hostfree(hp); /* won't work right */ + 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"); + impmsg(sc, "data error"); if (hp) hp->h_rfnm = 0; impnoops(sc); - break; + goto rawlinkin; /* * Interface reset. */ case IMPTYPE_RESET: - imperr(sc, "interface reset"); - sc->imp_state = IMPS_RESET; + impmsg(sc, "interface reset"); impnoops(sc); - goto drop; + goto rawlinkin; default: sc->imp_if.if_collisions++; /* XXX */ - goto drop; + goto rawlinkin; } /* - * 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) { @@ -298,20 +333,26 @@ COUNT(IMP_INPUT); 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; 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 *)&impdst, + (struct sockaddr *)&impsrc); return; } + if (IF_QFULL(inq)) { + IF_DROP(inq); + goto drop; + } IF_ENQUEUE(inq, m); return; @@ -325,15 +366,19 @@ drop: impdown(sc) struct imp_softc *sc; { + sc->imp_state = IMPS_DOWN; + impmsg(sc, "marked down"); /* notify protocols with messages waiting? */ } /*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"); @@ -351,8 +396,9 @@ impoutput(ifp, m0, pf) { register struct imp_leader *imp; register struct mbuf *m = m0; - int x, dhost, dimp, dlink, len; + int x, dhost, dimp, dlink, len, dnet; +COUNT(IMPOUTPUT); /* * Don't even try if the IMP is unavailable. */ @@ -367,9 +413,10 @@ impoutput(ifp, m0, pf) register struct ip *ip = mtod(m0, struct ip *); dhost = ip->ip_dst.s_host; - dimp = ip->ip_dst.s_imp; + dimp = ip->ip_dst.s_impno; dlink = IMPLINK_IP; - len = ntohs(ip->ip_len); + dnet = 0; + len = ntohs((u_short)ip->ip_len); break; } #endif @@ -400,10 +447,14 @@ impoutput(ifp, m0, pf) } 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_impno = dimp; - imp->il_length = (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: /* @@ -430,63 +481,54 @@ impsnd(ifp, m) struct impcb *icp; int x; +COUNT(IMPSND); ip = mtod(m, struct imp_leader *); /* * Do RFNM counting for data messages * (no more than 8 outstanding to any host) */ + x = splimp(); if (ip->il_mtype == IMPTYPE_DATA) { struct in_addr addr; - addr.s_net = ifp->if_net; +#ifdef notdef + addr.s_net = ip->il_network; +#else + addr.s_net = 0; +#endif addr.s_host = ip->il_host; addr.s_imp = ip->il_imp; - hp = h_enter(addr); + if ((hp = hostlookup(addr)) == 0) + hp = hostenter(addr); /* * 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, n = hp->h_q; - for (; n != (struct mbuf *)hp; n = n->m_act) - cnt++; - if (cnt >= 8) - goto drop; - - /* - * Q is kept as circulare list with h_q - * (head) pointing to the last entry. - */ - if ((n = hp->h_q) == 0) - hp->h_q = m->m_act = m; - else { - m->m_act = n->m_act; - hp->h_q = n->m_act = m; + if (hp->h_qcnt < 8) { /* high water mark */ + HOST_ENQUE(hp, m); + goto start; } - goto start; } -drop: m_freem(m); + splx(x); return (0); } enque: - x = splimp(); + if (IF_QFULL(&ifp->if_snd)) { + IF_DROP(&ifp->if_snd); + m_freem(m); + splx(x); + return (0); + } IF_ENQUEUE(&ifp->if_snd, m); - splx(x); - start: + splx(x); icp = &imp_softc[ifp->if_unit].imp_cb; if (icp->ic_oactive == 0) (*icp->ic_start)(ifp->if_unit); @@ -504,20 +546,21 @@ impnoops(sc) { register i; register struct mbuf *m; - register struct imp_leader *ip; + 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; i++ ) { + for (i = 0; i < IMP_DROPCNT + 1; i++ ) { if ((m = m_getclr(M_DONTWAIT)) == 0) return; m->m_off = MMINOFF; - m->m_len = sizeof(struct imp_leader); - ip = mtod(m, struct imp_leader *); - ip->il_format = IMP_NFF; - ip->il_link = i; - ip->il_mtype = IMPTYPE_NOOP; + 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; x = splimp(); IF_PREPEND(&sc->imp_if.if_snd, m); splx(x); @@ -525,4 +568,42 @@ impnoops(sc) 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; +{ + printf("%s: ", routine); + printbyte((char *)ip, 12); + printf("il_format, ip->il_network, + ip->il_flags); + if (ip->il_mtype <= IMPTYPE_READY) + printf("%s,", impleaders[ip->il_mtype]); + else + printf("%x,", ip->il_mtype); + printf("htype=%x,host=%x,imp=%x,link=", ip->il_htype, ip->il_host, + ntohs(ip->il_imp)); + if (ip->il_link == IMPLINK_IP) + printf("ip,"); + else + printf("%x,", ip->il_link); + printf("subtype=%x,len=%x>\n",ip->il_subtype,ntohs(ip->il_length)>>3); +} + +printbyte(cp, n) + register char *cp; + int n; +{ + register i, j, c; + + for (i=0; i>((1-j)*4))&0xf]); + putchar(' '); + } + putchar('\n'); +} +#endif #endif