⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mld6igmp_group_record.cc

📁 MLDv2 support igmpv3 lite
💻 CC
📖 第 1 页 / 共 3 页
字号:
   	return;    }    if (is_asm_mode()) {	//	// Router State: EXCLUDE (X, Y)	// Report Received: BLOCK (A)	// New Router State: EXCLUDE (X + (A - Y), Y)	// Actions: (A - X - Y) = Group Timer	//          Send Q(G, A - Y)	//	Mld6igmpSourceSet& a = _do_forward_sources;	TimeVal gt;	_group_timer.time_remaining(gt);	const set<IPvX>& b = sources;	Mld6igmpSourceSet a_and_b= a * b;	// Send Q(G, A - Y) with a_minus_y	_mld6igmp_vif.mld6igmp_group_source_query_send(	    group(),	    a_and_b.extract_source_addresses(),	    dummy_error_msg);	calculate_forwarding_changes(old_is_include_mode,				     old_do_forward_sources);	return;    }}/** * Lower the group timer. * * @param timeval the timeout interval the timer should be lowered to. */voidMld6igmpGroupRecord::lower_group_timer(const TimeVal& timeval){    TimeVal timeval_remaining;    //    // Lower the group timer    //    _group_timer.time_remaining(timeval_remaining);    if (timeval < timeval_remaining) {	_group_timer = eventloop().new_oneoff_after(	    timeval,	    callback(this, &Mld6igmpGroupRecord::group_timer_timeout));    }}/** * Lower the source timer for a set of sources. * * @param sources the source addresses. * @param timeval the timeout interval the timer should be lowered to. */voidMld6igmpGroupRecord::lower_source_timer(const set<IPvX>& sources,					 const TimeVal& timeval){    //    // Lower the source timer    //    _do_forward_sources.lower_source_timer(sources, timeval);}/** * Take the appropriate actions for a source that has expired. * * @param source_record the source record that has expired. */voidMld6igmpGroupRecord::source_expired(Mld6igmpSourceRecord* source_record){    Mld6igmpSourceSet::iterator iter;    // Erase the source record from the appropriate source set    iter = _do_forward_sources.find(source_record->source());    XLOG_ASSERT(iter != _do_forward_sources.end());    _do_forward_sources.erase(iter);    if (is_include_mode()) {	// notify routing (-)	mld6igmp_vif().join_prune_notify_routing(source_record->source(),						 group(),						 ACTION_PRUNE);	// Delete the source record	delete source_record;	// If no more source records, then delete the group record	if (_do_forward_sources.empty()) {	    mld6igmp_vif().group_records().erase(group());	    delete this;	}	return;    }    if (is_asm_mode()) {	// notify routing (-)	//	// XXX: Note that we send a PRUNE twice: the first one to remove the	// original JOIN for the source, and the second one to create	// PRUNE state for the source.	//	mld6igmp_vif().join_prune_notify_routing(source_record->source(),						 group(),						 ACTION_PRUNE);	delete source_record;	return;    }}/** * Get the number of seconds until the group timer expires. *  * @return the number of seconds until the group timer expires. */uint32_tMld6igmpGroupRecord::timeout_sec() const{    TimeVal tv;        _group_timer.time_remaining(tv);        return (tv.sec());}/** * Timeout: the group timer has expired. */voidMld6igmpGroupRecord::group_timer_timeout(){    if (is_include_mode()) {	// XXX: Nothing to do when in INCLUDE mode.	if (_do_forward_sources.empty()) {	    mld6igmp_vif().join_prune_notify_routing(IPvX::ZERO(family()),						     group(),						     ACTION_PRUNE);	    mld6igmp_vif().group_records().erase(group());	    delete this;	} else {	    mld6igmp_vif().join_prune_notify_routing(IPvX::ZERO(family()),						     group(),						     ACTION_PRUNE);	}	return;    }    if (is_asm_mode()) {	// notify routing (-)	mld6igmp_vif().join_prune_notify_routing(IPvX::ZERO(family()),						 group(),						 ACTION_PRUNE);	if (! _do_forward_sources.empty()) {	    // Transition to INCLUDE mode	    return;	}	//	// No sources with running source timers.	// Delete the group record and return immediately.	//	mld6igmp_vif().group_records().erase(group());	delete this;	return;    }}/** * Schedule periodic Group-Specific and Group-and-Source-Specific Query * retransmission. * * If the sources list is empty, we schedule Group-Specific Query, * otherwise we schedule Group-and-Source-Specific Query. * * @param sources the source addresses. */voidMld6igmpGroupRecord::schedule_periodic_group_query(const set<IPvX>& sources){    Mld6igmpSourceSet::iterator source_iter;    size_t count = _mld6igmp_vif.last_member_query_count() - 1;    if (_mld6igmp_vif.last_member_query_count() == 0)	return;    if (_mld6igmp_vif.query_last_member_interval().get() == TimeVal::ZERO())	return;    //    // Set the count for query retransmissions    //    if (sources.empty()) {	//	// Set the count for Group-Specific Query retransmission	//	_query_retransmission_count = count;    } else {	//	// Set the count for Group-and-Source-Specific Query retransmission	//	set<IPvX>::const_iterator ipvx_iter;	for (ipvx_iter = sources.begin();	     ipvx_iter != sources.end();	     ++ipvx_iter) {	    const IPvX& ipvx = *ipvx_iter;	    Mld6igmpSourceRecord* source_record = find_do_forward_source(ipvx);	    if (source_record == NULL)		continue;	    source_record->set_query_retransmission_count(count);	}    }    //    // Set the periodic timer for SSM Group-Specific and    // Group-and-Source-Specific Queries.    //    // Note that we set the timer only if it wasn't running already.    //    if (! _group_query_timer.scheduled()) {	_group_query_timer = eventloop().new_periodic(	    _mld6igmp_vif.query_last_member_interval().get(),	    callback(this, &Mld6igmpGroupRecord::group_query_periodic_timeout));    }}/** * Periodic timeout: time to send the next Group-Specific and * Group-and-Source-Specific Queries. * * @return true if the timer should be scheduled again, otherwise false. */boolMld6igmpGroupRecord::group_query_periodic_timeout(){    string dummy_error_msg;    bool s_flag = false;    set<IPvX> no_sources;		// XXX: empty set    set<IPvX> sources_with_s_flag;    set<IPvX> sources_without_s_flag;    Mld6igmpSourceSet::iterator source_iter;    TimeVal max_resp_time = mld6igmp_vif().query_last_member_interval().get();    bool do_send_group_query = true;    //    // XXX: Don't send Group-Specific or Group-and-Source-Specific Queries    // for entries that are in IGMPv1 mode.    //    if (is_igmpv1_mode())	return (false);    //    // XXX: The IGMPv3/MLDv2 spec doesn't say what to do here if we changed    // from a Querier to a non-Querier.    // However, the IGMPv2 spec says that Querier to non-Querier transitions    // are to be ignored (see the bottom part of Section 3 of RFC 2236).    // Hence, for this reason and for robustness purpose we send the Query    // messages without taking into account any Querier to non-Querier    // transitions.    //    //    // Send the Group-Specific Query message    //    if (_query_retransmission_count == 0) {	do_send_group_query = false;	// No more queries to send    } else {	_query_retransmission_count--;	//	// Calculate the group-specific "Suppress Router-Side Processing" bit	//	TimeVal timeval_remaining;	group_timer().time_remaining(timeval_remaining);	if (timeval_remaining > _mld6igmp_vif.last_member_query_time())	    s_flag = true;	_mld6igmp_vif.mld6igmp_query_send(mld6igmp_vif().primary_addr(),					  group(),					  max_resp_time,					  group(),					  no_sources,					  s_flag,					  dummy_error_msg);    }    //    // Select all the sources that should be queried, and add them to    // the appropriate set.    //    for (source_iter = _do_forward_sources.begin();	 source_iter != _do_forward_sources.end();	 ++source_iter) {	Mld6igmpSourceRecord* source_record = source_iter->second;	size_t count = source_record->query_retransmission_count();	bool s_flag = false;	if (count == 0)	    continue;	source_record->set_query_retransmission_count(count - 1);	//	// Calculate the "Suppress Router-Side Processing" bit	//	TimeVal timeval_remaining;	source_record->source_timer().time_remaining(timeval_remaining);	if (timeval_remaining > _mld6igmp_vif.last_member_query_time())	    s_flag = true;	if (s_flag)	    sources_with_s_flag.insert(source_record->source());	else	    sources_without_s_flag.insert(source_record->source());    }    //    // Send the Group-and-Source-Specific Query messages    //    if ((! sources_with_s_flag.empty()) && (! do_send_group_query)) {	//	// According to RFC 3376, Section 6.6.3.2:	// "If a group specific query is scheduled to be transmitted at the	// same time as a group and source specific query for the same group,	// then transmission of the group and source specific message with the	// "Suppress Router-Side Processing" bit set may be suppressed."	//	// The corresponding text from RFC 3810, Section 7.6.3.2 is similar.	//	_mld6igmp_vif.mld6igmp_query_send(mld6igmp_vif().primary_addr(),					  group(),					  max_resp_time,					  group(),					  sources_with_s_flag,					  true,		// XXX: set the s_flag					  dummy_error_msg);    }    if (! sources_without_s_flag.empty()) {	_mld6igmp_vif.mld6igmp_query_send(mld6igmp_vif().primary_addr(),					  group(),					  max_resp_time,					  group(),					  sources_without_s_flag,					  false,       // XXX: reset the s_flag					  dummy_error_msg);    }    if (sources_with_s_flag.empty()	&& sources_without_s_flag.empty()	&& (! do_send_group_query)) {	return (false);			// No more queries to send    }    return (true);		// Schedule the next timeout}/** * Record that an older Membership report message has been received. * * @param message_version the corresponding protocol version of the * received message. */voidMld6igmpGroupRecord::received_older_membership_report(int message_version){    TimeVal timeval = _mld6igmp_vif.older_version_host_present_interval();    if (_mld6igmp_vif.proto_is_igmp()) {	switch (message_version) {	case IGMP_V1:	    if (_mld6igmp_vif.is_igmpv2_mode()) {		//		// XXX: The value specified in RFC 2236 is different from		// the value specified in RFC 3376.		//		timeval = _mld6igmp_vif.group_membership_interval();	    }	    _igmpv1_host_present_timer = eventloop().new_oneoff_after(		timeval,		callback(this, &Mld6igmpGroupRecord::older_version_host_present_timer_timeout));	    break;	case IGMP_V2:	    _igmpv2_mldv1_host_present_timer = eventloop().new_oneoff_after(		timeval,		callback(this, &Mld6igmpGroupRecord::older_version_host_present_timer_timeout));	    break;	default:	    break;	}    }    if (_mld6igmp_vif.proto_is_mld6()) {	switch (message_version) {	case MLD_V1:	    _igmpv2_mldv1_host_present_timer = eventloop().new_oneoff_after(		timeval,		callback(this, &Mld6igmpGroupRecord::older_version_host_present_timer_timeout));	    break;	default:	    break;	}    }}voidMld6igmpGroupRecord::older_version_host_present_timer_timeout(){    // XXX: nothing to do}/** * Test if the group is running in IGMPv1 mode. * * @return true if the group is running in IGMPv1 mode, otherwise false. */boolMld6igmpGroupRecord::is_igmpv1_mode() const{    if (! _mld6igmp_vif.proto_is_igmp())	return (false);    if (_mld6igmp_vif.is_igmpv1_mode())	return (true);		// XXX: explicitly configured in IGMPv1 mode    return (_igmpv1_host_present_timer.scheduled());}/** * Test if the group is running in IGMPv2 mode. * * @return true if the group is running in IGMPv2 mode, otherwise false. */boolMld6igmpGroupRecord::is_igmpv2_mode() const{    if (! _mld6igmp_vif.proto_is_igmp())	return (false);    if (is_igmpv1_mode())	return (false);    return (_igmpv2_mldv1_host_present_timer.scheduled());}/** * Test if the group is running in IGMPv3 mode. * * @return true if the group is running in IGMPv3 mode, otherwise false. */boolMld6igmpGroupRecord::is_igmpv3_mode() const{    if (! _mld6igmp_vif.proto_is_igmp())	return (false);    if (is_igmpv1_mode() || is_igmpv2_mode())	return (false);    return (true);}/** * Test if the group is running in MLDv1 mode. * * @return true if the group is running in MLDv1 mode, otherwise false. */boolMld6igmpGroupRecord::is_mldv1_mode() const{    if (! _mld6igmp_vif.proto_is_mld6())	return (false);    if (_mld6igmp_vif.is_mldv1_mode())	return (true);		// XXX: explicitly configured in MLDv1 mode    return (_igmpv2_mldv1_host_present_timer.scheduled());}/** * Test if the group is running in MLDv2 mode. * * @return true if the group is running in MLDv2 mode, otherwise false. */boolMld6igmpGroupRecord::is_mldv2_mode() const{    if (! _mld6igmp_vif.proto_is_mld6())	return (false);    if (is_mldv1_mode())	return (false);    return (true);}/** * Calculate the forwarding changes and notify the interested parties. * * @param old_is_include mode if true, the old filter mode was INCLUDE, * otherwise was EXCLUDE. * @param old_do_forward_sources the old set of sources to forward. * @param old_dont_forward_sources the old set of sources not to forward. */voidMld6igmpGroupRecord::calculate_forwarding_changes(    bool old_is_include_mode,    const set<IPvX>& old_do_forward_sources) const{    bool new_is_include_mode = is_include_mode();    set<IPvX> new_do_forward_sources = _do_forward_sources.extract_source_addresses();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -