FreeBSD/sys/netinet6/mld6.c
/*
 * Update a group's timers for MLDv2.
 * Will update the global pending timer flags.
 * Note: Unlocked read from mli.
 */
Update a group's timers for MLDv2.
Will update the global pending timer flags.
Note: Unlocked read from mli.
Update a group ' s timers for MLDv2 . Will update the global pending timer flags . Note : Unlocked read from mli .
static void
mld_v2_process_group_timers(struct mld_ifsoftc *mli,
    struct mbufq *qrq, struct mbufq *scq,
    struct in6_multi *inm, const int uri_fasthz)
{
	int query_response_timer_expired;
	int state_change_retransmit_timer_expired;
#ifdef KTR
	char ip6tbuf[INET6_ADDRSTRLEN];
#endif
	IN6_MULTI_LOCK_ASSERT();
	MLD_LOCK_ASSERT();
	query_response_timer_expired = 0;
	state_change_retransmit_timer_expired = 0;
	if (inm->in6m_timer == 0) {
		query_response_timer_expired = 0;
	} else if (--inm->in6m_timer == 0) {
		query_response_timer_expired = 1;
	} else {
		V_current_state_timers_running6 = 1;
	}
	if (inm->in6m_sctimer == 0) {
		state_change_retransmit_timer_expired = 0;
	} else if (--inm->in6m_sctimer == 0) {
		state_change_retransmit_timer_expired = 1;
	} else {
		V_state_change_timers_running6 = 1;
	}
	if (!state_change_retransmit_timer_expired &&
	    !query_response_timer_expired)
		return;
	switch (inm->in6m_state) {
	case MLD_NOT_MEMBER:
	case MLD_SILENT_MEMBER:
	case MLD_SLEEPING_MEMBER:
	case MLD_LAZY_MEMBER:
	case MLD_AWAKENING_MEMBER:
	case MLD_IDLE_MEMBER:
		break;
	case MLD_G_QUERY_PENDING_MEMBER:
	case MLD_SG_QUERY_PENDING_MEMBER:
		if (query_response_timer_expired) {
			int retval;
			retval = mld_v2_enqueue_group_record(qrq, inm, 0, 1,
			    (inm->in6m_state == MLD_SG_QUERY_PENDING_MEMBER),
			    0);
			CTR2(KTR_MLD, "%s: enqueue record = %d",
			    __func__, retval);
			inm->in6m_state = MLD_REPORTING_MEMBER;
			in6m_clear_recorded(inm);
		}
	case MLD_REPORTING_MEMBER:
	case MLD_LEAVING_MEMBER:
		if (state_change_retransmit_timer_expired) {
			if (--inm->in6m_scrv > 0) {
				inm->in6m_sctimer = uri_fasthz;
				V_state_change_timers_running6 = 1;
			}
			(void)mld_v2_merge_state_changes(inm, scq);
			in6m_commit(inm);
			CTR3(KTR_MLD, "%s: T1 -> T0 for %s/%s", __func__,
			    ip6_sprintf(ip6tbuf, &inm->in6m_addr),
			    if_name(inm->in6m_ifp));
			if (inm->in6m_state == MLD_LEAVING_MEMBER &&
			    inm->in6m_scrv == 0) {
				inm->in6m_state = MLD_NOT_MEMBER;
				SLIST_INSERT_HEAD(&mli->mli_relinmhead,
				    inm, in6m_nrele);
			}
		}
		break;
	}
}
static void mld_v2_process_group_timers ( struct mld_ifsoftc * mli , struct mbufq * qrq , struct mbufq * scq , struct in6_multi * inm , const int uri_fasthz ) { int query_response_timer_expired ; int state_change_retransmit_timer_expired ; #ifdef KTR char ip6tbuf [ INET6_ADDRSTRLEN ] ; #endif IN6_MULTI_LOCK_ASSERT ( ) ; MLD_LOCK_ASSERT ( ) ; query_response_timer_expired = 0 ; state_change_retransmit_timer_expired = 0 ; if ( inm -> in6m_timer == 0 ) { query_response_timer_expired = 0 ; } else if ( -- inm -> in6m_timer == 0 ) { query_response_timer_expired = 1 ; } else { V_current_state_timers_running6 = 1 ; } if ( inm -> in6m_sctimer == 0 ) { state_change_retransmit_timer_expired = 0 ; } else if ( -- inm -> in6m_sctimer == 0 ) { state_change_retransmit_timer_expired = 1 ; } else { V_state_change_timers_running6 = 1 ; } if ( ! state_change_retransmit_timer_expired && ! query_response_timer_expired ) return ; switch ( inm -> in6m_state ) { case MLD_NOT_MEMBER : case MLD_SILENT_MEMBER : case MLD_SLEEPING_MEMBER : case MLD_LAZY_MEMBER : case MLD_AWAKENING_MEMBER : case MLD_IDLE_MEMBER : break ; case MLD_G_QUERY_PENDING_MEMBER : case MLD_SG_QUERY_PENDING_MEMBER : if ( query_response_timer_expired ) { int retval ; retval = mld_v2_enqueue_group_record ( qrq , inm , 0 , 1 , ( inm -> in6m_state == MLD_SG_QUERY_PENDING_MEMBER ) , 0 ) ; CTR2 ( KTR_MLD , " " , __func__ , retval ) ; inm -> in6m_state = MLD_REPORTING_MEMBER ; in6m_clear_recorded ( inm ) ; } case MLD_REPORTING_MEMBER : case MLD_LEAVING_MEMBER : if ( state_change_retransmit_timer_expired ) { if ( -- inm -> in6m_scrv > 0 ) { inm -> in6m_sctimer = uri_fasthz ; V_state_change_timers_running6 = 1 ; } ( void ) mld_v2_merge_state_changes ( inm , scq ) ; in6m_commit ( inm ) ; CTR3 ( KTR_MLD , " " , __func__ , ip6_sprintf ( ip6tbuf , & inm -> in6m_addr ) , if_name ( inm -> in6m_ifp ) ) ; if ( inm -> in6m_state == MLD_LEAVING_MEMBER && inm -> in6m_scrv == 0 ) { inm -> in6m_state = MLD_NOT_MEMBER ; SLIST_INSERT_HEAD ( & mli -> mli_relinmhead , inm , in6m_nrele ) ; } } break ; } }
Update a group's timers for MLDv2.
Update a group ' s timers for MLDv2 .
/*
	 * During a transition from compatibility mode back to MLDv2,
	 * a group record in REPORTING state may still have its group
	 * timer active. This is a no-op in this function; it is easier
	 * to deal with it here than to complicate the slow-timeout path.
	 */ /* We are in fasttimo, so be quick about it. */ /*
		 * Respond to a previously pending Group-Specific
		 * or Group-and-Source-Specific query by enqueueing
		 * the appropriate Current-State report for
		 * immediate transmission.
		 */ /* FALLTHROUGH */ /*
			 * State-change retransmission timer fired.
			 * If there are any further pending retransmissions,
			 * set the global pending state-change flag, and
			 * reset the timer.
			 */ /*
			 * Retransmit the previously computed state-change
			 * report. If there are no further pending
			 * retransmissions, the mbuf queue will be consumed.
			 * Update T0 state to T1 as we have now sent
			 * a state-change.
			 */ /*
			 * If we are leaving the group for good, make sure
			 * we release MLD's reference to it.
			 * This release must be deferred using a SLIST,
			 * as we are called from a loop which traverses
			 * the in_ifmultiaddr TAILQ.
			 */