#### ASpath-tree v.4.2 - Released on Thu APR 17 2003, h.16:58:12
#### File: lib/bgp-tree-changes.pl Last modified on Fri APR 11 2003, h.23:56:29

# Routine to check if changes  in the ASpath tree happened since last recorded tree
# (input: type of tree -whole (0), bb (1), otherIANA (3)-, output: flag_changed (1=yes),
# last_change_time, @keys containing aspaths)
sub check_update_changes {
	my ($tree_type) = @_;

	my ($key, $el, $flag_tmp, $num_as, $ncol);
	my ($tree_changes, $lastchange_time, $datefile, $aspathsfile) = (0, 0, '', '');
	my @tmp = ();
	my @keys = ();
	my @asn = ();
	my %test = ();

# Set and sort ASpaths array for $tree_type
	if ($tree_type == 0) { # WHOLE Changes
		if (open(DATEFILE, "<$OLDDATEFILE")) {
			$lastchange_time = <DATEFILE>;
			close(OLDDATEFILE);
		}
		if (%CHANGESALL || !(-e $OLDASPATHSFILE)) {
			unless (-e $OLDASPATHSFILE) {$tree_changes = 2}
			else {$tree_changes = 1}
			$datefile = $OLDDATEFILE;
			$aspathsfile = $OLDASPATHSFILE;
			@keys = (keys(%TREE_ROWS));
			open(ASPATHFILE, ">$aspathsfile");
			foreach $key (sort(@keys)) {
				@tmp  = &convert_asn($key);
				foreach $el (@tmp) {if ($el > 65535) {$el = $ASSET{$el}}}
				print ASPATHFILE join(" ", @tmp)."\n";
			}
			close(ASPATHFILE);
			foreach $key (keys(%CHANGESALL)) {
				if ($CHANGESALL{$key} eq 'old') {push(@keys, $key)}
			}
		}
		$ncol = length($keys[0])/5;
	}
	elsif ($tree_type == 1) {
		if (open(DATEFILE, "<$OLDBBDATEFILE")) {
			$lastchange_time = <DATEFILE>;
			close(OLDDATEFILE);
		}
		if (%CHANGESBBS || @NMOREPTLAS || @NEWRPTLAS || !(-e $OLDBBASPATHSFILE)) {
			unless (-e $OLDBBASPATHSFILE) {$tree_changes = 2}
			else {$tree_changes = 1}
			$datefile = $OLDBBDATEFILE;
			$aspathsfile = $OLDBBASPATHSFILE;
			foreach $key (keys(%TREE_ROWS)) {
				$TREE_ROWS{$key} =~ /(\S+)\s+(\S+)\s+(\S+)/;
				$flag_tmp = $1;
				$num_as = $2;
				if ($flag_tmp =~ /1/) {
					push(@keys, $key);
					if ($ncol < $num_as) {$ncol = $num_as}
				}
			}
			open(ASPATHFILE, ">$aspathsfile");
			foreach $key (sort(@keys)) {
				@tmp  = &convert_asn($key);
				foreach $el (@tmp) {if ($el > 65535) {$el = $ASSET{$el}}}
				print ASPATHFILE join(" ", @tmp)."\n";
			}
			close(ASPATHFILE);
			foreach $key (keys(%CHANGESBBS)) {
				if ($CHANGESBBS{$key} eq 'old') {
					push(@keys, $key);
					@tmp = &convert_asn($key);
					if ($ncol < @tmp) {$ncol = @tmp}
				}
			}
		}
	}
	elsif ($tree_type == 3) {
		if (open(DATEFILE, "<$OLDOTHDATEFILE")) {
			$lastchange_time = <DATEFILE>;
			close(OLDDATEFILE);
		}
		if (%CHANGESOTH || !(-e $OLDOTHASPATHSFILE)) {
			unless (-e $OLDOTHASPATHSFILE) {$tree_changes = 2}
			else {$tree_changes = 1}
			$datefile = $OLDOTHDATEFILE;
			$aspathsfile = $OLDOTHASPATHSFILE;
			foreach $key (keys(%TREE_ROWS)) {
				$TREE_ROWS{$key} =~ /(\S+)\s+(\S+)\s+(\S+)/;
				$flag_tmp = $1;
				$num_as = $2;
				if ($flag_tmp =~ /3/) {
					push(@keys, $key);
					if ($ncol < $num_as) {$ncol = $num_as}
				}
			}
			open(ASPATHFILE, ">$aspathsfile");
			foreach $key (sort(@keys)) {
				@tmp  = &convert_asn($key);
				foreach $el (@tmp) {if ($el > 65535) {$el = $ASSET{$el}}}
				print ASPATHFILE join(" ", @tmp)."\n";
			}
			close(ASPATHFILE);
			foreach $key (keys(%CHANGESOTH)) {
				if ($CHANGESOTH{$key} eq 'old') {
					push(@keys, $key);
					@tmp = &convert_asn($key);
					if ($ncol < @tmp) {$ncol = @tmp}
				}
			}
		}
	}
	if ($tree_changes) {
# Record current time as last change time
		if ($tree_changes == 1) {$lastchange_time = $CURRENTTIME}
		else {$lastchange_time = 0}
		open(DATEFILE, ">$datefile");
		print DATEFILE "$lastchange_time";
		close(OLDDATEFILE);
# Create html page for changes tree
		if ($CHANGESFLAG) {
			@keys = sort(@keys);
			&create_html_tree_changes($tree_type, $ncol, \@keys);
		}
	}
	return($lastchange_time);
}

