Subject: kern/36592: cdce does not work: arpresolve: can't allocate llinfo on cdce0
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <khorben@defora.org>
List: netbsd-bugs
Date: 07/01/2007 23:20:00
>Number:         36592
>Category:       kern
>Synopsis:       cdce does not work: arpresolve: can't allocate llinfo on cdce0
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Jul 01 23:20:00 +0000 2007
>Originator:     khorben@defora.org
>Release:        NetBSD 4.0_BETA2
>Organization:
khorben
>Environment:
System: NetBSD syn.defora.rom 4.0_BETA2 NetBSD 4.0_BETA2 (GENERIC.MP) #6: Mon Jul 2 02:25:25 CEST 2007 khorben@syn.defora.rom:/usr/obj/sys/arch/amd64/compile/GENERIC.MP amd64
Architecture: x86_64
Machine: amd64
>Description:

Trying to communicate from NetBSD 4.0_BETA2 (amd64) to a Zaurus running
Qtopia through USB does not work. cdce0 shows up normally:

cdce0 at uhub0 port 2 configuration 1 interface 0
cdce0: Sharp SL-C3200, rev 2.00/0.00, addr 2
cdce0: faking address
cdce0: address 2a:9c:1a:00:00:00

but then after giving it directly a correct address:

# ifconfig cdce0 192.168.1.1

(when the remote peer has 192.168.1.2), reaching the Zaurus is
impossible. The kernel keeps saying:

arpresolve: can't allocate llinfo on cdce0 for 192.168.1.2

>How-To-Repeat:

Setup a Zaurus to "USB - TCP/IP (advanced)" mode and try to establish a
link. I do not own any other cdce-compliant device.

>Fix:

Manually merging the changes to if_cdce.c (1.12.10.2 to 1.12.10.3) from
the itohy-usb1 branch makes it work. I have not investigated deeper this
issue.

$ ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 data bytes
64 bytes from 192.168.1.2: icmp_seq=0 ttl=64 time=1.295 ms
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=1.395 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=1.396 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=1.396 ms
^C
----192.168.1.2 PING Statistics----
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.295/1.370/1.396/0.050 ms
$ telnet 192.168.1.2 4244
Trying 192.168.1.2...
Connected to 192.168.1.2.
Escape character is '^]'.


Index: if_cdce.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/if_cdce.c,v
retrieving revision 1.12
diff -u -r1.12 if_cdce.c
--- if_cdce.c	16 Nov 2006 01:33:26 -0000	1.12
+++ if_cdce.c	1 Jul 2007 22:35:23 -0000
@@ -109,9 +109,9 @@
 Static void	 cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
 Static void	 cdce_start(struct ifnet *);
 Static int	 cdce_ioctl(struct ifnet *, u_long, caddr_t);
-Static void	 cdce_init(void *);
+Static int	 cdce_init(struct ifnet *);
 Static void	 cdce_watchdog(struct ifnet *);
-Static void	 cdce_stop(struct cdce_softc *);
+Static void	 cdce_stop(struct ifnet *, int);
 Static uint32_t	 cdce_crc32(const void *, size_t);
 
 Static const struct cdce_type cdce_devs[] = {
@@ -280,6 +280,8 @@
 	ifp->if_ioctl = cdce_ioctl;
 	ifp->if_start = cdce_start;
 	ifp->if_watchdog = cdce_watchdog;
+	ifp->if_init = cdce_init;
+	ifp->if_stop = cdce_stop;
 	strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ);
 
 	IFQ_SET_READY(&ifp->if_snd);
@@ -310,7 +312,7 @@
 	}
 
 	if (ifp->if_flags & IFF_RUNNING)
-		cdce_stop(sc);
+		cdce_stop(ifp, 1);
 
 	ether_ifdetach(ifp);
 
