Subject: IFF_ALLMULTI and ti/rtk/vr
To: None <tech-net@netbsd.org>
From: enami tsugutomo <enami@sm.sony.co.jp>
List: tech-net
Date: 10/02/2000 18:46:58
As far as reading the source, some driver like ti/rtk/vr doesn't DTRT
about IFF_ALLMULTI as NetBSD driver. So, probably mrouted doesn't
works with those interface.
I guess at leaset following changes are necessary. Could someone
review or test it?
enami.
Index: ic/rtl81x9.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/rtl81x9.c,v
retrieving revision 1.14
diff -u -r1.14 rtl81x9.c
--- ic/rtl81x9.c 2000/10/01 23:32:42 1.14
+++ ic/rtl81x9.c 2000/10/02 08:36:50
@@ -572,7 +572,9 @@
rxfilt = CSR_READ_4(sc, RTK_RXCFG);
- if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
+ if (ifp->if_flags & IFF_PROMISC) {
+allmulti:
+ ifp->if_flags |= IFF_ALLMULTI;
rxfilt |= RTK_RXCFG_RX_MULTI;
CSR_WRITE_4(sc, RTK_RXCFG, rxfilt);
CSR_WRITE_4(sc, RTK_MAR0, 0xFFFFFFFF);
@@ -589,7 +591,7 @@
while (enm != NULL) {
if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
ETHER_ADDR_LEN) != 0)
- continue;
+ goto allmulti;
h = rtk_calchash(enm->enm_addrlo);
if (h < 32)
@@ -599,6 +601,8 @@
mcnt++;
ETHER_NEXT_MULTI(step, enm);
}
+
+ ifp->if_flags &= ~IFF_ALLMULTI;
if (mcnt)
rxfilt |= RTK_RXCFG_RX_MULTI;
Index: pci/if_vr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_vr.c,v
retrieving revision 1.38
diff -u -r1.38 if_vr.c
--- pci/if_vr.c 2000/10/01 23:32:44 1.38
+++ pci/if_vr.c 2000/10/02 08:36:52
@@ -479,7 +479,9 @@
rxfilt = CSR_READ_1(sc, VR_RXCFG);
- if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
+ if (ifp->if_flags & IFF_PROMISC) {
+allmulti:
+ ifp->if_flags |= IFF_ALLMULTI;
rxfilt |= VR_RXCFG_RX_MULTI;
CSR_WRITE_1(sc, VR_RXCFG, rxfilt);
CSR_WRITE_4(sc, VR_MAR0, 0xFFFFFFFF);
@@ -494,8 +496,9 @@
/* now program new ones */
ETHER_FIRST_MULTI(step, &sc->vr_ec, enm);
while (enm != NULL) {
- if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0)
- continue;
+ if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
+ ETHER_ADDR_LEN) != 0)
+ goto allmulti;
h = vr_calchash(enm->enm_addrlo);
@@ -506,6 +509,8 @@
ETHER_NEXT_MULTI(step, enm);
mcnt++;
}
+
+ ifp->if_flags &= ~IFF_ALLMULTI;
if (mcnt)
rxfilt |= VR_RXCFG_RX_MULTI;
Index: pci/if_ti.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_ti.c,v
retrieving revision 1.11
diff -u -r1.11 if_ti.c
--- pci/if_ti.c 2000/10/01 23:32:43 1.11
+++ pci/if_ti.c 2000/10/02 08:36:53
@@ -1205,40 +1205,62 @@
ifp = &sc->ethercom.ec_if;
- if (ifp->if_flags & IFF_ALLMULTI) {
- TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_ENB, 0);
- return;
- } else {
- TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_DIS, 0);
- }
-
/* Disable interrupts. */
intrs = CSR_READ_4(sc, TI_MB_HOSTINTR);
CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
/* First, zot all the existing filters. */
- while (SIMPLEQ_FIRST(&sc->ti_mc_listhead) != NULL) {
- mc = SIMPLEQ_FIRST(&sc->ti_mc_listhead);
+ while ((mc = SIMPLEQ_FIRST(&sc->ti_mc_listhead)) != NULL) {
ti_del_mcast(sc, &mc->mc_addr);
SIMPLEQ_REMOVE_HEAD(&sc->ti_mc_listhead, mc, mc_entries);
free(mc, M_DEVBUF);
}
- /* Now program new ones. */
+ /*
+ * Remember all multicast addresses so that we can delete them
+ * later. Punt if there is a range of addresses or memory shortage.
+ */
ETHER_FIRST_MULTI(step, &sc->ethercom, enm);
while (enm != NULL) {
- mc = malloc(sizeof(struct ti_mc_entry), M_DEVBUF, M_NOWAIT);
- bcopy(enm->enm_addrlo,
- (char *)&mc->mc_addr, ETHER_ADDR_LEN);
+ if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
+ ETHER_ADDR_LEN) != 0)
+ goto allmulti;
+ if ((mc = malloc(sizeof(struct ti_mc_entry), M_DEVBUF,
+ M_NOWAIT)) == NULL)
+ goto allmulti;
+ memcpy(&mc->mc_addr, enm->enm_addrlo, ETHER_ADDR_LEN);
SIMPLEQ_INSERT_HEAD(&sc->ti_mc_listhead, mc, mc_entries);
- ti_add_mcast(sc, &mc->mc_addr);
ETHER_NEXT_MULTI(step, enm);
}
+ /* Accept only programmed multicast addresses */
+ ifp->if_flags &= ~IFF_ALLMULTI;
+ TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_DIS, 0);
+
+ /* Now program new ones. */
+ for (mc = SIMPLEQ_FIRST(&sc->ti_mc_listhead); mc != NULL;
+ mc = SIMPLEQ_NEXT(mc, mc_entries))
+ ti_add_mcast(sc, &mc->mc_addr);
+
/* Re-enable interrupts. */
CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs);
return;
+
+allmulti:
+ /* No need to keep individual multicast addresses */
+ while ((mc = SIMPLEQ_FIRST(&sc->ti_mc_listhead)) != NULL) {
+ SIMPLEQ_REMOVE_HEAD(&sc->ti_mc_listhead, mc,
+ mc_entries);
+ free(mc, M_DEVBUF);
+ }
+
+ /* Accept all multicast addresses */
+ ifp->if_flags |= IFF_ALLMULTI;
+ TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_ENB, 0);
+
+ /* Re-enable interrupts. */
+ CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs);
}
/*
@@ -1784,6 +1806,8 @@
goto fail2;
}
+ SIMPLEQ_INIT(&sc->ti_mc_listhead);
+
/* Set default tuneable values. */
sc->ti_stat_ticks = 2 * TI_TICKS_PER_SEC;
sc->ti_rx_coal_ticks = TI_TICKS_PER_SEC / 5000;
@@ -2557,12 +2581,12 @@
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
- if (command == SIOCADDMULTI)
- ether_addmulti(ifr, &sc->ethercom);
- else
- ether_delmulti(ifr, &sc->ethercom);
- if (ifp->if_flags & IFF_RUNNING) {
- ti_setmulti(sc);
+ error = (command == SIOCADDMULTI) ?
+ ether_addmulti(ifr, &sc->ethercom) :
+ ether_delmulti(ifr, &sc->ethercom);
+ if (error == ENETRESET) {
+ if (ifp->if_flags & IFF_RUNNING)
+ ti_setmulti(sc);
error = 0;
}
break;