void querier::timer_triggerd(const std::shared_ptr<proxy_msg>& msg) { HC_LOG_TRACE(""); gaddr_map::iterator db_info_it; std::shared_ptr<timer_msg> tm; if (!msg.unique()) { switch (msg->get_type()) { case proxy_msg::FILTER_TIMER_MSG: case proxy_msg::SOURCE_TIMER_MSG: case proxy_msg::RET_GROUP_TIMER_MSG: case proxy_msg::RET_SOURCE_TIMER_MSG: case proxy_msg::OLDER_HOST_PRESENT_TIMER_MSG: { tm = std::static_pointer_cast<timer_msg>(msg); db_info_it = m_db.group_info.find(tm->get_gaddr()); if (db_info_it == end(m_db.group_info)) { HC_LOG_ERROR("filter_timer message is still in use but cannot found"); return; } } break; case proxy_msg::GENERAL_QUERY_TIMER_MSG: tm = std::static_pointer_cast<timer_msg>(msg); break; default: HC_LOG_ERROR("unknown timer message format"); return; } } else { HC_LOG_DEBUG("filter_timer is outdate"); return; } switch (msg->get_type()) { case proxy_msg::FILTER_TIMER_MSG: timer_triggerd_filter_timer(db_info_it, tm); break; case proxy_msg::SOURCE_TIMER_MSG: timer_triggerd_source_timer(db_info_it, tm); break; case proxy_msg::RET_GROUP_TIMER_MSG: timer_triggerd_ret_group_timer(db_info_it, tm); break; case proxy_msg::RET_SOURCE_TIMER_MSG: timer_triggerd_ret_source_timer(db_info_it, tm); break; case proxy_msg::GENERAL_QUERY_TIMER_MSG: timer_triggerd_general_query_timer(tm); break; case proxy_msg::OLDER_HOST_PRESENT_TIMER_MSG: timer_triggerd_older_host_present_timer(db_info_it, tm); break; default: HC_LOG_ERROR("unknown timer message format"); return; } }
void querier::receive_record(const std::shared_ptr<proxy_msg>& msg) { HC_LOG_TRACE(""); if (msg->get_type() != proxy_msg::GROUP_RECORD_MSG) { HC_LOG_ERROR("wrong proxy message, it musst be be a GROUP_RECORD_MS"); return; } auto gr = std::static_pointer_cast<group_record_msg>(msg); auto db_info_it = m_db.group_info.find(gr->get_gaddr()); if (db_info_it == end(m_db.group_info)) { //add an empty neutral record to membership database HC_LOG_DEBUG("gaddr not found"); db_info_it = m_db.group_info.insert(gaddr_pair(gr->get_gaddr(), gaddr_info(m_db.querier_version_mode))).first; } //backwards compatibility coordination if (!is_newest_version(gr->get_grp_mem_proto()) && is_older_or_equal_version(gr->get_grp_mem_proto(), m_db.querier_version_mode) ) { db_info_it->second.compatibility_mode_variable = gr->get_grp_mem_proto(); auto ohpt = std::make_shared<older_host_present_timer_msg>(m_if_index, db_info_it->first, m_timers_values.get_older_host_present_interval()); db_info_it->second.older_host_present_timer = ohpt; m_timing->add_time(m_timers_values.get_older_host_present_interval(), m_msg_worker, ohpt); } //section 8.3.2. In the Presence of MLDv1 Multicast Address Listeners //MLDv2 BLOCK messages are ignored, as are source-lists in TO_EX() //messages (i.e., any TO_EX() message is treated as TO_EX( {} )). if (db_info_it->second.is_in_backward_compatibility_mode()) { if (gr->get_record_type() == CHANGE_TO_EXCLUDE_MODE) { gr->get_slist() = {}; } else if (gr->get_record_type() == BLOCK_OLD_SOURCES){ return; } } switch (db_info_it->second.filter_mode) { case INCLUDE_MODE: receive_record_in_include_mode(gr->get_record_type(), gr->get_gaddr(), gr->get_slist(), db_info_it->second); //if the new created group is not used delete it if (db_info_it->second.filter_mode == INCLUDE_MODE && db_info_it->second.include_requested_list.empty()) { m_db.group_info.erase(db_info_it); } break; case EXCLUDE_MODE: receive_record_in_exclude_mode(gr->get_record_type(), gr->get_gaddr(), gr->get_slist(), db_info_it->second); break; default : HC_LOG_ERROR("wrong filter mode: " << db_info_it->second.filter_mode); break; } }
void test_log() { hc_set_default_log_fun(HC_LOG_TRACE_LVL); HC_LOG_TRACE(""); HC_LOG_DEBUG("HC_LOG_DEBUG"); HC_LOG_INFO("HC_LOG_INFO"); HC_LOG_WARN("HC_LOG_WARN"); HC_LOG_ERROR("HC_LOG_ERROR"); HC_LOG_FATAL("HC_LOG_FATAL"); }
void message_queue<T, Compare>::enqueue(const T& t) { HC_LOG_TRACE(""); { std::unique_lock<std::mutex> lock(m_global_lock); m_q.push(t); } cond_empty.notify_one(); HC_LOG_DEBUG("!!!!!test2"); }
bool proxy_instance::send_gq_to_all(){ HC_LOG_TRACE(""); HC_LOG_DEBUG("send general query to all"); bool correct= true; state_table_map::iterator it_state_table; for(it_state_table= m_state_table.begin(); it_state_table != m_state_table.end(); it_state_table++){ if(!m_sender->send_general_query(it_state_table->first)){ HC_LOG_ERROR("failed to send general to if_index: " << it_state_table->first); correct = false; } } return correct; }
bool proxy_instance::init_mrt_socket(){ HC_LOG_TRACE(""); if(m_addr_family == AF_INET){ m_mrt_sock.create_raw_ipv4_socket(); }else if(m_addr_family == AF_INET6){ m_mrt_sock.create_raw_ipv6_socket(); }else{ HC_LOG_ERROR("wrong addr_family: " << m_addr_family); return false; } if(!m_is_single_instance){ if(!m_mrt_sock.set_kernel_table(m_upstream)){ return false; }else{ HC_LOG_DEBUG("proxy instance: " << m_upstream); } } if(!m_mrt_sock.set_mrt_flag(true)) return false; return true; }
void proxy_instance::handle_clock(struct clock_msg* c){ HC_LOG_TRACE(""); proxy_msg msg; state_table_map::iterator iter_table; g_state_map::iterator iter_state; src_state_map::iterator iter_src; src_group_state_pair* sgs_pair = NULL; switch(c->type){ case clock_msg::SEND_GQ_TO_ALL: { //send GQ send_gq_to_all(); m_check_source.check(); //reloade routing table //##-- dekrement all counter of all groups on all downstream interfaces in RUNNING state --## //##-- and dekrement all counter of all groups source addresses --## vector<addr_storage> tmp_erase_group_vector; //if group not joined and all sources are deleted for(iter_table= m_state_table.begin(); iter_table != m_state_table.end(); iter_table++){ for(iter_state= iter_table->second.begin(); iter_state != iter_table->second.end(); iter_state++){ sgs_pair = &iter_state->second; //-- process groups in RUNNING state -- if( sgs_pair->second.flag == src_state::RUNNING){ //if counter == 0 delete this group after query response if(--sgs_pair->second.robustness_counter == 0){ sgs_pair->second.flag= src_state::WAIT_FOR_DEL; sgs_pair->second.robustness_counter = PROXY_INSTANCE_DEL_IMMEDIATELY; msg.type = proxy_msg::CLOCK_MSG; msg.msg = new struct clock_msg(clock_msg::DEL_GROUP, iter_table->first, iter_state->first); m_timing->add_time(MC_TV_QUERY_RESPONSE_INTERVAL*1000 /*msec*/,this,msg); } } //-- process sources in FOREIGN_SRC state -downstream- -- vector<addr_storage> tmp_erase_source_vector; for(iter_src = sgs_pair->first.begin(); iter_src != sgs_pair->first.end(); iter_src++){ if(iter_src->second.flag == src_state::UNUSED_SRC || iter_src->second.flag == src_state::CACHED_SRC){ //del unused sources vif_map::iterator it_vif_map; if((it_vif_map = m_vif_map.find(iter_table->first)) == m_vif_map.end()){ HC_LOG_ERROR("cant find vif to if_index:" << iter_table->first); } if(m_check_source.is_src_unused(it_vif_map->second, iter_src->first, iter_state->first)){ iter_src->second.robustness_counter--; }else{ iter_src->second.robustness_counter=MC_TV_ROBUSTNESS_VARIABLE; } if(iter_src->second.robustness_counter == 0){ //save invalid sources tmp_erase_source_vector.push_back(iter_src->first); //refresh routing if(iter_src->second.flag == src_state::CACHED_SRC){ del_route(iter_table->first, iter_state->first, iter_src->first); } } }else{ HC_LOG_ERROR("downstream source is in unknown state: " << iter_src->second.state_type_to_string()); } } //erase invalid sources for(unsigned int i=0; i< tmp_erase_source_vector.size(); i++){ if((iter_src = sgs_pair->first.find(tmp_erase_source_vector[i]))!= sgs_pair->first.end()){ sgs_pair->first.erase(iter_src); }else{ HC_LOG_ERROR("cant find invalid downstream soruce: " << tmp_erase_source_vector[i]); } } //if group has no sources and is not joined (flag=INIT) remove the group if(sgs_pair->first.size() == 0){ if(sgs_pair->second.flag == src_state::INIT){ tmp_erase_group_vector.push_back(iter_state->first); } } } //erase unused groups for(unsigned int i=0; i< tmp_erase_group_vector.size(); i++){ if((iter_state = iter_table->second.find(tmp_erase_group_vector[i]))!= iter_table->second.end()){ iter_table->second.erase(iter_state); }else{ HC_LOG_ERROR("cant find unused groups: " << tmp_erase_group_vector[i]); } } tmp_erase_group_vector.clear(); } //-- process sources in FOREIGN_SRC state -upstream- -- upstream_src_state_map::iterator tmp_it_up_ss_map; src_state_map* tmp_ss_map; tmp_erase_group_vector.clear(); //unused groups for(tmp_it_up_ss_map = m_upstream_state.begin(); tmp_it_up_ss_map != m_upstream_state.end(); tmp_it_up_ss_map++){ tmp_ss_map = &tmp_it_up_ss_map->second; vector<addr_storage> tmp_erase_source_vector; for(iter_src = tmp_ss_map->begin(); iter_src != tmp_ss_map->end(); iter_src++){ // if(iter_src->second.flag == src_state::UNUSED_SRC || iter_src->second.flag == src_state::CACHED_SRC){ // //del old sources // if(--iter_src->second.robustness_counter == 0){ // //save invalid sources // tmp_erase_source_vector.push_back(iter_src->first); // //refresh routing // if(iter_src->second.flag == src_state::CACHED_SRC){ // del_route(m_upstream, tmp_it_up_ss_map->first, iter_src->first); // } // } // }else{ // HC_LOG_ERROR("upstream source is in unknown state: " << iter_src->second.state_type_to_string()); // } if(iter_src->second.flag == src_state::UNUSED_SRC){ //del old sources if(--iter_src->second.robustness_counter == 0){ //save invalid sources tmp_erase_source_vector.push_back(iter_src->first); } }else if(iter_src->second.flag == src_state::CACHED_SRC){ if(m_check_source.is_src_unused(m_upstream, iter_src->first, tmp_it_up_ss_map->first)){ if(--iter_src->second.robustness_counter == 0){ //save invalid sources tmp_erase_source_vector.push_back(iter_src->first); del_route(m_upstream, tmp_it_up_ss_map->first, iter_src->first); } }else{ iter_src->second.robustness_counter=MC_TV_ROBUSTNESS_VARIABLE; } }else{ HC_LOG_ERROR("upstream source is in unknown state: " << iter_src->second.state_type_to_string()); } } //erase invalid sources for(unsigned int i=0; i< tmp_erase_source_vector.size(); i++){ if((iter_src = tmp_ss_map->find(tmp_erase_source_vector[i])) != tmp_ss_map->end()){ tmp_ss_map->erase(iter_src); }else{ HC_LOG_ERROR("cant find invalid upstream soruce: " << tmp_erase_source_vector[i]); } } //if group has no sources remove the group if(tmp_it_up_ss_map->second.size() == 0){ tmp_erase_group_vector.push_back(tmp_it_up_ss_map->first); } } //erase unused groups for(unsigned int i=0; i < tmp_erase_group_vector.size(); i++){ tmp_it_up_ss_map = m_upstream_state.find(tmp_erase_group_vector[i]); if(tmp_it_up_ss_map != m_upstream_state.end()){ m_upstream_state.erase(tmp_it_up_ss_map); }else{ HC_LOG_ERROR("cant find unused groups: " << tmp_erase_group_vector[i]); } } //initiate new GQ msg.type = proxy_msg::CLOCK_MSG; msg.msg = new struct clock_msg(clock_msg::SEND_GQ_TO_ALL); m_timing->add_time(MC_TV_QUERY_INTERVAL*1000 /*msec*/,this,msg); break; } case clock_msg::SEND_GSQ: { iter_table =m_state_table.find(c->if_index); if(iter_table == m_state_table.end()) return; iter_state = iter_table->second.find(c->g_addr); if(iter_state == iter_table->second.end()) return; sgs_pair = &iter_state->second; if(sgs_pair->second.flag == src_state::RESPONSE_STATE){ m_sender->send_group_specific_query(c->if_index,c->g_addr); if(--sgs_pair->second.robustness_counter == PROXY_INSTANCE_DEL_IMMEDIATELY){ sgs_pair->second.flag = src_state::WAIT_FOR_DEL; msg.type = proxy_msg::CLOCK_MSG; msg.msg = new struct clock_msg(clock_msg::DEL_GROUP, iter_table->first, iter_state->first); if(m_addr_family == AF_INET){ m_timing->add_time(MC_TV_LAST_MEMBER_QUERY_INTEVAL*1000 /*msec*/,this,msg); }else if(m_addr_family == AF_INET6){ m_timing->add_time(MC_TV_LAST_LISTENER_QUERY_INTERVAL*1000 /*msec*/,this,msg); }else{ HC_LOG_ERROR("wrong addr_family: " << m_addr_family); return; } }else{ msg.type = proxy_msg::CLOCK_MSG; msg.msg = new struct clock_msg(clock_msg::SEND_GSQ, iter_table->first, iter_state->first); if(m_addr_family == AF_INET){ m_timing->add_time(MC_TV_LAST_MEMBER_QUERY_INTEVAL*1000 /*msec*/,this,msg); }else if(m_addr_family== AF_INET6){ m_timing->add_time(MC_TV_LAST_LISTENER_QUERY_INTERVAL*1000 /*msec*/,this,msg); }else{ HC_LOG_ERROR("wrong addr_family: " << m_addr_family); return; } } } break; } case clock_msg::DEL_GROUP:{ iter_table =m_state_table.find(c->if_index); if(iter_table == m_state_table.end()) return; iter_state = iter_table->second.find(c->g_addr); if(iter_state == iter_table->second.end()) return; sgs_pair = &iter_state->second; if(sgs_pair->second.flag == src_state::WAIT_FOR_DEL){ HC_LOG_DEBUG("DEL_GROUP if_index: " << c->if_index << " group: " << c->g_addr); //refresh upstream if(!is_group_joined(c->if_index,c->g_addr)){ if(!m_sender->send_leave(m_upstream, c->g_addr)){ HC_LOG_ERROR("failed to leave on upstream group: " << c->g_addr); } } //del only if no FOREIGN_SRC available if(sgs_pair->first.size() == 0){ iter_table->second.erase(iter_state); }else{ //set groupstate to INIT sgs_pair->second.flag = src_state::INIT; } //refresh routing //cout << "in del group: refresh_all_traffic()..." << endl; refresh_all_traffic(c->if_index, c->g_addr); } break; } case clock_msg::SEND_GQ: break; //start up Query Interval vor new interfaces default: HC_LOG_ERROR("unknown clock message foramt"); } }
void proxy_instance::handle_igmp(struct receiver_msg* r){ HC_LOG_TRACE(""); state_table_map::iterator iter_table; g_state_map::iterator iter_state; src_state_map::iterator iter_src; src_group_state_pair* sgs_pair; proxy_msg msg; switch(r->type){ case receiver_msg::JOIN: { //upstream joins are uninteresting if(r->if_index == m_upstream) return; iter_table =m_state_table.find(r->if_index); if(iter_table == m_state_table.end()) return; iter_state = iter_table->second.find(r->g_addr); if(iter_state == iter_table->second.end()){ //add group struct src_state tmp_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::RUNNING); iter_table->second.insert(g_state_pair(r->g_addr,src_group_state_pair(src_state_map(), tmp_state))); //--refresh upstream if(!is_group_joined(r->if_index,r->g_addr)){ if(!m_sender->send_report(m_upstream, r->g_addr)){ HC_LOG_ERROR("failed to join on upstream group: " << r->g_addr); return; } } //--refresh routing refresh_all_traffic(r->if_index, r->g_addr); }else{ //refresh group sgs_pair = &iter_state->second; sgs_pair->second.robustness_counter = MC_TV_ROBUSTNESS_VARIABLE; sgs_pair->second.flag = src_state::RUNNING; } break; } case receiver_msg::LEAVE:{ //cout << "leave an if: " << r->if_index << " für gruppe:" << r->g_addr << " empfangen" << endl; //upstream leaves are uninteresting if(r->if_index == m_upstream) return; iter_table =m_state_table.find(r->if_index); if(iter_table == m_state_table.end()) return; iter_state = iter_table->second.find(r->g_addr); if(iter_state == iter_table->second.end()) return; sgs_pair = &iter_state->second; sgs_pair->second.flag = src_state::RESPONSE_STATE; msg.type = proxy_msg::CLOCK_MSG; msg.msg = new struct clock_msg(clock_msg::SEND_GSQ, iter_table->first, iter_state->first); if(m_addr_family == AF_INET){ sgs_pair->second.robustness_counter = MC_TV_LAST_MEMBER_QUERY_COUNT; m_timing->add_time(MC_TV_LAST_MEMBER_QUERY_INTEVAL*1000 /*msec*/,this,msg); }else if(m_addr_family== AF_INET6){ sgs_pair->second.robustness_counter = MC_TV_LAST_LISTENER_QUERY_COUNT; m_timing->add_time(MC_TV_LAST_LISTENER_QUERY_INTERVAL*1000 /*msec*/,this,msg); }else{ HC_LOG_ERROR("wrong addr_family: " << m_addr_family); return; } break; } case receiver_msg::CACHE_MISS: { if(r->if_index == m_upstream){ upstream_src_state_map::iterator it_gss = m_upstream_state.find(r->g_addr); if(it_gss == m_upstream_state.end()){ //new group found struct src_state tmp_src_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::UNUSED_SRC); src_state_map tmp_src_state_map; tmp_src_state_map.insert(src_state_pair(r->src_addr,tmp_src_state)); m_upstream_state.insert(upstream_src_state_pair(r->g_addr,tmp_src_state_map)); }else{ // insert in existing group iter_src = it_gss->second.find(r->src_addr); if(iter_src == it_gss->second.end()){ //new src addr struct src_state tmp_src_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::UNUSED_SRC); it_gss->second.insert(src_state_pair(r->src_addr,tmp_src_state)); }else{ //src exist HC_LOG_DEBUG("kernel msg with src: " << r->src_addr << " received, this source address exist for if_index: " << r->if_index << " and group:" << r->g_addr << " because it's normaly not joined on a downstream interface"); return; } } //refresh routing if(split_traffic(r->if_index, r->g_addr, r->src_addr)){ // versetzt nach split traffic // upstream_src_state_map::iterator it_gss = m_upstream_state.find(r->g_addr); // if(it_gss == m_upstream_state.end()){ // HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find upstream g_addr:" << r->g_addr); // return; // } // iter_src = it_gss->second.find(r->src_addr); // if(iter_src == it_gss->second.end()){ // HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find to g_addr:" << r->g_addr << " the source:" << r->src_addr); // return; // } // iter_src->second.flag = src_state::CACHED_SRC; } }else{ //downstream cache miss iter_table =m_state_table.find(r->if_index); if(iter_table == m_state_table.end()) return; iter_state = iter_table->second.find(r->g_addr); if(iter_state == iter_table->second.end()) { //new group found struct src_state tmp_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::UNUSED_SRC); struct src_state tmp_state_group; src_state_map tmp_src_state_map; tmp_src_state_map.insert(src_state_pair(r->src_addr,tmp_state)); iter_table->second.insert(g_state_pair(r->g_addr, src_group_state_pair(tmp_src_state_map, tmp_state_group))); }else{ //insert in existing group sgs_pair = &iter_state->second; iter_src = sgs_pair->first.find(r->src_addr); if(iter_src == sgs_pair->first.end()){ //new src found, add to list struct src_state tmp_state(MC_TV_ROBUSTNESS_VARIABLE, src_state::UNUSED_SRC); sgs_pair->first.insert(src_state_pair(r->src_addr,tmp_state)); }else{ //error old src found HC_LOG_ERROR("kernel msg with src: " << r->src_addr << " received, this source address exist for if_index: " << r->if_index << " and group:" << r->g_addr); return; } } //refresh routing if(split_traffic(r->if_index, r->g_addr, r->src_addr)){ // versetzt nach split traffic // iter_state = iter_table->second.find(r->g_addr); // if(iter_state == iter_table->second.end()) { // HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find downstream g_addr:" << r->g_addr); // return; // } // sgs_pair = &iter_state->second; // iter_src = sgs_pair->first.find(r->src_addr); // if(iter_state == iter_table->second.end()) { // HC_LOG_ERROR("CACHE_MISS refresh routing: failed to find to g_addr:" << r->g_addr << " the source:" << r->src_addr); // return; // } // iter_src->second.flag = src_state::CACHED_SRC; } } break; } default: HC_LOG_ERROR("unknown receiver messge format"); } }
void proxy_instance::worker_thread(){ HC_LOG_TRACE(""); proxy_msg m; state_table_map::iterator it_state_table; //##-- add all interfaces --## //upsteam registrate_if(m_upstream); //downsteams (only one) for ( it_state_table=m_state_table.begin() ; it_state_table != m_state_table.end(); it_state_table++ ){ registrate_if(it_state_table->first); } //##-- general query --## //nach registrate_if ausgelagert //send_gq_to_all(); //##-- initiate GQ timer --## m.type = proxy_msg::CLOCK_MSG; m.msg = new struct clock_msg(clock_msg::SEND_GQ_TO_ALL); m_timing->add_time(MC_TV_QUERY_INTERVAL*1000 /*msec*/,this,m); //##-- thread working loop --## while(m_running){ m = m_job_queue.dequeue(); HC_LOG_DEBUG("received new job. type: " << m.msg_type_to_string()); switch(m.type){ case proxy_msg::TEST_MSG: { struct test_msg* t= (struct test_msg*) m.msg.get(); t->test(); break; } case proxy_msg::RECEIVER_MSG: { struct receiver_msg* t= (struct receiver_msg*) m.msg.get(); handle_igmp(t); break; } case proxy_msg::CLOCK_MSG: { struct clock_msg* t = (struct clock_msg*) m.msg.get(); handle_clock(t); break; } case proxy_msg::CONFIG_MSG: { struct config_msg* t = (struct config_msg*) m.msg.get(); handle_config(t); break; } case proxy_msg::DEBUG_MSG: { struct debug_msg* t = (struct debug_msg*) m.msg.get(); handle_debug_msg(t); break; } case proxy_msg::EXIT_CMD: m_running = false; break; default: HC_LOG_ERROR("unknown message format"); } } //##-- timing --## //remove all running times m_timing->stop_all_time(this); //##-- del all interfaces --## //upsteam unregistrate_if(m_upstream); //downsteams for ( it_state_table=m_state_table.begin() ; it_state_table != m_state_table.end(); it_state_table++ ){ unregistrate_if(it_state_table->first); } HC_LOG_DEBUG("worker thread proxy_instance end"); }
void worker::add_msg(proxy_msg& msg){ HC_LOG_TRACE(""); HC_LOG_DEBUG("message type:" << msg.msg_type_to_string()); m_job_queue.enqueue(msg); }