Subject: Re: IPv6 on the Seeq 8003 -- DAD problems
To: Jun-ichiro itojun Hagino <itojun@iijlab.net>
From: Jason R Thorpe <thorpej@zembu.com>
List: tech-net
Date: 06/11/2001 23:18:26
On Fri, Jun 08, 2001 at 06:41:34PM +0900, Jun-ichiro itojun Hagino wrote:

 > >The Seeq 8003 Ethernet on the SGI Indy/Indigo2 can hear its own
 > >transmissions, and is thus NOT marked IFF_SIMPLEX.  I get:
 > >
 > >sq0: DAD detected duplicate IPv6 address fe80:0001::0a00:69ff:fe08:7645: 1 NS, 0 NA
 > >sq0: DAD complete for fe80:0001::0a00:69ff:fe08:7645 - duplicate found
 > >sq0: manual intervention required
 > >
 > >What do I need to fix?
 > 
 > 	does it loop back both multicast and unicast?  then we'll need to
 > 	have some code in sys/net/if_ethersubr.c.
 > 	!IFF_SIMPLEX interface handling is lacking, and we can't deal with
 > 	it in L3 (because ether header is already gone).

Okay, well, the following simple patch makes IPv6 work on my SGI Indy.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

Index: if_ethersubr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ethersubr.c,v
retrieving revision 1.83
diff -c -r1.83 if_ethersubr.c
*** if_ethersubr.c	2001/06/03 03:24:23	1.83
--- if_ethersubr.c	2001/06/12 06:16:03
***************
*** 661,675 ****
  		return;
  	}
  
- 	/* If the CRC is still on the packet, trim it off. */
- 	if (m->m_flags & M_HASFCS) {
- 		m_adj(m, -ETHER_CRC_LEN);
- 		m->m_flags &= ~M_HASFCS;
- 	}
- 
- 	ifp->if_lastchange = time;
- 	ifp->if_ibytes += m->m_pkthdr.len;
  	if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
  		if (memcmp(etherbroadcastaddr,
  		    eh->ether_dhost, ETHER_ADDR_LEN) == 0)
  			m->m_flags |= M_BCAST;
--- 661,678 ----
  		return;
  	}
  
  	if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
+ 		/*
+ 		 * If this is not a simplex interface, drop the packet
+ 		 * if it came from us.
+ 		 */
+ 		if ((ifp->if_flags & IFF_SIMPLEX) == 0 &&
+ 		    memcmp(LLADDR(ifp->if_sadl), eh->ether_shost,
+ 		    ETHER_ADDR_LEN) == 0) {
+ 			m_freem(m);
+ 			return;
+ 		}
+ 
  		if (memcmp(etherbroadcastaddr,
  		    eh->ether_dhost, ETHER_ADDR_LEN) == 0)
  			m->m_flags |= M_BCAST;
***************
*** 677,682 ****
--- 680,694 ----
  			m->m_flags |= M_MCAST;
  		ifp->if_imcasts++;
  	}
+ 
+ 	/* If the CRC is still on the packet, trim it off. */
+ 	if (m->m_flags & M_HASFCS) {
+ 		m_adj(m, -ETHER_CRC_LEN);
+ 		m->m_flags &= ~M_HASFCS;
+ 	}
+ 
+ 	ifp->if_lastchange = time;
+ 	ifp->if_ibytes += m->m_pkthdr.len;
  
  #if NBRIDGE > 0
  	/*