chris@umcp-cs.UUCP (07/21/84)
Well, you didn't say what interface you were using, or which version of the BBN code, but we found & fixed two nasty problems in il.c in sys10. They both have to do with flushing packets in ilrint(). The first ubaremap()ed virtual address 14 (not even in kernel space!) to the UNIBUS; the second dropped all packets longer than a single mbuf once an error occurred on the interface. The (unrewritten but working) code: /* * Ethernet interface receiver interrupt. * If input error just drop packet. Use frame header info in first packet * for data chaining. */ ilrint(unit) int unit; { register struct ifcb *ip = &ilifcb[unit]; register struct uba_device *ui = ilinfo[unit]; register struct ildevice *addr = (struct ildevice *)ui->ui_addr; register struct il_rheader *l; register struct mbuf *m, *n; if ((m = ip->if_inq_cur) == NULL) return; /* * If frame input length is zero, we expect start of a new frame. * Get total frame length from rheader, and check status and lengths * for errors. */ if (ip->if_ilen == 0) { l = mtod(m, struct il_rheader *); ip->if_ilen = l->ilr_length + 4; #ifdef ILDEBUG printf("il%d: read done ", unit); ilprt("RCV", (int)l+2); printf("\n"); #endif if (l->ilr_status&0x3 || ip->if_ilen < 46+sizeof(struct il_rheader) || ip->if_ilen > ILMTU) { ip->if_error = TRUE; ip->if_ierrs++; #ifdef notdef if (ip->if_ierrs % 100 == 0) printf("il%d: += 100 input errors\n", unit); #endif printf("il%d: input error (status=%x, len=%d)\n", unit, l->ilr_status, ip->if_ilen); goto flush; } } m->m_len = MRND8 - addr->il_bcr; if (ip->if_ilen <= MRND8) { /* end of message */ /* * Queue good packet for input processing and awaken net * input process */ ip->if_ilen = 0; if (!ip->if_flush) { ip->if_ipkts++; #ifndef SOFTINT if (ip->if_inq_hd != NULL) ip->if_inq_tl->m_act = ip->if_inq_msg; else ip->if_inq_hd = ip->if_inq_msg; ip->if_inq_tl = ip->if_inq_msg; ip->if_inq_msg = NULL; if (netcb.n_flags & NASLEEP) { netcb.n_flags &= ~NASLEEP; wakeup((caddr_t)&netcb.n_ifcb_hd); } #else ilrcv(ip); #endif SOFTINT } /* * Get buffer for next packet to be read. */ if ((n = m_get(0)) != NULL) { /* * Got a buffer; fill it in. */ ip->if_flush = FALSE; ip->if_ilen = 0; n->m_off = MHEAD; ip->if_inq_msg = n; ip->if_inq_cur = n; } else { flush: /* * No more buffers: flush */ ip->if_flush = TRUE; ip->if_inq_msg = n = (struct mbuf *)&netflush; ip->if_flushes++; } } else { /* * Not end of packet; if not flushing * try to get more buffers. If there is * an error or no more buffers free partial message. */ ip->if_ilen -= m->m_len; if (!ip->if_flush) { if (!ip->if_error && (n = m_get(0)) != NULL) { m->m_next = n; n->m_off = MHEAD; ip->if_inq_cur = n; } else { m_freem(ip->if_inq_msg); ip->if_flush = TRUE; ip->if_error = FALSE; n = (struct mbuf *)&netflush; ip->if_inq_cur = n; ip->if_inq_msg = n; ip->if_flushes++; } } else n = &netflush; /* Continue flushing */ } /* * Reset for next packet if possible. * If waiting for transmit command completion, set flag * and wait until command completes. */ setup: if (!ip->if_active) ilread(ip, (caddr_t)((int)n + MHEAD), MRND8); else ip->if_startrcv = TRUE; } -- In-Real-Life: Chris Torek, Univ of MD Comp Sci (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland