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

📄 mld6igmp_proto.cc

📁 MLDv2 support igmpv3 lite
💻 CC
📖 第 1 页 / 共 2 页
字号:
Mld6igmpVif::mld6igmp_ssm_membership_report_recv(const IPvX& src,						 const IPvX& dst,						 uint8_t message_type,						 buffer_t *buffer){    uint16_t group_records_n = 0;    string error_msg;    typedef pair<IPvX, set<IPvX> > gs_record;	// XXX: a handy typedef    list<gs_record> mode_is_include_groups;    list<gs_record> mode_is_exclude_groups;    list<gs_record> change_to_include_mode_groups;    list<gs_record> change_to_exclude_mode_groups;    list<gs_record> allow_new_sources_groups;    list<gs_record> block_old_sources_groups;    list<gs_record>::iterator gs_iter;    //    // Decode the rest of the message header    //    BUFFER_GET_SKIP(2, buffer);		// The 'Reserved' field    BUFFER_GET_HOST_16(group_records_n, buffer);    //    // Decode the array of group records    //    while (group_records_n != 0) {	uint8_t record_type;	uint8_t aux_data_len;	uint16_t sources_n;	IPvX group_address(family());	set<IPvX> source_addresses;	list<gs_record>* gs_record_ptr = NULL;	BUFFER_GET_OCTET(record_type, buffer);	BUFFER_GET_OCTET(aux_data_len, buffer);	BUFFER_GET_HOST_16(sources_n, buffer);	BUFFER_GET_IPVX(family(), group_address, buffer);	// Decode the array of source addresses	while (sources_n != 0) {	    IPvX ipvx(family());	    BUFFER_GET_IPVX(family(), ipvx, buffer);	    source_addresses.insert(ipvx);	    sources_n--;	}	// XXX: Skip the 'Auxiliary Data', because we don't use it	BUFFER_GET_SKIP(aux_data_len, buffer);	//	// Select the appropriate set, and add the group and the sources to it	//	if (proto_is_igmp()) {	    switch (record_type) {	    case IGMP_MODE_IS_INCLUDE:		gs_record_ptr = &mode_is_include_groups;		break;	    case IGMP_MODE_IS_EXCLUDE:		gs_record_ptr = &mode_is_exclude_groups;		break;	    case IGMP_CHANGE_TO_INCLUDE_MODE:		gs_record_ptr = &change_to_include_mode_groups;		break;	    case IGMP_CHANGE_TO_EXCLUDE_MODE:		gs_record_ptr = &change_to_exclude_mode_groups;		break;	    case IGMP_ALLOW_NEW_SOURCES:		gs_record_ptr = &allow_new_sources_groups;		break;	    case IGMP_BLOCK_OLD_SOURCES:		gs_record_ptr = &block_old_sources_groups;		break;	    default:		break;	    }	}	if (proto_is_mld6()) {	    switch (record_type) {	    case MLD_MODE_IS_INCLUDE:		gs_record_ptr = &mode_is_include_groups;		break;	    case MLD_MODE_IS_EXCLUDE:		gs_record_ptr = &mode_is_exclude_groups;		break;	    case MLD_CHANGE_TO_INCLUDE_MODE:		gs_record_ptr = &change_to_include_mode_groups;		break;	    case MLD_CHANGE_TO_EXCLUDE_MODE:		gs_record_ptr = &change_to_exclude_mode_groups;		break;	    case MLD_ALLOW_NEW_SOURCES:		gs_record_ptr = &allow_new_sources_groups;		break;	    case MLD_BLOCK_OLD_SOURCES:		gs_record_ptr = &block_old_sources_groups;		break;	    default:		break;	    }	}	if (gs_record_ptr != NULL) {	    gs_record_ptr->push_back(make_pair(group_address,					       source_addresses));	} else {	    error_msg = c_format("RX %s from %s to %s on vif %s: "				 "unrecognized record type %d (ignored)",				 proto_message_type2ascii(message_type),				 cstring(src), cstring(dst),				 name().c_str(),				 record_type);	    XLOG_WARNING("%s", error_msg.c_str());	}	group_records_n--;    }    //    // Process the records    //    for (gs_iter = mode_is_include_groups.begin();	 gs_iter != mode_is_include_groups.end();	 ++gs_iter) {	group_records().process_mode_is_include(gs_iter->first,						gs_iter->second,						src);    }    for (gs_iter = mode_is_exclude_groups.begin();	 gs_iter != mode_is_exclude_groups.end();	 ++gs_iter) {	group_records().process_mode_is_exclude(gs_iter->first,						gs_iter->second,						src);    }    for (gs_iter = change_to_include_mode_groups.begin();	 gs_iter != change_to_include_mode_groups.end();	 ++gs_iter) {	group_records().process_change_to_include_mode(gs_iter->first,						       gs_iter->second,						       src);    }    for (gs_iter = change_to_exclude_mode_groups.begin();	 gs_iter != change_to_exclude_mode_groups.end();	 ++gs_iter) {	group_records().process_change_to_exclude_mode(gs_iter->first,						       gs_iter->second,						       src);    }    for (gs_iter = allow_new_sources_groups.begin();	 gs_iter != allow_new_sources_groups.end();	 ++gs_iter) {	group_records().process_allow_new_sources(gs_iter->first,						  gs_iter->second,						  src);    }    for (gs_iter = block_old_sources_groups.begin();	 gs_iter != block_old_sources_groups.end();	 ++gs_iter) {	group_records().process_block_old_sources(gs_iter->first,						  gs_iter->second,						  src);    }    return (XORP_OK); rcvlen_error:    error_msg = c_format("RX %s from %s to %s on vif %s: "			 "some fields are too short",			 proto_message_type2ascii(message_type),			 cstring(src), cstring(dst),			 name().c_str());    XLOG_WARNING("%s", error_msg.c_str());    return (XORP_ERROR);}/** * Mld6igmpVif::other_querier_timer_timeout: *  * Timeout: the previous querier has expired. I will become the querier. **/voidMld6igmpVif::other_querier_timer_timeout(){    string dummy_error_msg;    if (primary_addr() == IPvX::ZERO(family())) {	// XXX: the vif address is unknown; this cannot happen if the	// vif status is UP.	XLOG_ASSERT(! is_up());	return;    }        set_querier_addr(primary_addr());    set_i_am_querier(true);    //    // Now I am the querier. Send a general membership query.    //    TimeVal max_resp_time = query_response_interval().get();    set<IPvX> no_sources;		// XXX: empty set    mld6igmp_query_send(primary_addr(),			IPvX::MULTICAST_ALL_SYSTEMS(family()),			max_resp_time,			IPvX::ZERO(family()),			// XXX: ANY			no_sources,			false,			dummy_error_msg);    _startup_query_count = 0;		// XXX: not a startup case    _query_timer = mld6igmp_node().eventloop().new_oneoff_after(	effective_query_interval(),	callback(this, &Mld6igmpVif::query_timer_timeout));}/** * Mld6igmpVif::query_timer_timeout: *  * Timeout: time to send a membership query. **/voidMld6igmpVif::query_timer_timeout(){    TimeVal interval;    string dummy_error_msg;    if (! i_am_querier())	return;		// I am not the querier anymore. Ignore.    //    // Send a general membership query    //    TimeVal max_resp_time = query_response_interval().get();    set<IPvX> no_sources;		// XXX: empty set    mld6igmp_query_send(primary_addr(),			IPvX::MULTICAST_ALL_SYSTEMS(family()),			max_resp_time,			IPvX::ZERO(family()),			// XXX: ANY			no_sources,			false,			dummy_error_msg);    if (_startup_query_count > 0)	_startup_query_count--;    if (_startup_query_count > 0) {	// "Startup Query Interval"	interval = effective_query_interval() / 4;    } else {	interval = effective_query_interval();    }    _query_timer = mld6igmp_node().eventloop().new_oneoff_after(	interval,	callback(this, &Mld6igmpVif::query_timer_timeout));}/** * mld6igmp_query_version_consistency_check: * @src: The message source address. * @dst: The message destination address. * @message_type: The type of the MLD/IGMP message. * @message_version: The protocol version of the received Query message: * (IGMP_V1, IGMP_V2, IGMP_V3 for IGMP) or (MLD_V1, MLD_V2 for MLD). *  * Check for MLD/IGMP protocol version interface configuration consistency. * For example, if the received Query message was IGMPv1, a correctly * configured local interface must be operating in IGMPv1 mode. * Similarly, if the local interface is operating in IGMPv1 mode, * all other neighbor routers (for that interface) must be * operating in IGMPv1 as well. *  * Return value: %XORP_OK if consistency, otherwise %XORP_ERROR. **/intMld6igmpVif::mld6igmp_query_version_consistency_check(const IPvX& src,						      const IPvX& dst,						      uint8_t message_type,						      int message_version){    string proto_name, mode_config, mode_received;    if (message_version == proto_version())	return (XORP_OK);    if (proto_is_igmp())	proto_name = "IGMP";    if (proto_is_mld6())	proto_name = "MLD";    mode_config = c_format("%sv%u", proto_name.c_str(), proto_version());    mode_received = c_format("%sv%u", proto_name.c_str(), message_version);    // TODO: rate-limit the warning    XLOG_WARNING("RX %s from %s to %s on vif %s: "		 "this interface is in %s mode, but received %s message",		 proto_message_type2ascii(message_type),		 cstring(src), cstring(dst),		 name().c_str(),		 mode_config.c_str(),		 mode_received.c_str());    XLOG_WARNING("Please configure properly all routers on "		 "that subnet to use same %s version",		 proto_name.c_str());    return (XORP_ERROR);}voidMld6igmpVif::set_configured_query_interval_cb(TimeVal v){    set_effective_query_interval(v);}voidMld6igmpVif::set_effective_query_interval(const TimeVal& v){    _effective_query_interval = v;    recalculate_effective_query_interval();}voidMld6igmpVif::recalculate_effective_query_interval(){    recalculate_group_membership_interval();    recalculate_older_version_host_present_interval();}voidMld6igmpVif::set_query_last_member_interval_cb(TimeVal v){    UNUSED(v);    recalculate_last_member_query_time();}voidMld6igmpVif::set_query_response_interval_cb(TimeVal v){    UNUSED(v);    recalculate_group_membership_interval();    recalculate_older_version_host_present_interval();}voidMld6igmpVif::set_configured_robust_count_cb(uint32_t v){    set_effective_robustness_variable(v);}voidMld6igmpVif::set_effective_robustness_variable(uint32_t v){    _effective_robustness_variable = v;    recalculate_effective_robustness_variable();}voidMld6igmpVif::recalculate_effective_robustness_variable(){    recalculate_group_membership_interval();    recalculate_last_member_query_count();    recalculate_older_version_host_present_interval();}voidMld6igmpVif::recalculate_last_member_query_count(){    _last_member_query_count = effective_robustness_variable();    recalculate_last_member_query_time();}voidMld6igmpVif::recalculate_group_membership_interval(){    _group_membership_interval =	effective_query_interval() * effective_robustness_variable()	+ query_response_interval().get();}voidMld6igmpVif::recalculate_last_member_query_time(){    _last_member_query_time = query_last_member_interval().get()	* last_member_query_count();}voidMld6igmpVif::recalculate_older_version_host_present_interval(){    _older_version_host_present_interval =	effective_query_interval() * effective_robustness_variable()	+ query_response_interval().get();}voidMld6igmpVif::restore_effective_variables(){    // Restore the default Query Interval and Robustness Variable    set_effective_robustness_variable(configured_robust_count().get());    set_effective_query_interval(configured_query_interval().get());}voidMld6igmpVif::decode_exp_time_code8(uint8_t code, TimeVal& timeval,				   uint32_t timer_scale){    uint32_t decoded_time = 0;    //    // From RFC 3376 Section 4.1.1, and RFC 3810 Section 5.1.9:    //    // If Code < 128, Time = Code    //    // If Code >= 128, Code represents a floating-point value as follows:    //    //     0 1 2 3 4 5 6 7    //    +-+-+-+-+-+-+-+-+    //    |1| exp | mant  |    //    +-+-+-+-+-+-+-+-+    //    // Time = (mant | 0x10) << (exp + 3)    //    if (code < 128) {	decoded_time = code;    } else {	uint8_t mant = code & 0xf;	uint8_t exp = (code >> 4) & 0x7;	decoded_time = (mant | 0x10) << (exp + 3);    }    timeval = TimeVal(decoded_time, 0);    timeval = timeval / timer_scale;}voidMld6igmpVif::decode_exp_time_code16(uint16_t code, TimeVal& timeval,				    uint32_t timer_scale){    uint32_t decoded_time = 0;    //    // From RFC 3810 Section 5.1.9:    //    // If Code < 32768, Time = Code    //    // If Code >= 32768, Code represents a floating-point value as follows:    //    //     0 1 2 3 4 5 6 7 8 9 A B C D E F    //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    //    |1| exp |          mant         |    //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    //    // Time = (mant | 0x1000) << (exp + 3)    //    if (code < 32768) {	decoded_time = code;    } else {	uint8_t mant = code & 0xfff;	uint8_t exp = (code >> 12) & 0x7;	decoded_time = (mant | 0x1000) << (exp + 3);    }    timeval = TimeVal(decoded_time, 0);    timeval = timeval / timer_scale;}voidMld6igmpVif::encode_exp_time_code8(const TimeVal& timeval,				   uint8_t& code,				   uint32_t timer_scale){    TimeVal scaled_max_resp_time = timeval * timer_scale;    uint32_t decoded_time = scaled_max_resp_time.sec();    code = 0;    //    // From RFC 3376 Section 4.1.1, and RFC 3810 Section 5.1.9:    //    // If Code < 128, Time = Code    //    // If Code >= 128, Code represents a floating-point value as follows:    //    //     0 1 2 3 4 5 6 7    //    +-+-+-+-+-+-+-+-+    //    |1| exp | mant  |    //    +-+-+-+-+-+-+-+-+    //    // Time = (mant | 0x10) << (exp + 3)    //    if (decoded_time < 128) {	code = decoded_time;    } else {	uint8_t mant = 0;	uint8_t exp = 0;	// Calculate the "mant" and the "exp"	while ((decoded_time >> (exp + 3)) > 0x1f) {	    exp++;	}	mant = (decoded_time >> (exp + 3)) & 0xf;	code = 0x80 | (exp << 4) | mant;    }}voidMld6igmpVif::encode_exp_time_code16(const TimeVal& timeval,				    uint16_t& code,				    uint32_t timer_scale){    TimeVal scaled_max_resp_time = timeval * timer_scale;    uint32_t decoded_time = scaled_max_resp_time.sec();    code = 0;    //    // From RFC 3810 Section 5.1.9:    //    // If Code < 32768, Time = Code    //    // If Code >= 32768, Code represents a floating-point value as follows:    //    //     0 1 2 3 4 5 6 7 8 9 A B C D E F    //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    //    |1| exp |          mant         |    //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    //    // Time = (mant | 0x1000) << (exp + 3)    //    if (decoded_time < 32768) {	code = decoded_time;    } else {	uint8_t mant = 0;	uint8_t exp = 0;	// Calculate the "mant" and the "exp"	while ((decoded_time >> (exp + 3)) > 0x1fff) {	    exp++;	}	mant = (decoded_time >> (exp + 3)) & 0xfff;	code = 0x8000 | (exp << 12) | mant;    }}

⌨️ 快捷键说明

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