*** if_le.c Fri Jan 21 19:28:30 1994 --- if_le.c.bpf Fri Jan 21 19:40:23 1994 *************** *** 33,38 **** --- 33,43 ---- #include + #include "bpfilter.h" + #if NBPFILTER > 0 + #include + #endif + #include #include *************** *** 258,263 **** --- 263,272 ---- /* Do hardware-independent attach stuff. */ ether_attach(&es->es_if, unit, "le", leinit, leioctl, leoutput, lereset); + #if NBPFILTER > 0 + bpfattach(&es->es_bpf, &es->es_if, DLT_EN10MB, + sizeof(struct ether_header)); + #endif /* * attach interrupts and dma vectors */ *************** *** 574,580 **** --- 583,674 ---- */ if (ifp->if_flags & IFF_PROMISC) ib->ib_prom = 1; + #ifdef MULTICAST + /* + * The MULTICAST option is used to compile in support for higher- + * level (e.g., IP) multicasting. In that case, a different data + * structure is used to maintain the multicast addresses (see + * if_subr.c), and the following code for filter fiddling replaces + * Sun's original code, below. + */ + else if (ifp->if_flags & IFF_ALLMULTI) { + /* + * Turn on all 64 multicast hash bits. + */ + allmulti: ib->ib_ladrf[0] = 0xffff; + ib->ib_ladrf[1] = 0xffff; + ib->ib_ladrf[2] = 0xffff; + ib->ib_ladrf[3] = 0xffff; + } + else { + /* + * Set up multicast address filter by passing all multicast + * addresses through a crc generator, and then using the + * high order 6 bits as a index into the 64 bit logical + * address filter. The high order two bits select the word, + * while the rest of the bits select the bit within the word. + */ + struct ether_multi *enm; + struct ether_multistep step; + register u_char *cp; + register u_long crc; + register u_long c; + register int i, len; + ETHER_FIRST_MULTI(step, &es->es_ac, enm); + while (enm != NULL) { + if (ether_cmp(&enm->enm_addrlo, &enm->enm_addrhi)!= 0) + /* + * We must listen to a range of multicast + * addresses. For now, just accept all + * multicasts, rather than trying to set + * only those filter bits needed to match + * the range. (At this time, the only use + * of address ranges is for IP multicast + * routing, for which the range is big + * enough to require all bits set.) + */ + goto allmulti; + + cp = (unsigned char *)&enm->enm_addrlo; + c = *cp; + crc = 0xffffffff; + len = 6; + while (len-- > 0) { + c = *cp; + for (i = 0; i < 8; i++) { + if ((c & 0x01) ^ (crc & 0x01)) { + crc >>= 1; + crc = crc ^ 0xedb88320; + } + else + crc >>= 1; + c >>= 1; + } + cp++; + } + /* Just want the 6 most significant bits. */ + crc = crc >> 26; + + /* Turn on the corresponding bit in the filter. */ + ib->ib_ladrf[crc >> 4] |= 1 << (crc & 0xf); + + ETHER_NEXT_MULTI(step, enm); + } + + } + #ifdef notdef + /* + * Print the multicast hash table (for debugging). + */ + printf("multicast hash table: %x %x %x %x\n", + ib->ib_ladrf[3], + ib->ib_ladrf[2], + ib->ib_ladrf[1], + ib->ib_ladrf[0]); + #endif + #endif + ib->ib_padr[0] = es->es_enaddr.ether_addr_octet[1]; ib->ib_padr[1] = es->es_enaddr.ether_addr_octet[0]; ib->ib_padr[2] = es->es_enaddr.ether_addr_octet[3]; *************** *** 582,587 **** --- 676,682 ---- ib->ib_padr[4] = es->es_enaddr.ether_addr_octet[5]; ib->ib_padr[5] = es->es_enaddr.ether_addr_octet[4]; + #ifndef MULTICAST /* * Set up multicast address filter by passing all multicast * addresses through a crc generator, and then using the *************** *** 618,623 **** --- 713,719 ---- ib->ib_ladrf[crc >> 4] |= 1 << (crc & 0xf); } + #endif ib->ib_rdrp.drp_laddr = (long)es->es_rdrp; ib->ib_rdrp.drp_haddr = (long)es->es_rdrp >> 16; *************** *** 968,973 **** --- 1064,1076 ---- } } while (m = m->m_next); + #if NBPFILTER > 0 + { + struct le_softc *le = &le_softc[unit]; + if (le->es_bpf) + bpf_mtap(le->es_bpf, m0); + } + #endif /* * t points to the next free tmd. */ *************** *** 1275,1281 **** es->es_if.if_ierrors++; return; } ! /* * Pull packet off interface. Off is nonzero if packet has * trailing header; copy_to_mbufs will then force this header --- 1378,1440 ---- es->es_if.if_ierrors++; return; } ! #if NBPFILTER > 0 ! /* ! * If bpf is listening on this interface, let it ! * see the packet before we pass it up to higher ! * level protocols. ! * ! * Note that BPF doesn't currently (and hopefully never will) ! * handle trailer-encapsulated packets. We just ignore them. ! */ ! if (es->es_bpf && off == 0) { ! #ifdef BPFPROF ! register int before, after; ! /* lock out interrupts so they don't interfere with our ! measurements. */ ! (void)spl8(); ! before = COUNTER->counter14; ! #endif ! bpf_tap(es->es_bpf, (u_char *)header, ! (u_int)length + sizeof(struct ether_header)); ! #ifdef BPFPROF ! after = COUNTER->counter14; ! prof_bpf(before, after, ! (u_int)length + sizeof(struct ether_header)); ! goto bpflog_skipchk; ! #endif ! /* ! * If we are in promiscuous mode, we return if this ! * packet isn't for us. This prevents NIT from seeing ! * any promiscuous packets when there is a BPF listener. ! * The IFF_PROMISC test isn't necessary but saves the ! * bcmp() calls; it's probably worthwhile. ! */ ! if ((es->es_if.if_flags & IFF_PROMISC) && ! bcmp(header->ether_dhost.ether_addr_octet, ! es->es_enaddr.ether_addr_octet, 6) != 0 && ! #ifdef MULTICAST ! /* return only if non-multicast */ ! !(header->ether_dhost.ether_addr_octet[0] & 1)) ! #else ! bcmp(header->ether_dhost.ether_addr_octet, ! etherbroadcastaddr.ether_addr_octet, 6) != 0) ! #endif ! return; ! } ! #endif ! #ifdef BPFPROF ! /* ! * Record time spent allocating packet to mbuf, store in global ! * variables bpfprof_copy_before and bpfprof_copy_after. If this ! * packet wasn't used by this host, we charge the time to nit. ! */ ! bpflog_skipchk: ! { ! extern int bpfprof_copy_before; ! bpfprof_copy_before = COUNTER->counter14; ! } ! #endif /* * Pull packet off interface. Off is nonzero if packet has * trailing header; copy_to_mbufs will then force this header *************** *** 1354,1359 **** --- 1513,1538 ---- &((struct ifaddr *)data)->ifa_addr, &es->es_enaddr); break; + #ifdef MULTICAST + case SIOCADDMULTI: + case SIOCDELMULTI: + /* + * Update our multicast list. + */ + error = (cmd == SIOCADDMULTI) ? + ether_addmulti(ifr, &es->es_ac): + ether_delmulti(ifr, &es->es_ac); + + if (error == ENETRESET) { + /* + * Multicast list has changed; set the hardware + * filter accordingly. + */ + leinit(unit); + error = 0; + } + break; + #else /* * Set a multicast address for the interface. */ *************** *** 1377,1382 **** --- 1556,1562 ---- /* Initialize chip with new address. */ leinit(unit); break; + #endif case SIOCSIFFLAGS: /* Bring the new state into effect. */