?? mld6igmp_proto.cc
字號:
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 + -