# Routine to create $tree_type (0=whole, 1=backbone, 3=otherIANA) changes tree
sub create_output_table_changes {
	my ($tree_type, $ncol, $keys_index) = @_;

	my %test = ();
	my @sim = ("<IMG SRC=\"../$ICONS/e.gif\">",
                  "<IMG SRC=\"../$ICONS/v.gif\">",
                  "<IMG SRC=\"../$ICONS/h.gif\">",
                  "<IMG SRC=\"../$ICONS/l.gif\">",
                  "<IMG SRC=\"../$ICONS/t.gif\">",
                  "");
	my %color = ();
	   $color{new} = '#c0ffc0';
	   $color{old} = '#c0c0c0';
	my @asn_0 = ();
	my @asn_1 = ();
	my @asn_2 = ();
	my @bar = ();
	my @cell = ();
	my @f_table = ();
	my @bgc = ();
	my @keys = @$keys_index;
	my ($i, $j, $n, $l, $k, $numrows, $flagL) = (0, 0, 0, 0, 0, 0, 0);
	my ($key, $bgctext, $status, $asn_toprint) = ('', '', '', '');

	$ncol--;
	if ($tree_type == 0)    {%test = %CHANGESALL}
	elsif ($tree_type == 1) {%test = %CHANGESBBS}
	elsif ($tree_type == 3) {%test = %CHANGESOTH}

	unless (@keys) {return(())};
	for ($j = $#keys; $j >= 0; $j--) {
		@asn_1 = &convert_asn($keys[$j]);
		if ($j > 0) {@asn_2 = &convert_asn($keys[$j-1])}
		else {@asn_2 = ()}
		if ($numrows > 0) { # bgcolor already set
			$numrows--;
		}
		elsif ($test{$keys[$j]}) { # new or old line
			$status = $test{$keys[$j]};
			$bgctext = " BGCOLOR=\"$color{$status}\"";
			if ($bgctext) {
				for  ($l = $j; $l >=0; $l--) {
					if ($test{$keys[$l]} ne $status) {last}
				}
				$numrows = $j - $l - 1;
				($flagL, @bgc) = &set_bgc_array($ncol, $j, $numrows, \@keys, \@bar, $bgctext);
			}
		}
		else { # stable lines
			$bgctext = '';
			$flagL = 0;
			@bgc = ();
		}
		$n = $ncol*2+1;
		for ($i = $ncol; $i >= 0; $i--) {
			if (!defined($asn_1[$i])) {$n = $n-2}
			elsif (join("", @asn_1[(0)..($i)]) ne join("", @asn_2[(0)..($i)])) {
				if ($i eq $#asn_1) {
					$colspan = $ncol*2 - $n + 1;
					if ($colspan > 0) {$cell[$n+1] = "<TD COLSPAN=$colspan></TD>"}
				}
				$asn_toprint =substr($ASNAME{$asn_1[$i]}, 0, 11);
				$asn_toprint =~ s/-/\&nbsp\;/g;
				$cell[$n--] = "<TD$bgc[$n]>$asn_toprint</TD>";
				if (join("", @asn_1[(0)..($i-1)]) eq join("", @asn_2[(0)..($i-1)])) {
					if (!defined($asn_2[$i])) {
						if ($bar[$i]) {
							$cell[$n--] = "<TD$bgc[$n] VALIGN=bottom>".$sim[0]."</TD>";
							$bar[$i] = "";
						}
						else {$cell[$n--] = "<TD$bgc[$n]>".$sim[2]."</TD>"}
					}
					else {
						if ($bar[$i]) {$cell[$n--] = "<TD$bgc[$n]>".$sim[4]."</TD>"}
						else {
							$cell[$n--] = "<TD$bgc[$n]>".$sim[3]."</TD>";
							$bar[$i] = 1;
						}
					}
				}
				elsif ($bar[$i]) {
					$cell[$n--] = "<TD$bgc[$n] VALIGN=bottom>".$sim[0]."</TD>";
					$bar[$i] = "";
				}
				else {$cell[$n--] = "<TD$bgc[$n]>".$sim[2]."</TD>"}
			}
			elsif (!defined($asn_2[$i+1])) {
				$cell[$n--] = "<TD$bgc[$n] ALIGN=right>".$sim[3]."</TD>";
				if ($bar[$i]) {$cell[$n--] = "<TD$bgc[$n]>".$sim[1]."</TD>"}
				else {$cell[$n--] = "<TD$bgc[$n]>".$sim[5]."</TD>"}
			}
			else {
				$cell[$n--] = "<TD$bgc[$n]>".$sim[5]."</TD>";
				if ($bar[$i]) {$cell[$n--] = "<TD$bgc[$n]>".$sim[1]."</TD>"}
				else {$cell[$n--] = "<TD$bgc[$n]>".$sim[5]."</TD>"}
			}
		} #end for columns
		$f_table[$j] = join("", @cell);
		@cell = ();
	} #end for rows

	return(@f_table);
}

