FreeBSD/sys/net/if_vlan.c
/*
 * Program our multicast filter. What we're actually doing is
 * programming the multicast filter of the parent. This has the
 * side effect of causing the parent interface to receive multicast
 * traffic that it doesn't really want, which ends up being discarded
 * later by the upper protocol layers. Unfortunately, there's no way
 * to avoid this: there really is only one physical interface.
 */
Program our multicast filter. What we're actually doing is
programming the multicast filter of the parent. This has the
side effect of causing the parent interface to receive multicast
traffic that it doesn't really want, which ends up being discarded
later by the upper protocol layers. Unfortunately, there's no way
to avoid this: there really is only one physical interface.
Program our multicast filter . What we ' re actually doing is programming the multicast filter of the parent . This has the side effect of causing the parent interface to receive multicast traffic that it doesn ' t really want which ends up being discarded later by the upper protocol layers . Unfortunately there ' s no way to avoid this : there really is only one physical interface .
static int
vlan_setmulti(struct ifnet *ifp)
{
	struct ifnet		*ifp_p;
	struct ifmultiaddr	*ifma;
	struct ifvlan		*sc;
	struct vlan_mc_entry	*mc;
	int			error;
	sc = ifp->if_softc;
	TRUNK_LOCK_ASSERT(TRUNK(sc));
	ifp_p = PARENT(sc);
	CURVNET_SET_QUIET(ifp_p->if_vnet);
	while ((mc = SLIST_FIRST(&sc->vlan_mc_listhead)) != NULL) {
		SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries);
		(void)if_delmulti(ifp_p, (struct sockaddr *)&mc->mc_addr);
		free(mc, M_VLAN);
	}
	IF_ADDR_WLOCK(ifp);
	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
		if (ifma->ifma_addr->sa_family != AF_LINK)
			continue;
		mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT);
		if (mc == NULL) {
			IF_ADDR_WUNLOCK(ifp);
			return (ENOMEM);
		}
		bcopy(ifma->ifma_addr, &mc->mc_addr, ifma->ifma_addr->sa_len);
		mc->mc_addr.sdl_index = ifp_p->if_index;
		SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries);
	}
	IF_ADDR_WUNLOCK(ifp);
	SLIST_FOREACH (mc, &sc->vlan_mc_listhead, mc_entries) {
		error = if_addmulti(ifp_p, (struct sockaddr *)&mc->mc_addr,
		    NULL);
		if (error)
			return (error);
	}
	CURVNET_RESTORE();
	return (0);
}
static int vlan_setmulti ( struct ifnet * ifp ) { struct ifnet * ifp_p ; struct ifmultiaddr * ifma ; struct ifvlan * sc ; struct vlan_mc_entry * mc ; int error ; sc = ifp -> if_softc ; TRUNK_LOCK_ASSERT ( TRUNK ( sc ) ) ; ifp_p = PARENT ( sc ) ; CURVNET_SET_QUIET ( ifp_p -> if_vnet ) ; while ( ( mc = SLIST_FIRST ( & sc -> vlan_mc_listhead ) ) != NULL ) { SLIST_REMOVE_HEAD ( & sc -> vlan_mc_listhead , mc_entries ) ; ( void ) if_delmulti ( ifp_p , ( struct sockaddr * ) & mc -> mc_addr ) ; free ( mc , M_VLAN ) ; } IF_ADDR_WLOCK ( ifp ) ; TAILQ_FOREACH ( ifma , & ifp -> if_multiaddrs , ifma_link ) { if ( ifma -> ifma_addr -> sa_family != AF_LINK ) continue ; mc = malloc ( sizeof ( struct vlan_mc_entry ) , M_VLAN , M_NOWAIT ) ; if ( mc == NULL ) { IF_ADDR_WUNLOCK ( ifp ) ; return ( ENOMEM ) ; } bcopy ( ifma -> ifma_addr , & mc -> mc_addr , ifma -> ifma_addr -> sa_len ) ; mc -> mc_addr . sdl_index = ifp_p -> if_index ; SLIST_INSERT_HEAD ( & sc -> vlan_mc_listhead , mc , mc_entries ) ; } IF_ADDR_WUNLOCK ( ifp ) ; SLIST_FOREACH ( mc , & sc -> vlan_mc_listhead , mc_entries ) { error = if_addmulti ( ifp_p , ( struct sockaddr * ) & mc -> mc_addr , NULL ) ; if ( error ) return ( error ) ; } CURVNET_RESTORE ( ) ; return ( 0 ) ; }
Program our multicast filter.
Program our multicast filter .
/* Find the parent. */ /* First, remove any existing filter entries. */ /* Now program new ones. */