@@ -376,7 +378,7 @@
 	    m->m_pkthdr.len + extra, USBD_NO_COPY, 10000, cdce_txeof);
 	err = usbd_transfer(c->cdce_xfer);
 	if (err != USBD_IN_PROGRESS) {
-		cdce_stop(sc);
+		cdce_stop(GET_IFP(sc), 0);
 		return (EIO);
 	}
 
@@ -386,10 +388,10 @@
 }
 
 Static void
-cdce_stop(struct cdce_softc *sc)
+cdce_stop(struct ifnet *ifp, int disable)
 {
+	struct cdce_softc	*sc = ifp->if_softc;
 	usbd_status	 err;
-	struct ifnet	*ifp = GET_IFP(sc);
 	int		 i;
 
 	ifp->if_timer = 0;
@@ -447,8 +449,6 @@
 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 {
 	struct cdce_softc	*sc = ifp->if_softc;
-	struct ifaddr		*ifa = (struct ifaddr *)data;
-	struct ifreq		*ifr = (struct ifreq *)data;
 	int			 s, error = 0;
 
 	if (sc->cdce_dying)
@@ -457,42 +457,22 @@
 	s = splnet();
 
 	switch(command) {
-	case SIOCSIFADDR:
-		ifp->if_flags |= IFF_UP;
-		cdce_init(sc);
-		switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
-		case AF_INET:
-#if defined(__NetBSD__)
-			arp_ifinit(ifp, ifa);
-#else
-			arp_ifinit(&sc->arpcom, ifa);
-#endif
-			break;
-#endif /* INET */
-		}
-		break;
-
-	case SIOCSIFMTU:
-		if (ifr->ifr_mtu > ETHERMTU)
-			error = EINVAL;
-		else
-			ifp->if_mtu = ifr->ifr_mtu;
+#if 0  /* no media support */
+	case SIOCGIFMEDIA:
+	case SIOCSIFMEDIA:
+		errno = EINVAL;
 		break;
+#endif
 
-	case SIOCSIFFLAGS:
-		if (ifp->if_flags & IFF_UP) {
-			if (!(ifp->if_flags & IFF_RUNNING))
-				cdce_init(sc);
-		} else {
+	default:
+		error = ether_ioctl(ifp, command, data);
+		if (error == ENETRESET) {
+#if 0  /* XXX not yet */
 			if (ifp->if_flags & IFF_RUNNING)
-				cdce_stop(sc);
+				cdce_setmulti(sc);
+#endif
+			error = 0;
 		}
-		error = 0;
-		break;
-
-	default:
-		error = EINVAL;
 		break;
 	}
 
@@ -513,30 +493,29 @@
 	printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
 }
 
-Static void
-cdce_init(void *xsc)
+Static int
+cdce_init(struct ifnet *ifp)
 {
-	struct cdce_softc	*sc = xsc;
-	struct ifnet		*ifp = GET_IFP(sc);
+	struct cdce_softc	*sc = ifp->if_softc;
 	struct cdce_chain	*c;
 	usbd_status		 err;
 	int			 s, i;
 
 	if (ifp->if_flags & IFF_RUNNING)
-		return;
+		return (EIO);
 
 	s = splnet();
 
 	if (cdce_tx_list_init(sc) == ENOBUFS) {
 		printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
 		splx(s);
-		return;
+		return (EIO);
 	}
 
 	if (cdce_rx_list_init(sc) == ENOBUFS) {
 		printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
 		splx(s);
-		return;
+		return (ENOMEM);
 	}
 
 	/* Maybe set multicast / broadcast here??? */
@@ -547,7 +526,7 @@
 		printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
 		    usbd_errstr(err));
 		splx(s);
-		return;
+		return (EIO);
 	}
 
 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
@@ -556,7 +535,7 @@
 		printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
 		    usbd_errstr(err));
 		splx(s);
-		return;
+		return (EIO);
 	}
 
 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
@@ -571,6 +550,8 @@
 	ifp->if_flags &= ~IFF_OACTIVE;
 
 	splx(s);
+
+	return (0);
 }
 
 Static int