# routine to set the background color for tree table cells
# On input:
#   ncol: number of ASs in longest row
#   j: position of considered ASPath
#   numrows: number of consecutive rows that share the same background color
#   aspaths: pointer to array of encoded ASPaths
#   bar: pointer to array of continuing vertical bar for the considered ASPath
#   bgctext: html format background color to be used
# On output:
#   prevprev: flag to indicate the presence of a "L" symbol "before" coloured area
#   bgc: array of cell background colors in html format
sub set_bgc_array {
	my ($ncol, $j, $numrows, $aspaths, $bar, $bgctext) = @_;
	my (@v1, @v2, @bgc);
	my ($max, $i, $prev, $prevprev, $mini, $notcommonAS, $found) = (0, 0, 0, 0, 0, 0, 0);

	@v1 = &convert_asn($$aspaths[$j]);
	if ($j < $#$aspaths) { # compare with previous line (from bottom to top)
		@v2 = &convert_asn($$aspaths[$j+1]);
		if ($#v1 > $#v2) {$max = $#v2}
		else {$max = $#v1}
		for ($i=$max; $i >=0; $i--) {
			if (join("", @v1[(0)..($i)]) eq join("", @v2[(0)..($i)])) {
				$found = 1;
				last;
			}
		}
		if ($found) {$notcommonAS = $i+1}
	}
	$found = 0;
	if ($j > ($numrows+1)) { # compare with the first next line with different bgcol (from bottom to top)
		if ($numrows > 0) {@v1 = &convert_asn($$aspaths[$j-$numrows])}
		@v2 = &convert_asn($$aspaths[$j-$numrows-1]);
		if ($#v1 > $#v2) {$max = $#v2}
		else {$max = $#v1}
		for ($i=$max; $i >=0; $i--) {
			if (join("", @v1[(0)..($i)]) eq join("", @v2[(0)..($i)])) {
				$found = 1;
				last;
			}
		}
		if ($found && $i >= $notcommonAS) {$notcommonAS = $i+1}
	}
	else {@v2 = ()}

	if ($$bar[$notcommonAS] || ($found && defined($v2[$notcommonAS]))) {$prev = 0}
	else {$prev = 1}

	if ($prev) {$mini = 2*$notcommonAS}
	else {$mini = 2*$notcommonAS + 1}
	for ($i= $mini; $i <= 2*$ncol+1; $i++) {$bgc[$i] = $bgctext}

	return($prevprev, @bgc);
}

# Routine to generate HTML files for changes tree tables
sub create_html_tree_changes {
	my ($tree_type, $ncol, $index) = @_;

	my ($output_file, $title, $img_src, $tree_change);
	my $i = 0;
	my @tree = ();

	if ($tree_type == 0) { # complete
		$output_file = $OUTPUTCOMPLETECHANGES;
		$title = "The whole IPv6 BGP table: changes";
	}
	elsif ($tree_type == 1) { # backbone
		$output_file = $OUTPUTBBCHANGES;
		$title = "IPv6 BGP table: backbone changes";
	}
	elsif ($tree_type == 3) { # otherIANA
		$output_file = $OUTPUTIANACHANGES;
		$title = "IPv6 BGP table: &quot;2001 &quot;routes changes";
	}

	open(HTMLFILE,">".$output_file);

	print HTMLFILE &header($title, 1);

	print HTMLFILE "<TABLE>\n<TR>";
	if ($SITEPICTURE) {
		print HTMLFILE "<TD VALIGN=top ROWSPAN=3><IMG SRC=\"../$ICONS/$SITEPICTURE\" BORDER=0></TD>\n";
	}
	print HTMLFILE "<TD VALIGN=bottom ALIGN=center CLASS=a32b>$title</TD></TR>\n";
	print HTMLFILE "<TR><TD ALIGN=center VALIGN=top CLASS=n10b>Updated on $LONGDATE</TD></TR>\n";
	print HTMLFILE "<TR><TD></TD></TR>\n";
        print HTMLFILE "<TR><TD COLSPAN=2 ALIGN=right CLASS=n10>lost branch&nbsp;";
	print HTMLFILE "<IMG SRC=\"../$ICONS/bold.gif\" ALIGN=ABSCENTER></TD></TR>\n";
        print HTMLFILE "<TR><TD COLSPAN=2 ALIGN=right CLASS=n10>new branch&nbsp;";
	print HTMLFILE "<IMG SRC=\"../$ICONS/bnew.gif\" ALIGN=ABSCENTER></TD></TR>\n";

	print HTMLFILE "</TABLE>\n";
	print HTMLFILE "<P>\n";
	print HTMLFILE "<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>\n";
	if ($ROOTPICTURE) {
		$img_src = "<IMG SRC=\"../$ICONS/$ROOTPICTURE\">";
	}
	else {
		$img_src = $SITENAME."&nbsp;";
	}
	@tree = &create_output_table_changes($tree_type, $ncol, $index);

	print HTMLFILE "<TR><TD CLASS=a16b>$img_src</TD>$tree[0]</TR>\n";
	for ($i = 1; $i < @tree; $i++) {
		print HTMLFILE "<TR ALIGN=center><TD></TD>$tree[$i]</TR>\n";
	}

	print HTMLFILE "</TABLE>\n";

# The BB IPv6 BGP table
	if ($tree_type == 1) {
		if (@NMOREPTLAS || @NEWRPTLAS) {print HTMLFILE "<HR>\n"}
		if (@NMOREPTLAS) {
			$i = 0;
			print HTMLFILE "<SPAN CLASS=n12>The following pTLAs become unreachable:&nbsp;&nbsp;</SPAN><SPAN CLASS=a10>";
			for (@NMOREPTLAS) {
				print HTMLFILE "$_";
				if ($i < (@NMOREPTLAS-1)) {print HTMLFILE "<TT><B>, </B></TT>"}
				$i++;
			}
			print HTMLFILE "</SPAN><P>\n";
		}
		if (@NEWRPTLAS) {
			$i = 0;
			print HTMLFILE "<SPAN CLASS=n12>The following pTLAs become reachable:&nbsp;&nbsp;</SPAN><SPAN CLASS=a10>";
			for (@NEWRPTLAS) {
				print HTMLFILE "$_";
				if ($i < (@NEWRPTLAS-1)) {print HTMLFILE "<TT><B>, </B></TT>"}
				$i++;
			}
		}
	}

	print HTMLFILE "
	</SPAN><HR>\n<SPAN CLASS=n10>\n
	This page provides a graphical view of the last changes occurred on the IPv6 BGP routing tree.
	Branches highlighted in green boxes are new, while branches highlighted in gray boxes disappeared.
        <HR>\n".&footer."
        </SPAN>\n</BODY>\n</HTML>\n";

	close(HTMLFILE);

	$output_file =~ m!([^/]*)$!;
	&log_it("    $1 created", 1);
	return(0);
}

(1);
#### ASpath-tree v.4.2 - Released on Thu APR 17 2003, h.16:58:12
#### File: lib/bgp-tree-changes.pl Last modified on Fri APR 11 2003, h.23:56:29
