FreeBSD/sys/netinet6/mld6.c
/*
 * Respond to a pending MLDv2 General Query.
 */
Respond to a pending MLDv2 General Query.
Respond to a pending MLDv2 General Query .
static void
mld_v2_dispatch_general_query(struct mld_ifsoftc *mli)
{
	struct ifmultiaddr	*ifma;
	struct ifnet		*ifp;
	struct in6_multi	*inm;
	int			 retval;
	IN6_MULTI_LOCK_ASSERT();
	MLD_LOCK_ASSERT();
	KASSERT(mli->mli_version == MLD_VERSION_2,
	    ("%s: called when version %d", __func__, mli->mli_version));
	if (mbufq_len(&mli->mli_gq) != 0)
		goto send;
	ifp = mli->mli_ifp;
	IF_ADDR_RLOCK(ifp);
	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
		if (ifma->ifma_addr->sa_family != AF_INET6 ||
		    ifma->ifma_protospec == NULL)
			continue;
		inm = (struct in6_multi *)ifma->ifma_protospec;
		KASSERT(ifp == inm->in6m_ifp,
		    ("%s: inconsistent ifp", __func__));
		switch (inm->in6m_state) {
		case MLD_NOT_MEMBER:
		case MLD_SILENT_MEMBER:
			break;
		case MLD_REPORTING_MEMBER:
		case MLD_IDLE_MEMBER:
		case MLD_LAZY_MEMBER:
		case MLD_SLEEPING_MEMBER:
		case MLD_AWAKENING_MEMBER:
			inm->in6m_state = MLD_REPORTING_MEMBER;
			retval = mld_v2_enqueue_group_record(&mli->mli_gq,
			    inm, 0, 0, 0, 0);
			CTR2(KTR_MLD, "%s: enqueue record = %d",
			    __func__, retval);
			break;
		case MLD_G_QUERY_PENDING_MEMBER:
		case MLD_SG_QUERY_PENDING_MEMBER:
		case MLD_LEAVING_MEMBER:
			break;
		}
	}
	IF_ADDR_RUNLOCK(ifp);
send:
	mld_dispatch_queue(&mli->mli_gq, MLD_MAX_RESPONSE_BURST);
	if (mbufq_first(&mli->mli_gq) != NULL) {
		mli->mli_v2_timer = 1 + MLD_RANDOM_DELAY(
		    MLD_RESPONSE_BURST_INTERVAL);
		V_interface_timers_running6 = 1;
	}
}
static void mld_v2_dispatch_general_query ( struct mld_ifsoftc * mli ) { struct ifmultiaddr * ifma ; struct ifnet * ifp ; struct in6_multi * inm ; int retval ; IN6_MULTI_LOCK_ASSERT ( ) ; MLD_LOCK_ASSERT ( ) ; KASSERT ( mli -> mli_version == MLD_VERSION_2 , ( " " , __func__ , mli -> mli_version ) ) ; if ( mbufq_len ( & mli -> mli_gq ) != 0 ) goto send ; ifp = mli -> mli_ifp ; IF_ADDR_RLOCK ( ifp ) ; TAILQ_FOREACH ( ifma , & ifp -> if_multiaddrs , ifma_link ) { if ( ifma -> ifma_addr -> sa_family != AF_INET6 || ifma -> ifma_protospec == NULL ) continue ; inm = ( struct in6_multi * ) ifma -> ifma_protospec ; KASSERT ( ifp == inm -> in6m_ifp , ( " " , __func__ ) ) ; switch ( inm -> in6m_state ) { case MLD_NOT_MEMBER : case MLD_SILENT_MEMBER : break ; case MLD_REPORTING_MEMBER : case MLD_IDLE_MEMBER : case MLD_LAZY_MEMBER : case MLD_SLEEPING_MEMBER : case MLD_AWAKENING_MEMBER : inm -> in6m_state = MLD_REPORTING_MEMBER ; retval = mld_v2_enqueue_group_record ( & mli -> mli_gq , inm , 0 , 0 , 0 , 0 ) ; CTR2 ( KTR_MLD , " " , __func__ , retval ) ; break ; case MLD_G_QUERY_PENDING_MEMBER : case MLD_SG_QUERY_PENDING_MEMBER : case MLD_LEAVING_MEMBER : break ; } } IF_ADDR_RUNLOCK ( ifp ) ; send : mld_dispatch_queue ( & mli -> mli_gq , MLD_MAX_RESPONSE_BURST ) ; if ( mbufq_first ( & mli -> mli_gq ) != NULL ) { mli -> mli_v2_timer = 1 + MLD_RANDOM_DELAY ( MLD_RESPONSE_BURST_INTERVAL ) ; V_interface_timers_running6 = 1 ; } }
Respond to a pending MLDv2 General Query.
Respond to a pending MLDv2 General Query .
/*
	 * Check that there are some packets queued. If so, send them first.
	 * For large number of groups the reply to general query can take
	 * many packets, we should finish sending them before starting of
	 * queuing the new reply.
	 */ /*
	 * Slew transmission of bursts over 500ms intervals.
	 */