From owner-freebsd-bugs Wed Jun 18 13:40:03 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.5/8.8.5) id NAA09997 for bugs-outgoing; Wed, 18 Jun 1997 13:40:03 -0700 (PDT) Received: (from gnats@localhost) by hub.freebsd.org (8.8.5/8.8.5) id NAA09983; Wed, 18 Jun 1997 13:40:02 -0700 (PDT) Resent-Date: Wed, 18 Jun 1997 13:40:02 -0700 (PDT) Resent-Message-Id: <199706182040.NAA09983@hub.freebsd.org> Resent-From: gnats (GNATS Management) Resent-To: freebsd-bugs Resent-Reply-To: FreeBSD-gnats@FreeBSD.ORG, dcurtis@lcs.mit.edu Received: from ananke.lcs.mit.edu (ananke.lcs.mit.edu [18.26.0.154]) by hub.freebsd.org (8.8.5/8.8.5) with ESMTP id NAA09867 for ; Wed, 18 Jun 1997 13:36:57 -0700 (PDT) Received: (from dcurtis@localhost) by ananke.lcs.mit.edu (8.8.5/8.8.5) id QAA00410; Wed, 18 Jun 1997 16:36:45 -0400 (EDT) Message-Id: <199706182036.QAA00410@ananke.lcs.mit.edu> Date: Wed, 18 Jun 1997 16:36:45 -0400 (EDT) From: dcurtis@lcs.mit.edu Reply-To: dcurtis@lcs.mit.edu To: FreeBSD-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: 3.2 Subject: kern/3901: Improving multicast for Intel 10/100 Ethernet cards Sender: owner-bugs@FreeBSD.ORG X-Loop: FreeBSD.org Precedence: bulk >Number: 3901 >Category: kern >Synopsis: Multicast for Intel 10/100 Ethernet Card >Confidential: no >Severity: non-critical >Priority: high >Responsible: freebsd-bugs >State: open >Class: change-request >Submitter-Id: current-users >Arrival-Date: Wed Jun 18 13:40:00 PDT 1997 >Last-Modified: >Originator: Dorothy Curtis >Organization: MIT/LCS >Release: FreeBSD 3.0-CURRENT i386 >Environment: Not applicable. >Description: The existing driver for the Intel 10/100 Ethernet card behaves suboptimally in supporting multicast: it passes all multicast traffic through to the kernel for filtering. The supplied patches enhance the driver to use the card's hardware multicast filtering feature, thus offloading the address filtering from the cpu. Also included is a fix to if.c so that the interface is notified when a multicast address is deleted. >How-To-Repeat: Currently, assuming you are on a net with multicast traffic, tcpdump -p ip multicast shows all of the multicast traffic. With the following fix, the above command shows almost no traffic: occasional messages directed to ALL-SYSTEMS.MCAST.NET should appear, but no others. The mtest program can be used to join and leave multicast groups. The above tcpdump command will show messages from the groups that have been joined. When a group has been left, no messages will appear from that group. (Note that quitting the mtest program leaves all groups.) >Fix: Three patches follow for /usr/src/sys/pci/if_fxpreg.h /usr/src/sys/pci/if_fxp.c /usr/src/sys/net/if.c --- /usr/src/sys/pci/if_fxpreg.h Wed Jun 18 13:01:07 1997 +++ /new/usr/src/sys/pci/if_fxpreg.h Wed Jun 18 13:02:18 1997 @@ -102,6 +102,23 @@ volatile u_int32_t link_addr; volatile u_int8_t macaddr[6]; }; + +/* + * Multicast support + */ +#define MAXMCAST 50 +struct fxp_en_addr { + u_char data[6]; +}; + +struct fxp_cb_mas { + volatile u_int16_t cb_status; + volatile u_int16_t cb_command; + volatile u_int32_t link_addr; + volatile u_int16_t mcast_bytes; + volatile struct fxp_en_addr mcast_addrs[MAXMCAST+1]; +}; + /* I hate bit-fields :-( */ struct fxp_cb_config { volatile u_int16_t cb_status; --- /usr/src/sys/pci/if_fxp.c Wed Jun 18 13:00:47 1997 +++ /new/usr/src/sys/pci/if_fxp.c Wed Jun 18 15:21:07 1997 @@ -28,6 +28,13 @@ */ /* + * 3/25/97: dcurtis: improved multicast handling by stealing code + * from GAWollman's if_ie.c. This change enables control of the card's + * multicast address filtering per IOCTL calls from user code. By using + * the hardware filtering work is offloaded from the cpu. + */ + +/* * Intel EtherExpress Pro/100B PCI Fast Ethernet driver */ @@ -91,6 +98,8 @@ int phy_primary_addr; /* address of primary PHY */ int phy_primary_device; /* device type of primary PHY */ int phy_10Mbps_only; /* PHY is 10Mbps-only device */ + int mcast_count; /* count of mcast addrs */ + struct fxp_en_addr mcast_addrs[MAXMCAST+1]; /* array of mcast addrs */ }; static u_long fxp_count; @@ -810,6 +819,42 @@ fxp_init(ifp->if_softc); } +static int +fxp_mc_reset(struct fxp_softc *sc) { + struct ifmultiaddr *ifma; + struct ifnet *ifp; + + /* + * Step through the list of addresses. + */ + + sc->mcast_count = 0; + for (ifma = sc->arpcom.ac_if.if_multiaddrs.lh_first; ifma; + ifma = ifma->ifma_link.le_next) { + char *eaptr; + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + + if(sc->mcast_count >= MAXMCAST) { + ifp = &sc->arpcom.ac_if; + printf("fxp%d: warning: exceeded max (%d) multicast addrs\n", + ifp->if_unit, MAXMCAST); + return 1; + } + bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), + &(sc->mcast_addrs[sc->mcast_count]), 6); +#ifdef FXP_DEBUG + eaptr = &(sc->mcast_addrs[sc->mcast_count]); + printf("copying in %dth\n", sc->mcast_count); + printf("addr = %d:%d:%d:%d:%d:%d\n", + eaptr[0], eaptr[1], eaptr[2], eaptr[3], eaptr[4], eaptr[5]); +#endif + sc->mcast_count++; + } + return 0; +} + + static void fxp_init(xsc) void *xsc; @@ -818,6 +863,7 @@ struct ifnet *ifp = &sc->arpcom.ac_if; struct fxp_cb_config *cbp; struct fxp_cb_ias *cb_ias; + struct fxp_cb_mas *cb_mas; struct fxp_cb_tx *txp; struct fxp_csr *csr = sc->csr; int i, s, mcast, prm; @@ -830,13 +876,18 @@ prm = (ifp->if_flags & IFF_PROMISC) ? 1 : 0; sc->promisc_mode = prm; + /* - * Sleeze out here and enable reception of all multicasts if - * multicasts are enabled. Ideally, we'd program the multicast - * address filter to only accept specific multicasts. + * Handle multicast addresses. */ - mcast = (ifp->if_flags & (IFF_MULTICAST|IFF_ALLMULTI)) ? 1 : 0; + mcast = fxp_mc_reset(sc); + /* + * Set mcast if IFF_ALLMULTI is set. + * (It may have already been set if there were too many discrete * multicast addrs.) + */ + mcast |= ((ifp->if_flags & IFF_ALLMULTI)) ? 1 : 0; + /* * Initialize base of CBL and RFA memory. Loading with zero * sets it up for regular linear addressing. @@ -931,6 +982,30 @@ while (!(cb_ias->cb_status & FXP_CB_STATUS_C)); /* + * Program the multicast addresses, if any. Temporarily use + * the TxCB memory area as above. + */ + if (sc->mcast_count) { + cb_mas = (struct fxp_cb_mas *) sc->cbl_base; + cb_mas->cb_status = 0; + cb_mas->cb_command = FXP_CB_COMMAND_MAS | FXP_CB_COMMAND_EL; + cb_mas->link_addr = -1; + + bcopy(sc->mcast_addrs, (void *)cb_mas->mcast_addrs, + sc->mcast_count * sizeof *sc->mcast_addrs); + cb_mas->mcast_bytes = sc->mcast_count * 6; /* grrr... */ + + /* + * Start the MAS (Multicast Address Setup) command/DMA. + */ + fxp_scb_wait(csr); + csr->scb_command = FXP_SCB_COMMAND_CU_START; + /* ...and wait for it to complete. */ + while (!(cb_ias->cb_status & FXP_CB_STATUS_C)); + } + + + /* * Initialize transmit control block (TxCB) list. */ @@ -1157,6 +1232,9 @@ * Multicast list has changed; set the hardware filter * accordingly. */ +#ifdef FXP_DEBUG + printf("calling fxp_init due to SIOCADD/DELMULTI\n"); +#endif fxp_init(sc); error = 0; break; --- /usr/src/sys/net/if.c Wed Jun 18 13:01:25 1997 +++ /new/usr/src/sys/net/if.c Wed Jun 18 15:31:08 1997 @@ -943,8 +943,12 @@ splx(s); free(ifma->ifma_addr, M_IFMADDR); free(ifma, M_IFMADDR); - if (sa == 0) + if (sa == 0) { + s = splimp(); + ifp->if_ioctl(ifp, SIOCDELMULTI, 0); + splx(s); return 0; + } /* * Now look for the link-layer address which corresponds to @@ -971,6 +975,7 @@ s = splimp(); LIST_REMOVE(ifma, ifma_link); + ifp->if_ioctl(ifp, SIOCDELMULTI, 0); splx(s); free(ifma->ifma_addr, M_IFMADDR); free(sa, M_IFMADDR); >Audit-Trail: >Unformatted: