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

📄 mld6igmp_vif.cc

📁 MLDv2 support igmpv3 lite
💻 CC
📖 第 1 页 / 共 4 页
字号:
    bool ip_internet_control = true;	// XXX: always true        if (! (is_up() || is_pending_down())) {	error_msg = c_format("vif %s is not UP", name().c_str());	return (XORP_ERROR);    }        XLOG_ASSERT(src != IPvX::ZERO(family()));        //    // Prepare the MLD or IGMP header.    //    // Point the buffer to the protocol header    datalen = BUFFER_DATA_SIZE(buffer);    if (datalen > 0) {	BUFFER_RESET_TAIL(buffer);    }    if (proto_is_igmp()) {	BUFFER_PUT_OCTET(message_type, buffer);	// The message type	BUFFER_PUT_OCTET(max_resp_code, buffer);	BUFFER_PUT_HOST_16(0, buffer);		// Zero the checksum field	BUFFER_PUT_IPVX(group_address, buffer);    }    if (proto_is_mld6()) {	BUFFER_PUT_OCTET(message_type, buffer);	// The message type	BUFFER_PUT_OCTET(0, buffer);		// XXX: Always 0 for MLD	BUFFER_PUT_HOST_16(0, buffer);		// Zero the checksum field	BUFFER_PUT_HOST_16(max_resp_code, buffer);	BUFFER_PUT_HOST_16(0, buffer);		// Reserved	BUFFER_PUT_IPVX(group_address, buffer);    }    // Restore the buffer to include the data    if (datalen > 0) {	BUFFER_RESET_TAIL(buffer);	BUFFER_PUT_SKIP(datalen, buffer);    }    //    // Compute the checksum    //    cksum = inet_checksum(BUFFER_DATA_HEAD(buffer), BUFFER_DATA_SIZE(buffer));#ifdef HAVE_IPV6    // Add the checksum for the IPv6 pseudo-header    if (proto_is_mld6()) {	uint16_t cksum2;	size_t ph_len = BUFFER_DATA_SIZE(buffer);	cksum2 = calculate_ipv6_pseudo_header_checksum(src, dst, ph_len,						       IPPROTO_ICMPV6);	cksum = inet_checksum_add(cksum, cksum2);    }#endif // HAVE_IPV6    BUFFER_COPYPUT_INET_CKSUM(cksum, buffer, 2);	// XXX: the checksum        XLOG_TRACE(mld6igmp_node().is_log_trace(), "TX %s from %s to %s",	       proto_message_type2ascii(message_type),	       cstring(src),	       cstring(dst));        //    // Send the message    //    ret_value = mld6igmp_node().mld6igmp_send(name(), name(),					      src, dst,					      mld6igmp_node().ip_protocol_number(),					      MINTTL, -1,					      ip_router_alert,					      ip_internet_control,					      buffer, error_msg);        return (ret_value);     buflen_error:    XLOG_UNREACHABLE();    error_msg = c_format("TX %s from %s to %s: "			 "packet cannot fit into sending buffer",			 proto_message_type2ascii(message_type),			 cstring(src),			 cstring(dst));    XLOG_ERROR("%s", error_msg.c_str());    return (XORP_ERROR);}/** * Send Group-Specific Query message. * * @param group_address the "Multicast Address" or "Group Address" field * in the MLD or IGMP headers respectively. * @param error_msg the error message (if error). * @return XORP_OK on success, otherwise XORP_ERROR. **/intMld6igmpVif::mld6igmp_group_query_send(const IPvX& group_address,				       string& error_msg){    const IPvX& src = primary_addr();    const IPvX& dst = group_address;    const TimeVal& max_resp_time = query_last_member_interval().get();    Mld6igmpGroupRecord* group_record = NULL;    set<IPvX> no_sources;		// XXX: empty set    int ret_value;    //    // Only the Querier should originate Query messages    //    if (! i_am_querier())	return (XORP_OK);    // Find the group record    group_record = _group_records.find_group_record(group_address);    if (group_record == NULL)	return (XORP_ERROR);		// No such group    //    // Lower the group timer    //    _group_records.lower_group_timer(group_address, last_member_query_time());    //    // Send the message    //    ret_value = mld6igmp_query_send(src, dst, max_resp_time, group_address,				    no_sources,				    false,	// XXX: reset the s_flag 				    error_msg);    //    // Schedule the periodic Group-Specific Query    //    if (ret_value == XORP_OK)	group_record->schedule_periodic_group_query(no_sources);    //    // Print the error message if there was an error    //    if (ret_value != XORP_OK) {	XLOG_ERROR("Error sending Group-Specific query for %s: %s",		   cstring(group_address), error_msg.c_str());    }    return (ret_value);}/** * Send MLDv2 or IGMPv3 Group-and-Source-Specific Query message. * * @param group_address the "Multicast Address" or "Group Address" field * in the MLD or IGMP headers respectively. * @param sources the set of source addresses. * @param error_msg the error message (if error). * @return XORP_OK on success, otherwise XORP_ERROR. **/intMld6igmpVif::mld6igmp_group_source_query_send(const IPvX& group_address,					      const set<IPvX>& sources,					      string& error_msg){    const IPvX& src = primary_addr();    const IPvX& dst = group_address;    const TimeVal& max_resp_time = query_last_member_interval().get();    Mld6igmpGroupRecord* group_record = NULL;    set<IPvX> selected_sources;    set<IPvX>::const_iterator source_iter;    int ret_value;    //    // Only the Querier should originate Query messages    //    if (! i_am_querier())	return (XORP_OK);    if (sources.empty())	return (XORP_OK);		// No sources to query    // Find the group record    group_record = _group_records.find_group_record(group_address);    if (group_record == NULL)	return (XORP_ERROR);		// No such group    //    // Select only the sources with source timer larger than the    // Last Member Query Time.    //    for (source_iter = sources.begin();	 source_iter != sources.end();	 ++source_iter) {	const IPvX& ipvx = *source_iter;	Mld6igmpSourceRecord* source_record;	source_record = group_record->find_do_forward_source(ipvx);	if (source_record == NULL)	    continue;	TimeVal timeval_remaining;	source_record->source_timer().time_remaining(timeval_remaining);	if (timeval_remaining <= last_member_query_time())	    continue;	selected_sources.insert(ipvx);    }    if (selected_sources.empty())	return (XORP_OK);		// No selected sources to query    //    // Lower the source timer    //    group_record->lower_source_timer(selected_sources,				     last_member_query_time());    //    // Send the message    //    ret_value = mld6igmp_query_send(src, dst, max_resp_time, group_address,				    selected_sources,				    false,	// XXX: reset the s_flag 				    error_msg);    //    // Schedule the periodic Group-and-Source-Specific Query    //    if (ret_value == XORP_OK)	group_record->schedule_periodic_group_query(selected_sources);    //    // Print the error message if there was an error    //    if (ret_value != XORP_OK) {	XLOG_ERROR("Error sending Group-and-Source-Specific query for %s: %s",		   cstring(group_address), error_msg.c_str());    }    return (ret_value);}/** * Send MLD or IGMP Query message. * * @param src the message source address. * @param dst the message destination address. * @param max_resp_time the maximum response time. * @param group_address the "Multicast Address" or "Group Address" field * in the MLD or IGMP headers respectively. * @param sources the set of source addresses (for IGMPv3 or MLDv2 only). * @param s_flag the "Suppress Router-Side Processing" bit (for IGMPv3 * or MLDv2 only; in all other cases it should be set to false). * @param error_msg the error message (if error). * @return XORP_OK on success, otherwise XORP_ERROR. **/intMld6igmpVif::mld6igmp_query_send(const IPvX& src,				 const IPvX& dst,				 const TimeVal& max_resp_time,				 const IPvX& group_address,				 const set<IPvX>& sources,				 bool s_flag,				 string& error_msg){    buffer_t *buffer;    uint32_t timer_scale = mld6igmp_constant_timer_scale();    TimeVal scaled_max_resp_time = max_resp_time * timer_scale;    set<IPvX>::const_iterator source_iter;    uint8_t qrv, qqic;    size_t max_sources_n;    size_t max_payload = 0;    Mld6igmpGroupRecord* group_record = NULL;    //    // Only the Querier should originate Query messages    //    if (! i_am_querier())	return (XORP_OK);    // Find the group record    group_record = _group_records.find_group_record(group_address);    //    // Check protocol version and Query message matching    //    do {	if (sources.empty())	    break;	// IGMPv3/MLDv2 Query(G, A) message	if (is_igmpv3_mode(group_record) || is_mldv2_mode(group_record))	    break;	// XXX: Query(G, A) messages are not allowed in this mode	return (XORP_ERROR);	    } while (false);    //    // Lower the group and source timers (if necessary)    //    if (! s_flag) {	if (sources.empty()) {	    // XXX: Q(G) Query	    _group_records.lower_group_timer(group_address,					     last_member_query_time());	} else {	    // XXX: Q(G, A) Query	    _group_records.lower_source_timer(group_address, sources,					      last_member_query_time());	}    }    //    // Prepare the data after the Query header    //    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    // | Resv  |S| QRV |     QQIC      |     Number of Sources (N)     |    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    //    qrv = 0;    if (effective_robustness_variable() <= 0x7)	qrv = effective_robustness_variable();    if (s_flag)	qrv |= 0x8;    qqic = 0;    encode_exp_time_code8(effective_query_interval(), qqic, 1);    //    // Calculate the maximum number of sources    //    max_sources_n = sources.size();    if (proto_is_igmp()) {	max_payload = mtu()		// The MTU of the vif	    - (0xf << 2)		// IPv4 max header size	    - 4				// IPv4 Router Alert option	    - IGMP_V3_QUERY_MINLEN;	// IGMPv3 Query pre-source fields    }    if (proto_is_mld6()) {	max_payload = mtu()		// The MTU of the vif	    - 8		// IPv6 Hop-by-hop Ext. Header with Router Alert option	    - MLD_V2_QUERY_MINLEN;	// MLDv2 Query pre-source fields    }    max_sources_n = min(max_sources_n, max_payload / IPvX::addr_bytelen(family()));    //    // XXX: According to RFC 3810 (MLDv2), Section 8.3.2, the Querier    // continues to send MLDv2 queries, regardless of its Multicast Address    // Compatibility Mode.    //    // Interestingly, RFC 3376 (IGMPv3) does not include this statement.    // According to the following email, the need for this statement has been    // discovered too late to be included in RFC 3376:    // http://www1.ietf.org/mail-archive/web/ssm/current/msg00084.html    //    //    // Prepare the buffer    //    buffer = buffer_send_prepare();    BUFFER_PUT_SKIP(mld6igmp_constant_minlen(), buffer);    //    // Insert the data (for IGMPv3 and MLDv2 only)    //    if (is_igmpv3_mode() || is_mldv2_mode()) {	//	// XXX: Note that we consider only the interface mode, but ignore	// the Multicast Address Compatibility Mode.	//	BUFFER_PUT_OCTET(qrv, buffer);	BUFFER_PUT_OCTET(qqic, buffer);	BUFFER_PUT_HOST_16(max_sources_n, buffer);	source_iter = sources.begin();	while (max_sources_n > 0) {	    const IPvX& ipvx = *source_iter;	    BUFFER_PUT_IPVX(ipvx, buffer);	    ++source_iter;	    max_sources_n--;	}    } else {	//	// If IGMPv1 Multicast Address Compatibility Mode, then set the	// Max Response Time to zero.	//	if (is_igmpv1_mode(group_record))	    scaled_max_resp_time = TimeVal::ZERO();    }    //    // Send the message    //    return (mld6igmp_send(src, dst,			  mld6igmp_constant_membership_query(),			  scaled_max_resp_time.sec(),			  group_address, buffer, error_msg)); buflen_error:    XLOG_UNREACHABLE();    XLOG_ERROR("INTERNAL mld6igmp_query_send() ERROR: "	       "buffer size too small");    return (XORP_ERROR);}/** * Mld6igmpVif::mld6igmp_recv: * @src: The message source address. * @dst: The message destination address. * @ip_ttl: The IP TTL of the message. If it has a negative value, * it should be ignored. * @ip_tos: The IP TOS of the message. If it has a negative value, * it should be ignored. * @ip_router_alert: True if the received IP packet had the Router Alert * IP option set. * @ip_internet_control: If true, then this is IP control traffic. * @buffer: The buffer with the received message. * @error_msg: The error message (if error). *  * Receive MLD or IGMP message and pass it for processing. *  * Return value: %XORP_OK on success, otherwise %XORP_ERROR. **/intMld6igmpVif::mld6igmp_recv(const IPvX& src,			   const IPvX& dst,			   int ip_ttl,			   int ip_tos,			   bool ip_router_alert,			   bool ip_internet_control,			   buffer_t *buffer,			   string& error_msg){    int ret_value = XORP_ERROR;        if (! is_up()) {	error_msg = c_format("vif %s is not UP", name().c_str());	return (XORP_ERROR);    }        ret_value = mld6igmp_process(src, dst, ip_ttl, ip_tos, ip_router_alert,				 ip_internet_control, buffer, error_msg);        return (ret_value);}/** * Mld6igmpVif::mld6igmp_process: * @src: The message source address. * @dst: The message destination address. * @ip_ttl: The IP TTL of the message. If it has a negative value, * it should be ignored. * @ip_tos: The IP TOS of the message. If it has a negative value, * it should be ignored. * @ip_router_alert: True if the received IP packet had the Router Alert * IP option set. * @ip_internet_control: If true, then this is IP control traffic. * @buffer: The buffer with the message. * @error_msg: The error message (if error). *  * Process MLD or IGMP message and pass the control to the type-specific * functions. *  * Return value: %XORP_OK on success, otherwise %XORP_ERROR. **/intMld6igmpVif::mld6igmp_process(const IPvX& src,			      const IPvX& dst,			      int ip_ttl,			      int ip_tos,			      bool ip_router_alert,			      bool ip_internet_control,			      buffer_t *buffer,			      string& error_msg){    uint8_t message_type = 0;    uint16_t max_resp_code = 0;    IPvX group_address(family());    uint16_t cksum;    bool check_router_alert_option = false;

⌨️ 快捷键说明

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