Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Aug 2005 13:27:51 +0100 (BST)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        net@FreeBSD.org
Cc:        sobomax@FreeBSD.org, jhb@FreeBSD.org, onoe@FreeBSD.org, joerg@FreeBSD.org, marius@FreeBSD.org, mdodd@FreeBSD.org, nyan@FreeBSD.org, imp@FreeBSD.org, yongari@FreeBSD.org
Subject:   Drivers that modify ifp->if_flags's IFF_ALLMULTI field
Message-ID:  <20050809131102.H84992@fledge.watson.org>

next in thread | raw e-mail | index | archive | help

(maintainers or effective maintainers of the affected device drivers CC'd 
-- see below for the details, sorry about dups)

I've recently been reviewing the use of if_flags with respect to network 
stack and driver locking.  Part of that work has been to break the field 
out into two separate fields: one maintained and locked by the device 
driver (if_drv_flags), and the other maintained and locked by the network 
stack (if_flags).  So far, I've moved IFF_OACTIVE and IFF_RUNNING from 
if_flags to if_drv_flags.  This change was recently committed to 7.x, and 
will be merged to 6.x prior to 6.0.

I'm now reviewing the remainder of the flags, and hit upon IFF_ALLMULTI, 
which seems generally to be an administrative flag specificying that all 
multicast packets should be accepted at the device driver layer.  This 
flag is generally set in one of three ways:

(1) if_allmulti() is invoked by network protocols wanting to specify that
     they want to see all multicast packets, such as for multicast routing.

(2) IFF_ALLMULTI is sometimes set directly by cross-driver common link
     layer code, specifically if IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)
     is matched in if_resolvemulti().

(3) Some device drivers set IFF_ALLMULTI when their multicast address
     filters overflow to indicate that all multicast traffic should and is
     being accepted, to be handled at the link or network layer.

IFF_ALLMULTI is then generally read by network device drivers in order to 
special case their multicast handling if all multicast is desired.

My feeling is that (2) and (3) are in fact bugs in device drivers and the 
IPv6 code.  Specifically:

- IFF_ALLMULTI should be set using if_allmulti(), which maintains a
   counter of consumers, which (2) bypasses.  Also, once (2) has happened,
   IFF_ALLMULTI is not disabled by the consumer.  And, it may be disabled
   by another consumer, breaking the consumer that wanted it on.  This
   should be corrected to use if_allmulti(), and ideally a symetric "now
   turn it off" should be identified.

- (3) is also a bug, as it reflects internal driver state, and will
   interfere with the administrative setting of IFF_ALLMULTI by turning it
   off even though there are consumers that want it on.  Drivers should
   maintain their forcing of the flag on or off internally.  If it is
   necesary to also expose IFF_ALLMULTI as a status flag for the device
   driver, a new flag should be introduced that is distinguished from the
   administrative state.

(3) is fairly uncommon -- most device drivers already maintain the forcing 
of the all multicast state internally in a separate flag.  The following 
device drivers do not, however:

   src/sys/dev/awi/awi.c
   src/sys/dev/gem/if_gem.c
   src/sys/dev/hme/if_hme.c
   src/sys/dev/ie/if_ie.c
   src/sys/dev/lnc/if_lnc.c
   src/sys/dev/pdq/pdq_ifsubr.c
   src/sys/dev/ray/if_ray.c
   src/sys/dev/snc/dp83932.c
   src/sys/dev/usb/if_udav.c
   src/sys/pci/if_de.c

The fix is generally pretty straight forward, and depending on the device 
driver, may or may not require adding new state to softc.

Robert N M Watson



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050809131102.H84992>