Subject: port-vax/2796: vax if_qe lacks multicast, bpf +FIX
To: None <gnats-bugs@gnats.netbsd.org>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: netbsd-bugs
Date: 10/02/1996 03:37:59
>Number: 2796
>Category: port-vax
>Synopsis: vax if_qe lacks multicast, bpf +FIX
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Wed Oct 2 03:50:01 1996
>Last-Modified:
>Originator: Jonathan Stone
>Organization:
Stanford DSG
>Release: 1.2
>Environment:
System: NetBSD Cup.DSG.Stanford.EDU 1.2_BETA NetBSD 1.2_BETA (DSG) #47: Mon Jul 29 12:05:57 PDT 1996 jonathan@Cup.DSG.Stanford.EDU:/aga/n1/src/NetBSD/IP-PLUS/src/sys/arch/i386/compile/DSG i386
this problem report has _nothing_ to do with the above machine
>Description:
The vax qe (and de) drivers lack multicast support.
They also lack bpf support.
>How-To-Repeat:
Try any BPF-based application
Try running tcpdump on NetBSD/vax.
Try using NetBSD/vax as a MOP server.
Try the LBL tools, or any other IP multicast app
(e.g., pinging the 224.0.0.1 address).
Watch NetBSD/vax not respond.
>Fix:
The following patch for if_qe.c is untested, but probably
basically correct. Similar patches worked on -Tahoe and -reno.
It could do with a compile with -Wall -Wstrict-rpototypes,
and review of the multicast-filter update code.
Note that i have added BFP hooks into the qe driver
rather than into the if_uba support code deliberately;
the if_uba code cannot do the the bpfattach(),
so I think the bpf wiretaps should be duplicated here
and in if_de.c.
NetBSD doesn't really support IFF_ALMULTI; the support
for adding more than 16 multicast filters probably needs
work. As noted, the ISO support in 4.4-Lite is broken,
and needs reworking to coexist with IPmulticast.
Calling up the stack to ether_addmulti(), instead of inling
ISO addresses, is probably the right thing to do.
Better support for DELQA native "turbo" mode is possible
and should be implemented.
Index: if_qe.c
===================================================================
RCS file: /cvsroot/src/sys/arch/vax/if/if_qe.c,v
retrieving revision 1.16
diff -c -r1.16 if_qe.c
*** if_qe.c 1996/08/20 14:07:42 1.16
--- if_qe.c 1996/10/02 10:24:50
***************
*** 136,142 ****
--- 136,146 ----
/*
* Digital Q-BUS to NI Adapter
+ * supports DEQNA and DELQA in DEQNA-mode.
*/
+
+ #include "bpfilter.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
***************
*** 173,181 ****
extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];
#endif
#include <machine/pte.h>
#include <machine/cpu.h>
! #include <machine/mtpr.h>
#include <vax/if/if_qereg.h>
#include <vax/if/if_uba.h>
--- 177,198 ----
extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];
#endif
+ #if defined(CCITT) && defined(LLC)
+ #include <sys/socketvar.h>
+ #include <netccitt/x25.h>
+ #include <netccitt/pk.h>
+ #include <netccitt/pk_var.h>
+ #include <netccitt/pk_extern.h>
+ #endif
+
+ #if NBPFILTER > 0
+ #include <net/bpf.h>
+ #include <net/bpfdesc.h>
+ #endif
+
#include <machine/pte.h>
#include <machine/cpu.h>
! #include <machine/mtpr.h> /* XXX Qbus mips? */
#include <vax/if/if_qereg.h>
#include <vax/if/if_uba.h>
***************
*** 224,229 ****
--- 241,247 ----
int qe_intvec; /* Interrupt vector */
struct qedevice *addr; /* device addr */
int setupqueued; /* setup packet queued */
+ int setuplength; /* length of setup packet */
int nxmit; /* Transmits in progress */
int qe_restarts; /* timeouts */
};
***************
*** 369,375 ****
* The Deqna is cable of transmitting broadcasts, but
* doesn't listen to its own.
*/
! ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
/*
* Read the address from the prom and save it.
--- 387,394 ----
* The Deqna is cable of transmitting broadcasts, but
* doesn't listen to its own.
*/
! ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST |IFF_SIMPLEX |
! IFF_NOTRAILERS;
/*
* Read the address from the prom and save it.
***************
*** 394,399 ****
--- 413,424 ----
sc->qe_uba.iff_flags = UBA_CANTWAIT;
if_attach(ifp);
ether_ifattach(ifp);
+
+ #if NBPFILTER > 0
+ bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
+ #endif
+
+
}
/*
***************
*** 540,546 ****
rp = &sc->tring[index];
if( sc->setupqueued ) {
buf_addr = sc->setupaddr;
! len = 128;
rp->qe_setup = 1;
sc->setupqueued = 0;
} else {
--- 565,571 ----
rp = &sc->tring[index];
if( sc->setupqueued ) {
buf_addr = sc->setupaddr;
! len = sc->setuplength;
rp->qe_setup = 1;
sc->setupqueued = 0;
} else {
***************
*** 549,554 ****
--- 574,583 ----
splx(s);
return;
}
+ #if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+ #endif
buf_addr = sc->qe_ifw[index].ifw_info;
len = if_ubaput(&sc->qe_uba, &sc->qe_ifw[index], m);
}
***************
*** 768,773 ****
--- 797,803 ----
{
struct qe_softc *sc = ifp->if_softc;
struct ifaddr *ifa = (struct ifaddr *)data;
+ struct ifreq *ifr = (struct ifreq *)data;
int s = splnet(), error = 0;
switch (cmd) {
***************
*** 804,809 ****
--- 834,863 ----
} else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
IFF_RUNNING && (sc->qe_flags & QEF_RUNNING) == 0)
qerestart(sc);
+ else
+ /*
+ * In case IFF_PROMISC or IFF_ALLMULTI has changed.
+ */
+ qesetup(sc);
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ /*
+ * Update our multicast list.
+ */
+ error = (cmd == SIOCADDMULTI) ?
+ ether_addmulti(ifr, &sc->qe_ac):
+ ether_delmulti(ifr, &sc->qe_ac);
+
+ if (error == ENETRESET) {
+ /*
+ * Multicast list has changed; set the hardware filter
+ * accordingly.
+ */
+ qesetup(sc);
+ error = 0;
+ }
break;
default:
***************
*** 878,890 ****
--- 932,989 ----
*/
for (i = 0; i < 6; i++) {
sc->setup_pkt[i][2] = 0xff;
+
+
#ifdef ISO
+ /*
+ * XXX layer violation, should use SIOCADDMULTI.
+ * Will definitely break with IPmulticast.
+ */
sc->setup_pkt[i][3] = all_es_snpa[i];
sc->setup_pkt[i][4] = all_is_snpa[i];
sc->setup_pkt[i][5] = all_l1is_snpa[i];
sc->setup_pkt[i][6] = all_l2is_snpa[i];
#endif
}
+ if (sc->qe_if.if_flags & IFF_PROMISC) {
+ sc->setuplength = QE_PROMISC;
+ }
+ /* XXX no IFF_ALLMULTI support in 4.4bsd */
+ else if (sc->qe_if.if_flags & IFF_ALLMULTI) {
+ sc->setuplength = QE_ALLMULTI;
+ }
+ else {
+ register k;
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ /*
+ * Step through our list of multicast addresses, putting them
+ * in the third through fourteenth address slots of the setup
+ * packet. (See the DEQNA manual to understand the peculiar
+ * layout of the bytes within the setup packet.) If we have
+ * too many multicast addresses, or if we have to listen to
+ * a range of multicast addresses, turn on reception of all
+ * multicasts.
+ */
+ sc->setuplength = QE_SOMEMULTI;
+ i = 2;
+ k = 0;
+ ETHER_FIRST_MULTI(step, &sc->qe_ac, enm);
+ while (enm != NULL) {
+ if ((++i > 7 && k != 0) ||
+ bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
+ sc->setuplength = QE_ALLMULTI;
+ break;
+ }
+ if (i > 7) {
+ i = 1;
+ k = 8;
+ }
+ for (j = 0; j < 6; j++)
+ sc->setup_pkt[j+k][i] = enm->enm_addrlo[j];
+ ETHER_NEXT_MULTI(step, enm);
+ }
+ }
sc->setupqueued++;
}
***************
*** 911,916 ****
--- 1010,1016 ----
if (len == 0)
return;
+
/*
* Pull packet off interface. Off is nonzero if packet
* has trailing header; qeget will then force this header
***************
*** 924,930 ****
*(((u_long *)m->m_data)+1),
*(((u_long *)m->m_data)+2),
*(((u_long *)m->m_data)+3)
! ); }
#endif
if (m)
--- 1024,1053 ----
*(((u_long *)m->m_data)+1),
*(((u_long *)m->m_data)+2),
*(((u_long *)m->m_data)+3)
! ; }
! #endif
!
! #if NBPFILTER > 0
! /*
! * Check if there's a BPF listener on this interface.
! * If so, hand off the raw packet to BPF.
! */
! if (ifp->if_bpf) {
! bpf_mtap(ifp->if_bpf, m);
!
! /*
! * Note that the interface cannot be in promiscuous mode if
! * there are no BPF listeners. And if we are in promiscuous
! * mode, we have to check if this packet is really ours.
! */
! if ((ifp->if_flags & IFF_PROMISC) &&
! (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
! bcmp(eh->ether_dhost, sc->qe_arpcom.ac_enaddr,
! sizeof(eh->ether_dhost)) != 0) {
! m_freem(m);
! return;
! }
! }
#endif
if (m)
Index: if_qereg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/vax/if/if_qereg.h,v
retrieving revision 1.1
diff -c -r1.1 if_qereg.h
*** if_qereg.h 1995/03/30 20:26:41 1.1
--- if_qereg.h 1996/10/02 10:24:51
***************
*** 170,172 ****
--- 170,179 ----
#define QE_NOTYET 0x8000 /* Descriptor not in use yet */
#define QE_INUSE 0x4000 /* Descriptor being used by QNA */
#define QE_MASK 0xc000 /* Lastnot/error/used mask */
+
+ /*
+ * Values for the length of the setup packet that control reception filter.
+ */
+ #define QE_SOMEMULTI 128 /* Receive up to 12 multicasts */
+ #define QE_ALLMULTI 129 /* Receive all multicasts */
+ #define QE_PROMISC 130 /* Receive all packets */
>Audit-Trail:
>Unformatted: