Exemple #1
0
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 ++;
	}
}
Exemple #2
0
int
main( int argc, char *argv[] ) {
  init_trema( &argc, &argv );

  dump_filter();

  start_trema();
}
Exemple #3
0
void group_interface::dump_filter() const {
	if (should_log(DEBUG)) {
		base_stream &os = log();

		os.write("Filter is now ");
		dump_filter(os);
		os.newl();
	}
}
Exemple #4
0
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();
}
Exemple #5
0
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();
}
Exemple #6
0
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;
	}
}