void mld_group_interface::handle_last_listener_query() { if (g_last_listener_query_count == g_intf->conf()->last_listener_query_count()) { /* If we reach here, no one reported */ g_last_listener_timer.stop(); delete_sources(g_exclude_set); g_include_set.clear(); g_request_set.clear(); g_exclude_set.clear(); g_filter_mode = include; dump_filter(); owner()->trigger_mode_event(this, all_sources, address_set()); owner()->someone_lost_interest(); } else { /* Send Q(MA) */ send_mld_query(true); g_last_listener_query_count ++; } }
int main( int argc, char *argv[] ) { init_trema( &argc, &argv ); dump_filter(); start_trema(); }
void group_interface::dump_filter() const { if (should_log(DEBUG)) { base_stream &os = log(); os.write("Filter is now "); dump_filter(os); os.newl(); } }
void mld_group_interface::handle_filter_timer() { delete_sources(g_exclude_set); g_include_set = g_request_set; g_request_set.clear(); g_exclude_set.clear(); g_filter_mode = include; dump_filter(); owner()->trigger_mode_event(this, all_sources, address_set()); if (g_include_set.empty()) owner()->someone_lost_interest(); }
void mld_group_interface::delete_sources(const address_set &sources) { bool changed = false; for (address_set::const_iterator i = sources.begin(); i != sources.end(); ++i) { for (std::vector<source_timer>::iterator k = g_sources_timers.begin(); k != g_sources_timers.end(); ++k) { if (k->argument() == *i) { g_sources_timers.erase(k); if (g_include_set.has_addr(*i)) { g_include_set.remove(*i); if (g_filter_mode == include) { changed = true; owner()->trigger_mode_event(this, removed_sources, *i); if (g_include_set.empty()) { if (owner()->someone_lost_interest()) return; } } } else if (g_request_set.has_addr(*i)) { g_request_set.remove(*i); g_exclude_set.insert(*i); changed = true; owner()->trigger_mode_event(this, added_sources, *i); } else if (g_exclude_set.has_addr(*i)) { g_exclude_set.remove(*i); changed = true; owner()->trigger_mode_event(this, removed_sources, *i); } break; } } } if (changed) dump_filter(); }
void mld_group_interface::refresh(const inet6_addr &src, int mode, const address_set &sources) { if (g_last_listener_timer.is_running() && !((mode == MLD_SSM_CHANGE_TO_INCLUDE || mode == MLD_SSM_MODE_INCLUDE) && sources.empty())) { /* Cancel fast-leave */ g_last_listener_timer.stop(); } g_last_reporter = src; if (should_log(MESSAGE_SIG)) { log().xprintf("Refresh triggered by %{Addr} with mode" " %s and sources %{addrset}.\n", src, _mode_name(mode), sources); } address_set diff; switch (g_filter_mode) { case include: switch (mode) { case MLD_SSM_CHANGE_TO_INCLUDE: /* Router State: INCLUDE(A) * Report Received: TO_IN(B) * New Router State: INCLUDE(A+B) * Actions: (B)=MALI, Send Q(MA,A-B) */ /* Send Q(MA,A-B) */ send_mld_query(false, g_include_set - sources); /* the rest is processed below */ case MLD_SSM_ALLOW_SOURCES: case MLD_SSM_MODE_INCLUDE: /* Router State: INCLUDE(A) * Report Received: ALLOW(B), INCLUDE(B) * New Router State: INCLUDE(A+B) * Actions: (B)=MALI */ /* A = A+B */ g_include_set.union_with(sources, diff); /* (B)=MALI */ update_sources_timer(sources); if (!diff.empty()) { dump_filter(); owner()->trigger_mode_event(this, added_sources, diff); } break; case MLD_SSM_CHANGE_TO_EXCLUDE: /* Router State: INCLUDE(A) * Report Received: TO_EX(B) * New Router State: EXCLUDE(A*B,B-A) * Actions: (B-A)=0, Delete (A-B), Send Q(MA,A*B), Filter Timer=MALI */ /* Send Q(MA,A*B) */ send_mld_query(false, g_include_set * sources); /* the rest is processed below */ case MLD_SSM_MODE_EXCLUDE: /* Router State: INCLUDE(A) * Report Received: EXCLUDE(B) * New Router State: EXCLUDE(A*B,B-A) * Actions: (B-A)=0, Delete (A-B), Filter Timer=MALI */ g_filter_mode = exclude; /* X = A*B */ g_request_set = g_include_set * sources; /* Y = B-A */ g_exclude_set = sources - g_include_set; /* Delete (A-B) */ delete_sources(g_include_set - sources); /* Filter Timer=MALI */ restart_filter_timer(); dump_filter(); owner()->trigger_mode_event(this, all_sources, address_set()); break; case MLD_SSM_BLOCK_SOURCES: /* Router State: INCLUDE(A) * Report Received: BLOCK(B) * New Router State: INCLUDE(A) * Actions: Send Q(MA,A*B) */ /* Fast leave */ update_sources_timer(sources, g_intf->conf()->last_listener_query_interval() + 500); send_mld_query(false, sources); /* Send Q(MA,A*B) */ send_mld_query(false, g_include_set * sources); break; } break; case exclude: switch (mode) { case MLD_SSM_CHANGE_TO_INCLUDE: /* Router State: EXCLUDE(X,Y) * Report Received: TO_IN(A) * New Router State: EXCLUDE(X+A,Y-A) * Actions: (A)=MALI, Send Q(MA,X-A), Send Q(MA) */ /* Send Q(MA,X-A) */ send_mld_query(false, g_request_set - sources); /* Send Q(MA) */ send_mld_query(true); start_fast_leave(); case MLD_SSM_MODE_INCLUDE: /* Router State: EXCLUDE(X,Y) * Report Received: INCLUDE(A) * New Router State: EXCLUDE(X+A,Y-A) * Actions: (A)=MALI */ /* X = X+A */ g_request_set.union_with(sources); /* Y = Y-A */ g_exclude_set.diff_with(sources, diff); /* (A)=MALI */ update_sources_timer(sources); if (!diff.empty()) { dump_filter(); owner()->trigger_mode_event(this, removed_sources, diff); } break; case MLD_SSM_CHANGE_TO_EXCLUDE: /* Router State: EXCLUDE(X,Y) * Report Received: TO_EX(A) * New Router State: EXCLUDE(A-Y,Y*A) * Actions: (A-X-Y)= Filter Timer, Delete (X-A), Delete (Y-A) * Send Q(MA,A-Y), Filter Timer=MALI */ /* Send Q(MA,A-Y) */ send_mld_query(false, sources - g_exclude_set); case MLD_SSM_MODE_EXCLUDE: /* Router State: EXCLUDE(X,Y) * Report Received: EXCLUDE(A) * New Router State: EXCLUDE(A-Y,Y*A) * Actions: (A-X-Y)=Filter Timer, Delete (X-A), Delete (Y-A) * Filter Timer=MALI */ /* (A-X-Y)=Filter Timer */ update_sources_timer(sources - g_request_set - g_exclude_set, g_filter_timer.time_left()); /* Delete (X-A) */ delete_sources(g_request_set - sources); /* Delete (Y-A) */ delete_sources(g_exclude_set - sources); /* X = A-Y */ g_request_set = sources - g_exclude_set; /* Y = Y*A */ g_exclude_set.intersect_with(sources); /* Filter Timer=MALI */ restart_filter_timer(); break; case MLD_SSM_ALLOW_SOURCES: /* Router State: EXCLUDE(X,Y) * Report Received: ALLOW(A) * New Router State: EXCLUDE(X+A,Y-A) * Actions: (A)=MALI */ /* X = X+A */ g_request_set.union_with(sources); /* Y = Y-A */ g_exclude_set.diff_with(sources, diff); /* (A)=MALI */ update_sources_timer(sources); if (!diff.empty()) { dump_filter(); owner()->trigger_mode_event(this, added_sources, diff); } break; case MLD_SSM_BLOCK_SOURCES: /* Router State: EXCLUDE(X,Y) * Report Received: BLOCK(A) * New Router State: EXCLUDE(X+(A-Y),Y) * Actions: (A-X-Y)=Filter Timer, Send Q(MA,A-Y) */ /* (A-X-Y)=Filter Timer */ update_sources_timer(sources - g_request_set - g_exclude_set, g_filter_timer.time_left()); /* Send Q(MA,A-Y) */ send_mld_query(false, sources - g_exclude_set); /* X = X+(A-Y) */ g_request_set.union_with(sources - g_exclude_set); break; } break; } }