├── .github └── workflows │ └── main.yml ├── Buildquirks.pm ├── GNUmakefile ├── Hostctl.pm ├── Html.pm ├── Kstat.pm ├── LICENSE ├── Logcmd.pm ├── Machine.pm ├── Netstat.pm ├── README ├── Testvars.pm ├── bsdcons.pl ├── build-ot14.list ├── build-ot15.list ├── cleanup.pl ├── cmd-ot1.list ├── cmd-ot10.list ├── cmd-ot11.list ├── cmd-ot17.list ├── cmd-ot19.list ├── cmd-ot2.list ├── cmd-ot21.list ├── cmd-ot25.list ├── cmd-ot26.list ├── cmd-ot27.list ├── cmd-ot33.list ├── cmd-ot41.list ├── cmd-ot42.list ├── cmd-ot48.list ├── cmd-ot5.list ├── cmd-ot52.list ├── cmd-ot57.list ├── cmd-ot6.list ├── cmd-ot62.list ├── cmd-ot7.list ├── cmd-ot71.list ├── cmd-ot72.list ├── cmd-ot73.list ├── cmd-ot74.list ├── cmd-ot8.list ├── cmd-ot81.list ├── cmd-ot91.list ├── cmd-ot92.list ├── cmd-ot93.list ├── cmd-ot94.list ├── cvsbuild.pl ├── cvslog.pl ├── env-ot1.sh ├── env-ot10.sh ├── env-ot11.sh ├── env-ot12.sh ├── env-ot14.sh ├── env-ot19.sh ├── env-ot2.sh ├── env-ot21.sh ├── env-ot25.sh ├── env-ot26.sh ├── env-ot27.sh ├── env-ot29.sh ├── env-ot3.sh ├── env-ot31.sh ├── env-ot33.sh ├── env-ot35.sh ├── env-ot4.sh ├── env-ot41.sh ├── env-ot42.sh ├── env-ot44.sh ├── env-ot48.sh ├── env-ot5.sh ├── env-ot50.sh ├── env-ot51.sh ├── env-ot52.sh ├── env-ot57.sh ├── env-ot6.sh ├── env-ot62.sh ├── env-ot7.sh ├── env-ot71.sh ├── env-ot72.sh ├── env-ot73.sh ├── env-ot74.sh ├── env-ot8.sh ├── env-ot81.sh ├── env-ot91.sh ├── env-ot92.sh ├── env-ot93.sh ├── env-ot94.sh ├── favicon.ink.svg ├── favicon.svg ├── force-ssh.pl ├── gnuplot.pl ├── keys.sh ├── kstack.sh ├── make.pl ├── makealign.sh ├── mktestlist.pl ├── net.pl ├── netbench.pl ├── netlink-html.pl ├── netlink.pl ├── once.pl ├── perform-html.pl ├── perform.pl ├── pkg-alpine.list ├── pkg-debian.list ├── pkg-ot1.list ├── pkg-ot10.list ├── pkg-ot11.list ├── pkg-ot12.list ├── pkg-ot14.list ├── pkg-ot15.list ├── pkg-ot19.list ├── pkg-ot2.list ├── pkg-ot21.list ├── pkg-ot25.list ├── pkg-ot26.list ├── pkg-ot27.list ├── pkg-ot29.list ├── pkg-ot3.list ├── pkg-ot31.list ├── pkg-ot32.list ├── pkg-ot33.list ├── pkg-ot4.list ├── pkg-ot41.list ├── pkg-ot42.list ├── pkg-ot48.list ├── pkg-ot5.list ├── pkg-ot50.list ├── pkg-ot51.list ├── pkg-ot57.list ├── pkg-ot6.list ├── pkg-ot62.list ├── pkg-ot7.list ├── pkg-ot71.list ├── pkg-ot72.list ├── pkg-ot73.list ├── pkg-ot74.list ├── pkg-ot8.list ├── pkg-ot81.list ├── pkg-ot91.list ├── pkg-ot92.list ├── pkg-ot93.list ├── pkg-ot94.list ├── plot.gp ├── ports.list ├── portstest.pl ├── power.pl ├── reboot.pl ├── regress-html.pl ├── regress.pl ├── release.pl ├── run.pl ├── running-html.pl ├── setup-html.pl ├── setup.pl ├── site-alpine.list ├── site-debian.list ├── site.list ├── step.pl ├── tables.js ├── test.list ├── test.pl └── testsuite-html.pl /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Install packages 16 | run: | 17 | sudo apt-get install --yes make perl-base 18 | sudo apt-get install --yes \ 19 | libdatetime-format-dateparse-perl \ 20 | libhtml-parser-perl 21 | - name: Checkout sources 22 | uses: actions/checkout@v4 23 | - name: Make syntax check 24 | run: make 25 | -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | LISTS = $(wildcard *.list) 2 | PLS = $(wildcard *.pl) 3 | PMS = $(wildcard *.pm) 4 | SHS = $(wildcard *.sh) 5 | SORTED = $(LISTS:.list=.sorted) 6 | SYNTAX = $(PMS:.pm=.syntax) $(PLS:.pl=.syntax) $(SHS:.sh=.syntax) 7 | 8 | .PHONY: all copyyear sorted syntax clean 9 | 10 | all: syntax sorted copyyear 11 | 12 | sorted: ${SORTED} 13 | 14 | %.sorted: %.list 15 | @sort -uc $< 16 | @echo $< sorted unique 17 | @date >$@ 18 | 19 | syntax: ${SYNTAX} 20 | 21 | %.syntax: %.pl 22 | @perl -c `sed -n '1s/^#!.* -T.*/-T/p;q' $<` $< 23 | @date >$@ 24 | 25 | %.syntax: %.pm 26 | @perl -I. -c $< 27 | @date >$@ 28 | 29 | %.syntax: %.sh 30 | @sh -n $< 31 | @echo $< syntax OK 32 | @date >$@ 33 | 34 | copyyear: LICENSE 35 | @grep -e "Copyright .*`date +%Y` " LICENSE 36 | 37 | clean: 38 | rm -f -- *.sorted *.syntax 39 | -------------------------------------------------------------------------------- /Hostctl.pm: -------------------------------------------------------------------------------- 1 | # functions to control a set of hosts 2 | 3 | # Copyright (c) 2018-2024 Alexander Bluhm 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | package Hostctl; 18 | 19 | use strict; 20 | use warnings; 21 | use Carp; 22 | use POSIX; 23 | 24 | use Logcmd; 25 | use Machine; 26 | 27 | use parent 'Exporter'; 28 | our @EXPORT= qw( 29 | usehosts setup_hosts 30 | collect_version collect_dmesg collect_result 31 | bsdcons_hosts cvsbuild_hosts powerdown_hosts powerup_hosts reboot_hosts 32 | setup_html current_html wait_html 33 | ); 34 | 35 | my %lasthosts = ( 36 | ot1 => "ot4", 37 | ot10 => "ot11", 38 | ot14 => "ot15", 39 | ot31 => "ot32", 40 | ); 41 | 42 | my ($bindir, $htmlprog, $user, $firsthost, $lasthost, $date, $verbose); 43 | 44 | sub usehosts { 45 | my %args = @_; 46 | ($bindir, $htmlprog, $date, $verbose) = 47 | delete @args{qw(bindir htmlprog date verbose)}; 48 | ($user, $firsthost) = split('@', delete $args{host}, 2); 49 | ($user, $firsthost) = ("root", $user) unless $firsthost; 50 | if ($args{lasthost}) { 51 | $lasthost = delete $args{lasthost}; 52 | $lasthost =~ s/.*@//; 53 | } 54 | my @unknown = keys %args; 55 | croak "Unknown args: @unknown" if @unknown; 56 | 57 | $lasthost ||= $lasthosts{$firsthost} || $firsthost 58 | and return; 59 | for (my $host = $firsthost; 60 | -f "$bindir/pkg-$host.list"; 61 | $lasthost = $host++) { 62 | # XXX hack to find out whether a remote machine exists 63 | } 64 | } 65 | 66 | sub setup_hosts { 67 | my %args = @_; 68 | my $patch = delete $args{patch}; 69 | my $release = delete $args{release}; 70 | my %mode = %{delete $args{mode}}; 71 | my @unknown = keys %args; 72 | croak "Unknown args: @unknown" if @unknown; 73 | 74 | my @pidcmds; 75 | for (my $host = $firsthost; $host le $lasthost; $host++) { 76 | my @setupcmd = ("$bindir/setup.pl", '-h', "$user\@$host"); 77 | push @setupcmd, '-d', $date if $date; 78 | push @setupcmd, '-v' if $verbose; 79 | push @setupcmd, '-P', $patch if $patch; 80 | push @setupcmd, '-r', $release if $release; 81 | push @setupcmd, keys %mode; 82 | push @pidcmds, forkcmd(@setupcmd); 83 | 84 | if ($mode{install} || $mode{upgrade} || $mode{sysupgrade}) { 85 | # create new summary with setup log 86 | sleep 5; 87 | setup_html(); 88 | } 89 | } 90 | if (@pidcmds) { 91 | # create new summary with setup log 92 | sleep 5; 93 | setup_html(); 94 | my @cmd = ("$bindir/running-html.pl"); 95 | system(@cmd); 96 | 97 | waitcmd(@pidcmds); 98 | } 99 | } 100 | 101 | sub collect_version { 102 | for (my $host = $firsthost; $host le $lasthost; $host++) { 103 | my $version = "version-$host.txt"; 104 | logeval { logcmd({ 105 | cmd => ['ssh', "$user\@$host", 'sysctl', 106 | 'kern.version', 'hw.machine', 'hw.ncpu', 'hw.ncpuonline'], 107 | outfile => $version, 108 | })}; 109 | if ($@) { 110 | unlink $version; 111 | last; 112 | } 113 | my $dmesg = "dmesg-boot-$host.txt"; 114 | logeval { logcmd({ 115 | cmd => ['ssh', "$user\@$host", 'cat', '/var/run/dmesg.boot'], 116 | outfile => $dmesg, 117 | })}; 118 | if ($@) { 119 | unlink $dmesg; 120 | last; 121 | } 122 | } 123 | } 124 | 125 | sub collect_dmesg { 126 | for (my $host = $firsthost; $host le $lasthost; $host++) { 127 | my $dmesg = "dmesg-$host.txt"; 128 | logeval { logcmd({ 129 | cmd => ['ssh', "$user\@$host", 'dmesg'], 130 | outfile => $dmesg, 131 | })}; 132 | if ($@) { 133 | unlink $dmesg; 134 | last; 135 | } 136 | } 137 | } 138 | 139 | sub collect_result { 140 | foreach my $source (@_) { 141 | my @scpcmd = ('scp'); 142 | push @scpcmd, '-q' unless $verbose; 143 | push @scpcmd, ("$source/test.*", "."); 144 | runcmd(@scpcmd); 145 | 146 | open(my $tr, '<', "test.result") 147 | or die "Open 'test.result' for reading failed: $!"; 148 | my $logdir = "logs"; 149 | -d $logdir || mkdir $logdir 150 | or die "Make directory '$logdir' failed: $!"; 151 | chdir($logdir) 152 | or die "Change directory to '$logdir' failed: $!"; 153 | my @paxcmd = ('pax', '-rzf', "../test.log.tgz"); 154 | open(my $pax, '|-', @paxcmd) 155 | or die "Open pipe to '@paxcmd' failed: $!"; 156 | while (<$tr>) { 157 | my ($status, $test, $message) = split(" ", $_, 3); 158 | next if $status =~ /VALUE/; 159 | print $pax $test unless $test =~ m,[^\w/],; 160 | } 161 | my $now = strftime("%FT%TZ", gmtime); 162 | close($pax) or die $! ? 163 | "Close pipe to '@paxcmd' failed: $!" : 164 | "$now Command '@paxcmd' failed: $?"; 165 | close($tr) 166 | or die "Close 'test.result' after reading failed: $!"; 167 | 168 | chdir("..") 169 | or die "Change directory to '..' failed: $!"; 170 | } 171 | } 172 | 173 | sub hosts_command { 174 | my ($command, %args) = @_; 175 | my $cvsdate = delete $args{cvsdate}; 176 | my $patch = delete $args{patch}; 177 | my $modify = delete $args{modify}; 178 | my $release = delete $args{release}; 179 | my $repeatdir = delete $args{repeatdir}; 180 | my %mode = %{delete $args{mode} || {}}; 181 | my @unknown = keys %args; 182 | croak "Unknown args: @unknown" if @unknown; 183 | 184 | my @pidcmds; 185 | for (my $host = $firsthost; $host le $lasthost; $host++) { 186 | my @cmd = ("$bindir/$command", '-h', "$user\@$host"); 187 | push @cmd, '-d', $date if $date; 188 | push @cmd, '-D', $cvsdate if $cvsdate; 189 | push @cmd, '-P', $patch if $patch; 190 | push @cmd, '-m', $modify if $modify; 191 | push @cmd, '-r', $release if $release; 192 | push @cmd, '-R', $repeatdir if $repeatdir; 193 | push @cmd, '-v' if $verbose; 194 | push @cmd, keys %mode; 195 | push @pidcmds, forkcmd(@cmd); 196 | } 197 | if (@pidcmds) { 198 | # create new summary with setup log 199 | sleep 5; 200 | setup_html(); 201 | 202 | waitcmd(@pidcmds); 203 | } 204 | } 205 | 206 | sub bsdcons_hosts { 207 | hosts_command("bsdcons.pl", @_); 208 | } 209 | 210 | sub cvsbuild_hosts { 211 | hosts_command("cvsbuild.pl", @_); 212 | } 213 | 214 | sub powerdown_hosts { 215 | hosts_command("power.pl", @_, mode => { down => 1 }); 216 | } 217 | 218 | sub powerup_hosts { 219 | hosts_command("power.pl", @_, mode => { up => 1 }); 220 | } 221 | 222 | sub reboot_hosts { 223 | hosts_command("reboot.pl", @_); 224 | } 225 | 226 | # there may be races with other running instances, make it non fatal 227 | sub setup_html { 228 | my %args = @_; 229 | my @cmd = ("$bindir/setup-html.pl"); 230 | push @cmd, '-a' if $args{all}; 231 | push @cmd, '-d', $date if $args{date}; 232 | logeval { runcmd(@cmd) }; 233 | } 234 | 235 | my @htmlpids; 236 | sub current_html { 237 | my @cmd = ("$bindir/$htmlprog-html.pl", '-d', $date, @_); 238 | push @htmlpids, forkcmd(@cmd); 239 | } 240 | 241 | sub wait_html { 242 | logeval { waitcmd(@htmlpids) }; 243 | undef @htmlpids; 244 | } 245 | 246 | 1; 247 | -------------------------------------------------------------------------------- /Kstat.pm: -------------------------------------------------------------------------------- 1 | # put common statistics parsing functions in a module 2 | 3 | # Copyright (c) 2025 Alexander Bluhm 4 | # Copyright (c) 2023 Moritz Buhl 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | package Kstat; 19 | 20 | use strict; 21 | use warnings; 22 | 23 | use parent 'Exporter'; 24 | our @EXPORT= qw( 25 | kstat_diff 26 | generate_diff_kstat 27 | ); 28 | 29 | # map kstat indentation to perl hash 30 | sub parse { 31 | my ($file) = @_; 32 | my %kstat; 33 | open(my $fh, '<', $file) 34 | or die "Open '$file' for reading failed: $!"; 35 | 36 | my ($l1, $l2); 37 | while(<$fh>) { 38 | chomp; 39 | if (m{^([\w:-]+)$}) { 40 | $l1 = $1; 41 | $kstat{$l1} = {}; 42 | } elsif (m{^( +)([^:]+:) ((\d+)(?: (\w+))?|.*)$}) { 43 | $l2 = $2; 44 | $kstat{$l1}{$l2}{indent} = $1; 45 | $kstat{$l1}{$l2}{string} = $3; 46 | $kstat{$l1}{$l2}{value} = $4; 47 | $kstat{$l1}{$l2}{unit} = $5; 48 | } else { 49 | die "Cannot parse '$_'"; 50 | } 51 | } 52 | 53 | return %kstat; 54 | } 55 | 56 | # iterate over all key value pairs and print them 57 | sub myprint { 58 | my ($fh, $l1) = @_; 59 | my %res; 60 | foreach my $k1 (sort keys %$l1) { 61 | print $fh "$k1\n"; 62 | my $l2 = $l1->{$k1}; 63 | if (ref($l2) eq 'HASH') { 64 | foreach my $k2 (sort keys %$l2) { 65 | my $l3 = $l2->{$k2}; 66 | print $fh "$l3->{indent}$k2 ", 67 | defined $l3->{value} ? 68 | defined $l3->{unit} ? 69 | "$l3->{value} $l3->{unit}" : 70 | "$l3->{value}" : 71 | "$l3->{string}", 72 | "\n"; 73 | } 74 | } else { 75 | print $fh "$k1 $l2\n"; 76 | } 77 | } 78 | } 79 | 80 | # iterate over all keys and subtract values. Only save the ones greater than 0 81 | sub diff { 82 | my ($l1, $m1) = @_; 83 | my %res; 84 | foreach my $k1 (keys %$l1) { 85 | my $l2 = $l1->{$k1}; 86 | if (ref($l2) eq 'HASH') { 87 | my $m2 = $m1->{$k1}; 88 | my $r2 = $res{$k1} ||= {}; 89 | foreach my $k2 (keys %$l2) { 90 | my $l3 = $l2->{$k2}; 91 | my $m3 = $m2->{$k2}; 92 | if (defined $l3->{value}) { 93 | if ($l3->{value} != $m3->{value}) { 94 | $r2->{$k2} = $l3; 95 | $r2->{$k2}{value} = $m3->{value} - $l3->{value}; 96 | } 97 | } else { 98 | if ($l3->{string} ne $m3->{string}) { 99 | $r2->{$k2} = $l3; 100 | $r2->{$k2}{string} = "$l3->{string} -> $m3->{string}"; 101 | } 102 | } 103 | } 104 | } 105 | } 106 | return %res; 107 | } 108 | 109 | # remove empty key-hash pairs 110 | sub sweep { 111 | my ($l1) = @_; 112 | foreach my $k1 (keys %$l1) { 113 | my $l2 = $l1->{$k1}; 114 | if (ref($l2) eq 'HASH') { 115 | delete $l1->{$k1} unless keys %$l2; 116 | } 117 | } 118 | } 119 | 120 | sub kstat_diff { 121 | my ($fh, $test, $arg) = @_; 122 | 123 | my $before = "$test.stats-kstat_$arg-before.txt"; 124 | my $after = "$test.stats-kstat_$arg-after.txt"; 125 | -r $before && -r $after 126 | or return; 127 | my %bef = parse($before); 128 | my %aft = parse($after); 129 | my %dif = diff(\%bef, \%aft); 130 | # better always show the caption 131 | #sweep(\%dif); 132 | myprint($fh, \%dif); 133 | } 134 | 135 | sub generate_diff_kstat { 136 | my ($test, $arg) = @_; 137 | 138 | my $diff = "$test.stats-kstat_$arg-diff.txt"; 139 | open(my $fh, '>', $diff) 140 | or die "Open '$diff' for writing failed: $!"; 141 | kstat_diff($fh, $test, $arg); 142 | close($fh) 143 | or die "Close '$diff' after writing failed: $!"; 144 | } 145 | 146 | 1; 147 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2025 Alexander Bluhm 2 | Copyright (c) 2018-2023 Moritz Buhl 3 | 4 | Permission to use, copy, modify, and distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /Logcmd.pm: -------------------------------------------------------------------------------- 1 | # run commands and log their output into file 2 | 3 | # Copyright (c) 2016-2024 Alexander Bluhm 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | package Logcmd; 18 | 19 | use strict; 20 | use warnings; 21 | use Carp; 22 | use File::Copy; 23 | use POSIX; 24 | 25 | use parent 'Exporter'; 26 | our @EXPORT= qw(createlog relogdie logmsg logeval runcmd forkcmd waitcmd logcmd 27 | loggrep); 28 | use subs qw(logmsg); 29 | 30 | my ($fh, $file, $verbose, @diemsg); 31 | sub createlog { 32 | my %args = @_; 33 | $file = $args{file}; 34 | open($fh, '>', $file) 35 | or croak "Open '$file' for writing failed: $!" 36 | if $file; 37 | $fh->autoflush() if $fh; 38 | $verbose = $args{verbose}; 39 | $| = 1 if $verbose; 40 | 41 | $SIG{__DIE__} = sub { 42 | print $fh @_ if $fh; 43 | @diemsg = @_; 44 | die @_; 45 | }; 46 | } 47 | 48 | sub relogdie { 49 | return unless @diemsg; 50 | print $fh @diemsg if $fh; 51 | print @diemsg if $verbose; 52 | } 53 | 54 | sub logmsg { 55 | print $fh @_ if $fh; 56 | print @_ if $verbose; 57 | } 58 | 59 | sub logeval(&) { 60 | my $code = shift; 61 | local $SIG{__DIE__}; 62 | eval { &$code }; 63 | if ($@) { 64 | $@ =~ s/^([-0-9]+T[:0-9]+Z )?/${1}Warning: /; 65 | logmsg $@; 66 | } 67 | } 68 | 69 | sub runcmd { 70 | my @cmd = @_; 71 | my $now = strftime("%FT%TZ", gmtime); 72 | logmsg "$now Command '@cmd' started.\n"; 73 | system(@cmd) && $? == -1 and 74 | croak "System '@cmd' failed: $!"; 75 | $now = strftime("%FT%TZ", gmtime); 76 | $? and croak "$now Command '@cmd' failed: $?"; 77 | logmsg "$now Command '@cmd' finished.\n"; 78 | } 79 | 80 | sub forkcmd { 81 | my @cmd = @_; 82 | my $now = strftime("%FT%TZ", gmtime); 83 | logmsg "$now Command '@cmd' started.\n"; 84 | defined(my $pid = fork()) 85 | or croak "Fork '@cmd' failed: $!"; 86 | if ($pid == 0) { 87 | undef $SIG{__DIE__}; 88 | open(STDIN, '<', "/dev/null") 89 | or carp "Redirect stdin to /dev/null failed: $!"; 90 | setsid() 91 | or carp "Setsid $$ failed: $!"; 92 | { 93 | no warnings 'exec'; 94 | exec(@cmd); 95 | carp "Exec '@cmd' failed: $!"; 96 | } 97 | _exit(126); 98 | } 99 | return ($pid => [@cmd]); 100 | } 101 | 102 | my %waitstatus; 103 | sub waitcmd { 104 | my %pidcmds = @_; 105 | my $total = keys %pidcmds; 106 | my $failed = 0; 107 | my $now = strftime("%FT%TZ", gmtime); 108 | while (my $pid = each %waitstatus) { 109 | my $cmd = delete $pidcmds{$pid} 110 | or next; 111 | # someone else has waited for our process 112 | my $status = delete $waitstatus{$pid}; 113 | my @cmd = @$cmd; 114 | if ($status) { 115 | logeval { croak "$now Command '@cmd' failed: $status" }; 116 | $failed++; 117 | } else { 118 | logmsg "$now Command '@cmd' finished.\n"; 119 | } 120 | } 121 | while (keys %pidcmds) { 122 | (my $pid = wait()) == -1 123 | and croak "Wait failed: $!"; 124 | my $status = $?; 125 | my $cmd = delete $pidcmds{$pid}; 126 | unless ($cmd) { 127 | # we have waited for someone else's process 128 | $waitstatus{$pid} = $status; 129 | next; 130 | } 131 | my @cmd = @$cmd; 132 | $now = strftime("%FT%TZ", gmtime); 133 | if ($status) { 134 | logeval { croak "$now Command '@cmd' failed: $status" }; 135 | $failed++; 136 | } else { 137 | logmsg "$now Command '@cmd' finished.\n"; 138 | } 139 | } 140 | if ($failed) { 141 | $now = strftime("%FT%TZ", gmtime); 142 | croak "$now Commands $failed out of $total failed."; 143 | } 144 | } 145 | 146 | sub logcmd { 147 | my (@cmd, $infile, $outfile); 148 | if (ref($_[0])) { 149 | my %args = %{$_[0]}; 150 | @cmd = ref($args{cmd}) ? @{$args{cmd}} : $args{cmd}; 151 | $infile = $args{infile}; 152 | $outfile = $args{outfile}; 153 | } else { 154 | @cmd = @_; 155 | } 156 | my $now = strftime("%FT%TZ", gmtime); 157 | logmsg "$now Command '@cmd' started.\n"; 158 | open(my $fh, '>', $outfile) 159 | or croak "Open file '$outfile' for writing failed: $!" 160 | if $outfile; 161 | logmsg "Writing output to '$outfile'.\n" if $outfile; 162 | defined(my $outpid = open(my $out, '-|')) 163 | or croak "Open pipe from '@cmd' failed: $!"; 164 | if ($outpid == 0) { 165 | $SIG{__DIE__} = 'DEFAULT'; 166 | close($out); 167 | open(STDIN, '<', "/dev/null") 168 | or carp "Redirect stdin to /dev/null failed: $!"; 169 | open(STDERR, '>&', \*STDOUT) 170 | or carp "Redirect stderr to stdout failed: $!"; 171 | open(STDOUT, '>&', $fh) 172 | or carp "Redirect stdout to file failed: $!" 173 | if $outfile; 174 | setsid() 175 | or carp "Setsid $$ failed: $!"; 176 | if ($infile) { 177 | defined(my $inpid = open(my $in, '|-')) 178 | or croak "Open pipe to '@cmd' failed: $!"; 179 | if ($inpid == 0) { 180 | close($in); 181 | { 182 | no warnings 'exec'; 183 | exec(@cmd); 184 | carp "Exec '@cmd' failed: $!"; 185 | } 186 | _exit(126); 187 | } 188 | copy($infile, $in) 189 | or die "Copy '$infile' to '@cmd' failed: $!"; 190 | $now = strftime("%FT%TZ", gmtime); 191 | close($in) or croak $! ? 192 | "Close pipe to '@cmd' failed: $!" : 193 | "$now Command '@cmd' failed: $?"; 194 | _exit(0); 195 | } else { 196 | no warnings 'exec'; 197 | exec(@cmd); 198 | carp "Exec '@cmd' failed: $!"; 199 | } 200 | _exit(126); 201 | } 202 | close($fh) if $outfile; 203 | local $_; 204 | while (<$out>) { 205 | s/[^\s[:print:]]/_/g; 206 | logmsg $_; 207 | } 208 | $now = strftime("%FT%TZ", gmtime); 209 | close($out) or croak $! ? 210 | "Close pipe from '@cmd' failed: $!" : 211 | "$now Command '@cmd' failed: $?"; 212 | logmsg "$now Command '@cmd' finished.\n"; 213 | } 214 | 215 | sub loggrep { 216 | my ($regex) = @_; 217 | open(my $fh, '<', $file) 218 | or croak "Open '$file' for reading failed: $!"; 219 | my @match = grep { /$regex/ } <$fh>; 220 | close($fh); 221 | return wantarray ? @match : $match[0]; 222 | } 223 | 224 | 1; 225 | -------------------------------------------------------------------------------- /Netstat.pm: -------------------------------------------------------------------------------- 1 | # put common statistics parsing functions in a module 2 | 3 | # Copyright (c) 2025 Alexander Bluhm 4 | # Copyright (c) 2023 Moritz Buhl 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | package Netstat; 19 | 20 | use strict; 21 | use warnings; 22 | 23 | use parent 'Exporter'; 24 | our @EXPORT= qw( 25 | netstat_diff 26 | generate_diff_netstat 27 | ); 28 | 29 | # netstat output might use plural for some nouns 30 | # always use the plural form of these words. 31 | my @plurales = qw(miss); 32 | my @pluralys = qw(entr); 33 | my @plurals = qw(ACK Interface SYN TDB accept ack agreement allocation 34 | association attempt authentication byte calculation call change 35 | checksum cleanup collision connection datagram decapsulation 36 | decryption destination drop duplicate episode error failure field 37 | flow fragment frame gap gateway global insert jump llx local 38 | lookup mbuf message mismatche node notification option overflow 39 | packet prediction probe quer redirect replay report request 40 | response rexmit route scan seed segment slide state table 41 | timeout transition upcall use); 42 | my $regex_es = join('|', @plurales); 43 | my $regex_ys = join('|', @pluralys); 44 | my $regex_s = join('|', @plurals); 45 | 46 | sub canonicalize_key { 47 | local $_ = shift; 48 | chomp; 49 | s/\b(?<=$regex_es)\b/es/; 50 | s/\b(?<=$regex_ys)\b/ies/; 51 | s/\b(?<=$regex_s)\b/s/; 52 | return $_; 53 | } 54 | 55 | # map netstat indentation to perl hash some nestat -s lines increase the 56 | # indentation and at the same time have a value. Write that value to the 57 | # "total" field. 58 | sub parse_s { 59 | my ($file) = @_; 60 | my %netstat; 61 | open(my $fh, '<', $file) 62 | or die "Open '$file' for reading failed: $!"; 63 | 64 | my ($l1, $l2, $l3); 65 | while(<$fh>) { 66 | chomp; 67 | if (m{^(\w+):$}) { 68 | $l1 = canonicalize_key $1; 69 | $netstat{$l1} = {} 70 | } elsif (m{^\t\t\t([^:\t]+): (\d+)$}) { 71 | my $k = canonicalize_key($1); 72 | my $n3 = $netstat{$l1}{$l2}{$l3}; 73 | if (ref($n3) ne 'HASH') { 74 | $n3 = $netstat{$l1}{$l2}{$l3} = { total => $n3 }; 75 | } 76 | $n3->{$k} = $2; 77 | } elsif (m{^\t\t(\d+) (.+)$}) { 78 | $l3 = canonicalize_key $2; 79 | my $v = $1; 80 | my $n2 = $netstat{$l1}{$l2}; 81 | if (ref($n2) ne 'HASH') { 82 | $n2 = $netstat{$l1}{$l2} = { total => $n2 }; 83 | } 84 | if ($l3 =~ m{\((.+)\)} && $1 =~ /\d/) { 85 | my ($l) = $l3 =~ /\((.+)\)/; 86 | $l3 =~ s/ \(.+\)//; 87 | (my $k2 = "$l3 $l") =~ s/\d+ //; 88 | $k2 = canonicalize_key $k2; 89 | my ($v2) = $l =~ /(\d+)/; 90 | $n2->{$k2} = $v2; 91 | } 92 | $n2->{$l3} = $v; 93 | } elsif (m{^\t\t([^:]+): (\d+)$}) { 94 | $l3 = canonicalize_key $1; 95 | $netstat{$l1}{$l2}{$l3} = $2; 96 | } elsif (m{^\t(\d+) (.+)$}) { 97 | my $v = $1; 98 | $l2 = canonicalize_key $2; 99 | if ($l2 =~ m{\((.+)\)} && $1 =~ /\d/) { 100 | my ($l) = $l2 =~ /\((.+)\)/; 101 | $l2 =~ s/ \(.+\)//; 102 | (my $k2 = "$l2 $l") =~ s/\d+ //; 103 | $k2 = canonicalize_key $k2; 104 | my ($v2) = $l =~ /(\d+)/; 105 | $netstat{$l1}{$k2} = $v2; 106 | } 107 | $netstat{$l1}{$l2} = $v; 108 | } elsif (m{^\t([^:]+):?$}) { 109 | $l2 = canonicalize_key $1; 110 | $netstat{$l1}{$l2} = {}; 111 | } else { 112 | die "Cannot parse '$_'"; 113 | } 114 | } 115 | 116 | return %netstat; 117 | } 118 | 119 | sub parse_m { 120 | my ($file) = @_; 121 | my %netstat; 122 | open(my $fh, '<', $file) 123 | or die "Open '$file' for reading failed: $!"; 124 | 125 | my ($l1, $l2, $l3) = "memory"; 126 | my $n1 = $netstat{$l1} ||= {}; 127 | while(<$fh>) { 128 | if (m{^(\d+) mbufs? (in use):}) { 129 | $l2 = "mbuf $2"; 130 | $n1->{$l2} = $1; 131 | $l2 = "mbuf types"; 132 | } elsif (m{^\t(\d+) mbufs? (allocated to .+)}) { 133 | $l3 = "mbuf $2"; 134 | $n1->{$l2}{$l3} = $1; 135 | } elsif (m{^(\d+)/\d+ (mbuf \d+ byte clusters in use)}) { 136 | $l2 = "mbuf cluster in use"; 137 | $l3 = $2; 138 | $n1->{$l2}{$l3} = $1; 139 | } elsif (m{^(\d+)/\d+/\d+ (Kbytes allocated to network)}) { 140 | $l2 = $2; 141 | $n1->{$l2} = $1; 142 | } elsif (m{^(\d+) (\w[\w ]+)$}) { 143 | $l2 = "counter"; 144 | $l3 = $2; 145 | $n1->{$l2}{$l3} = $1; 146 | } 147 | } 148 | 149 | return %netstat; 150 | } 151 | 152 | # iterate over all key value pairs and print them 153 | sub myprint { 154 | my ($fh, $l1) = @_; 155 | my %res; 156 | foreach my $k1 (sort keys %$l1) { 157 | print $fh "$k1:\n"; 158 | my $l2 = $l1->{$k1}; 159 | if (ref($l2) eq 'HASH') { 160 | foreach my $k2 (sort keys %$l2) { 161 | my $l3 = $l2->{$k2}; 162 | if (ref($l3) eq 'HASH') { 163 | print $fh "\t$k2:\n"; 164 | foreach my $k3 (sort keys %$l3) { 165 | my $l4 = $l3->{$k3}; 166 | if (ref($l4) eq 'HASH') { 167 | print $fh "\t\t$k3:\n"; 168 | foreach my $k4 (sort keys %$l4) { 169 | print $fh "\t\t\t$k4: $l4->{$k4}\n"; 170 | } 171 | } else { 172 | print $fh "\t\t$k3: $l4\n"; 173 | } 174 | } 175 | } else { 176 | print $fh "\t$k2: $l3\n"; 177 | } 178 | } 179 | } else { 180 | print $fh "$k1: $l2\n"; 181 | } 182 | } 183 | } 184 | 185 | # iterate over all keys and subtract values. Only save the ones greater than 0 186 | sub diff { 187 | my ($l1, $m1) = @_; 188 | my %res; 189 | foreach my $k1 (keys %$l1) { 190 | my $l2 = $l1->{$k1}; 191 | if (ref($l2) eq 'HASH') { 192 | my $m2 = $m1->{$k1}; 193 | my $r2 = $res{$k1} ||= {}; 194 | foreach my $k2 (keys %$l2) { 195 | my $l3 = $l2->{$k2}; 196 | if (ref($l3) eq 'HASH') { 197 | my $m3 = $m2->{$k2}; 198 | my $r3 = $r2->{$k2} ||= {}; 199 | foreach my $k3 (keys %$l3) { 200 | my $l4 = $l3->{$k3}; 201 | if (ref($l4) eq 'HASH') { 202 | my $m4 = $m3->{$k3}; 203 | my $r4 = $r3->{$k3} ||= {}; 204 | foreach my $k4 (keys %$l4) { 205 | my $v = $m4->{$k4} - $l4->{$k4}; 206 | $r4->{$k4} = $v if ($v != 0); 207 | } 208 | } else { 209 | my $v = $m3->{$k3} - $l3->{$k3}; 210 | $r3->{$k3} = $v if ($v != 0); 211 | } 212 | } 213 | } else { 214 | my $v = $m2->{$k2} - $l2->{$k2}; 215 | $r2->{$k2} = $v if ($v != 0); 216 | } 217 | } 218 | } else { 219 | my $v = $m1->{$k1} - $l1->{$k1}; 220 | $res{$k1} = $v if ($v != 0); 221 | } 222 | } 223 | return %res; 224 | } 225 | 226 | # remove empty key-hash pairs 227 | sub sweep { 228 | my ($l1) = @_; 229 | foreach my $k1 (keys %$l1) { 230 | my $l2 = $l1->{$k1}; 231 | if (ref($l2) eq 'SCALAR') { 232 | delete $l1->{$k1} if ($l2 == 0); 233 | } elsif (ref($l2) eq 'HASH') { 234 | foreach my $k2 (keys %$l2) { 235 | my $l3 = $l2->{$k2}; 236 | if (ref($l3) eq 'SCALAR') { 237 | delete $l2->{$k2} if ($l3 == 0); 238 | } elsif (ref($l3) eq 'HASH') { 239 | foreach my $k3 (keys %$l3) { 240 | my $l4 = $l3->{$k3}; 241 | if (ref($l4) eq 'SCALAR') { 242 | delete $l3->{$k3} if ($l4 == 0); 243 | } elsif (ref($l4) eq 'HASH') { 244 | foreach my $k4 (keys %$l4) { 245 | my $l5 = $l4->{$k4}; 246 | delete $l4->{$k4} if ($l5 == 0); 247 | } 248 | delete $l3->{$k3} if (scalar (keys %$l4) == 0); 249 | } 250 | } 251 | delete $l2->{$k2} if (scalar (keys %$l3) == 0); 252 | } 253 | } 254 | } 255 | delete $l1->{$k1} if (scalar (keys %$l2) == 0); 256 | } 257 | } 258 | 259 | sub netstat_diff { 260 | my ($fh, $test, $arg) = @_; 261 | 262 | my $before = "$test.stats-netstat_$arg-before.txt"; 263 | my $after = "$test.stats-netstat_$arg-after.txt"; 264 | -r $before && -r $after 265 | or return; 266 | my $parser; 267 | $parser = \&parse_m if $arg eq '-m'; 268 | $parser = \&parse_s if $arg eq '-s'; 269 | my %bef = $parser->($before); 270 | my %aft = $parser->($after); 271 | my %dif = diff(\%bef, \%aft); 272 | sweep(\%dif); 273 | myprint($fh, \%dif); 274 | } 275 | 276 | sub generate_diff_netstat { 277 | my ($test) = @_; 278 | 279 | my $diff = "$test.stats-netstat-diff.txt"; 280 | open(my $fh, '>', $diff) 281 | or die "Open '$diff' for writing failed: $!"; 282 | foreach my $opt ('-m', '-s') { 283 | netstat_diff($fh, $test, $opt); 284 | } 285 | close($fh) 286 | or die "Close '$diff' after writing failed: $!"; 287 | } 288 | 289 | 1; 290 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Run a bunch of OpenBSD regression tests in a row. The intention 2 | is to have a reliable set of tests and run them on a regular basis. 3 | The result summary is written to a file, log output of each test 4 | is available. 5 | 6 | A second purpose is to run OpenBSD performance tests. A certain 7 | cvs checkout corresponding to a date is created. The build environment 8 | is based on the previous release and adapted with commands from 9 | current.html. This is mostly updating the build tools to compile 10 | a kernel from that cvs checkout date. The results are grouped by 11 | run date, cvs checkout date, and repetitions. The tests are run 12 | multiple times to detect deviations. Tests consist of iperf3, 13 | tcpbench, and kernel compile time. 14 | 15 | Additional features are running ports tests, building release, and 16 | testing network interfaces in multiple configurations. 17 | 18 | Buildquirks.pm - create tool chain to compile kernel from certain date 19 | Hostctl.pm - run commands on all tests hosts to configure them 20 | Html.pm - utility functions to create html pages with results 21 | Logcmd.pm - common log functions for run.pl, setp.pl, and setup.pl 22 | Machine.pm - functions to setup a single machine 23 | Netstat.pm - parse netstat statistics and show counter differences 24 | Testvars.pm - variables with test names for perform and netlink 25 | bsdcons.pl - collect kernel output from console of selected machine 26 | build-ot14.list - setup builds special tools needed on test machine ot14 27 | cleanup.pl - remove old test logs to recover disk space 28 | cmd-ot1.list - setup executes commands after installation of ot1 29 | cvsbuild.pl - checkout kernel at certain cvs date and install it 30 | cvslog.pl - collect all cvs commit messages between two dates 31 | env-ot1.sh - environment variables to be set on the test machine ot1 32 | favicon.ink.svg - favicon for bluhm.genua.de created with inkscape 33 | favicon.svg - favicon converted to small SVG 34 | force-ssh.pl - restrict ssh commands on linux perform servers 35 | gnuplot.pl - generate gnuplot graphics for perform html 36 | keys.sh - generate gnuplot icons for legend in html graphics 37 | this is started by gnuplot.pl 38 | mktestlist.pl - find possible names of tests in regress directory 39 | make.pl - run make build and release 40 | makealign.sh - align object files of kernel on perform machine 41 | mktestlist.pl - print the Makefile leaves of the regress directory 42 | net.pl - run network regression tests 43 | netlink-html.pl - convert netlink test results into html table 44 | netlink.pl - set up and run one network regression test on test machine 45 | this is started by net.pl 46 | once.pl - run performance test once, used for manual testing 47 | perform-html.pl - convert performance test results into html table 48 | perform.pl - run one set up performance test on test machine, 49 | this is started by step.pl or once.pl 50 | pkg-ot1.list - setup installs packages on test machine ot1 51 | plot.gp - gnuplot script used by gnuplot.pl 52 | ports.list - list of /usr/ports subdirectories that should be tested 53 | portstest.pl - run port test for set of ports on test machine 54 | this is started by test.pl 55 | power.pl - power up and down machine to save cooling power 56 | reboot.pl - reboot machine, after optionally reordering kernel 57 | regress-html.pl - convert all regression test results into html table 58 | regress.pl - run one openbsd regression test on test machine, 59 | this is started by run.pl 60 | release.pl - build release from /usr/src 61 | this is started by make.pl 62 | run.pl - do regression tests, add this to cron job 63 | running-html.pl - create html table with all tests currently running 64 | setup-html.pl - convert machine setup logs into html table 65 | setup.pl - install one test machine, 66 | this is started by run.pl and step.pl 67 | site.list - list of config files that must be installed on test machine 68 | step.pl - do performance tests, add this to cron job 69 | test.pl - do ports tests, add this to cron job 70 | test.list - list of /usr/src/regress subdirectories that should be tested 71 | testsuite-html.pl - create html of test suites run during regress 72 | 73 | Several modes for run.pl and setup.pl exist to prepare the test machines. 74 | 75 | build - build system from source /usr/src 76 | cvs - cvs update /usr/src and make obj 77 | install - install from snapshot 78 | keep - keep existing software on machine and skip setup 79 | kernel - build kernel from source /usr/src/sys 80 | upgrade - upgrade with snapshot 81 | 82 | Daily test results are published here: 83 | http://bluhm.genua.de/regress/results/regress.html 84 | Performance timelines are published here: 85 | http://bluhm.genua.de/perform/results/perform.html 86 | 87 | Thanks to genua GmbH https://www.genua.de/ for sponsoring this work. 88 | -------------------------------------------------------------------------------- /bsdcons.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # collect kernel output from console to regress or perform dir 3 | 4 | # Copyright (c) 2018-2023 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use Date::Parse; 22 | use File::Basename; 23 | use Getopt::Std; 24 | use POSIX; 25 | 26 | use lib dirname($0); 27 | use Logcmd; 28 | use Machine; 29 | 30 | my $now = strftime("%FT%TZ", gmtime); 31 | my $scriptname = "$0 @ARGV"; 32 | 33 | my %opts; 34 | getopts('d:D:h:lm:P:R:r:v', \%opts) or do { 35 | print STDERR <<"EOF"; 36 | usage: bsdcons.pl [-lv] [-d date] [-D cvsdate] -h host [-m modify] [-P patch] 37 | [-R repeatdir] [-r release] 38 | -d date set date string and change to sub directory, may be current 39 | -D cvsdate update sources from cvs to this date 40 | -h host root\@openbsd-test-machine, login per ssh 41 | -l update bsdcons in latest directory with this host 42 | -m modify modify mode 43 | -P patch patch name 44 | -R repdir repetition number or btrace 45 | -r release change to release sub directory 46 | -v verbose 47 | EOF 48 | exit(2); 49 | }; 50 | $opts{h} or die "No -h specified"; 51 | !$opts{d} || $opts{d} eq "current" || str2time($opts{d}) 52 | or die "Invalid -d date '$opts{d}'"; 53 | my $date = $opts{d}; 54 | !$opts{D} || str2time($opts{D}) 55 | or die "Invalid -D cvsdate '$opts{D}'"; 56 | my $cvsdate = $opts{D}; 57 | my $patch = $opts{P}; 58 | my $modify = $opts{m}; 59 | !$opts{R} || $opts{R} =~ /^\d{3}$/ 60 | or die "Invalid -R repeatdir '$opts{R}'"; 61 | my $repeatdir = $opts{R}; 62 | my $release; 63 | if ($opts{r} && $opts{r} ne "current") { 64 | ($release = $opts{r}) =~ /^\d+\.\d$/ 65 | or die "Release '$opts{r}' must be major.minor format"; 66 | } 67 | $opts{d} && $opts{l} 68 | and die "Use either specific date or latest date"; 69 | @ARGV and die "No arguments allowed"; 70 | 71 | my $testdir = dirname($0). "/.."; 72 | chdir($testdir) 73 | or die "Change directory to '$testdir' failed: $!"; 74 | $testdir = getcwd(); 75 | my $resultdir = "$testdir/results"; 76 | if ($date && $date eq "current") { 77 | my $current = readlink("$resultdir/$date") 78 | or die "Read link '$resultdir/$date' failed: $!"; 79 | -d "$resultdir/$current" 80 | or die "Test directory '$resultdir/$current' failed: $!"; 81 | $date = $current; 82 | } 83 | chdir($resultdir) 84 | or die "Change directory to '$resultdir' failed: $!"; 85 | 86 | my ($user, $host) = split('@', $opts{h}, 2); 87 | ($user, $host) = ("root", $user) unless $host; 88 | 89 | createlog(verbose => $opts{v}); 90 | logmsg("$now Script '$scriptname' started.\n"); 91 | 92 | if ($opts{l}) { 93 | my @bsdcons = sort glob("*T*/bsdcons-$host.txt") 94 | or die "No latest 'bsdcons-$host.txt' in date directories"; 95 | logmsg("Update latest '$bsdcons[-1]' file.\n"); 96 | $date = dirname($bsdcons[-1]); 97 | } 98 | 99 | $resultdir .= "/$release" if $release; 100 | $resultdir .= "/$date" if $date; 101 | $resultdir .= "/$cvsdate" if $date && $cvsdate; 102 | if ($patch) { 103 | my $patchdir = "patch-". 104 | join(',', map { s,\.[^/]*,,; basename($_) } split(/,/, $patch)); 105 | my $dir = "$resultdir/$patchdir.[0-9]"; 106 | $resultdir = (glob($dir))[-1] 107 | or die "Patch directory '$dir' not found"; 108 | } 109 | if ($modify) { 110 | my $dir = "$resultdir/modify-$modify.[0-9]"; 111 | $resultdir = (glob($dir))[-1] 112 | or die "Modify directory '$dir' not found"; 113 | } 114 | $resultdir .= "/$repeatdir" if $repeatdir; 115 | chdir($resultdir) 116 | or die "Change directory to '$resultdir' failed: $!"; 117 | logmsg("Result directory is '$resultdir'.\n"); 118 | 119 | createhost($user, $host); 120 | 121 | # execute commands 122 | 123 | get_bsdcons(); 124 | 125 | $now = strftime("%FT%TZ", gmtime); 126 | logmsg("$now Script '$scriptname' finished.\n"); 127 | -------------------------------------------------------------------------------- /build-ot14.list: -------------------------------------------------------------------------------- 1 | splicebench 2 | udpbench 3 | -------------------------------------------------------------------------------- /build-ot15.list: -------------------------------------------------------------------------------- 1 | splicebench 2 | udpbench 3 | -------------------------------------------------------------------------------- /cleanup.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # remove directories with old results 3 | 4 | # Copyright (c) 2018-2020 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use File::Basename; 22 | use File::Path qw(remove_tree); 23 | use Getopt::Std; 24 | use POSIX; 25 | 26 | my $now = strftime("%FT%TZ", gmtime); 27 | 28 | my $scriptname = "$0 @ARGV"; 29 | 30 | my %opts; 31 | getopts('d:m:nvw:y:', \%opts) or do { 32 | print STDERR <<"EOF"; 33 | usage: cleanup.pl [-nv] [-d days] [-m months] [-w weeks] [-y years] 34 | -d days remove log and obj tgz older than days, default 3 35 | -m months thin out directories older than months, default 1 36 | -n do not clean, just display obsolete directories 37 | -v verbose 38 | -w weeks remove setup and run log older than weeks, default 4 39 | -y years remove all directories older than years, default 1 40 | EOF 41 | exit(2); 42 | }; 43 | my $dy = 365.25; 44 | my $dm = $dy/12; 45 | my $dw = 7; 46 | my $alldays = ($opts{y} // 1) * $dy; 47 | my $thindays = ($opts{m} // 1) * $dm; 48 | my $logdays = ($opts{w} // 4) * $dw; 49 | my $tgzdays = ($opts{d} // 3); 50 | @ARGV and die "No arguments allowed"; 51 | 52 | my ($year, $month, $day) = $now =~ /^(\d+)-(\d+)-(\d+)T/ 53 | or die "Bad date: $now"; 54 | 55 | my $dir = dirname($0). "/.."; 56 | chdir($dir) 57 | or die "Change directory to '$dir' failed: $!"; 58 | my $regressdir = getcwd(); 59 | $dir = "results"; 60 | chdir($dir) 61 | or die "Change directory to '$dir' failed: $!"; 62 | 63 | my @datedirs = glob('20[0-9][0-9]-[01][0-9]-[0-3][0-9]T*Z'); 64 | 65 | foreach my $date (reverse sort @datedirs) { 66 | my ($y, $m, $d) = $date =~ /^(\d+)-(\d+)-(\d+)T/ 67 | or die "Bad date directory name: $date"; 68 | my $age = ($year*$dy + $month*$dm + $day) - ($y*$dy + $m*$dm + $d); 69 | 70 | if ($age > $alldays or ($age > $thindays && $d !~ /5$/)) { 71 | print "remove $date\n" if $opts{v}; 72 | remove_tree($date, { safe => 1 }) unless $opts{n}; 73 | next; 74 | } 75 | my @cleanfiles; 76 | if ($age > $tgzdays) { 77 | push @cleanfiles, glob("$date/test.*.tgz"); 78 | } 79 | if ($age > $logdays) { 80 | push @cleanfiles, glob("$date/*.log"); 81 | } 82 | if (@cleanfiles) { 83 | print "clean $date\n" if $opts{v}; 84 | unlink(@cleanfiles) or die "Unlink '@cleanfiles' failed: $!" 85 | unless $opts{n}; 86 | next; 87 | } 88 | print "skip $date\n" if $opts{v}; 89 | } 90 | -------------------------------------------------------------------------------- /cmd-ot1.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot10.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot11.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot17.list: -------------------------------------------------------------------------------- 1 | -groupadd -g 999 vmm 2 | -useradd -G vmm -u 1000 ot60 3 | -useradd -G vmm -u 1001 lt61 4 | -useradd -G vmm -u 1002 ot62 5 | -useradd -G vmm -u 1003 lt63 6 | -useradd -G vmm -u 1004 ot64 7 | cd /dev && sh ./MAKEDEV `jot 10 0 | sed s/^/tap/` 8 | -------------------------------------------------------------------------------- /cmd-ot19.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot2.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot21.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot25.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | rm -f /var/db/kernel.SHA256 3 | -------------------------------------------------------------------------------- /cmd-ot26.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot27.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot33.list: -------------------------------------------------------------------------------- 1 | [ -e /home/user/disk.img ] || dd if=/dev/null of=/home/user/disk.img bs=1G seek=10 count=0 2 | -------------------------------------------------------------------------------- /cmd-ot41.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot42.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot48.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | rm -f /var/db/kernel.SHA256 3 | -------------------------------------------------------------------------------- /cmd-ot5.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot52.list: -------------------------------------------------------------------------------- 1 | -groupadd -g 999 vmm 2 | -useradd -G vmm -m lt70 3 | -useradd -G vmm -m lt75 4 | -useradd -G vmm -m ot71 5 | -useradd -G vmm -m ot72 6 | -useradd -G vmm -m ot73 7 | -useradd -G vmm -m ot74 8 | cd /dev && sh ./MAKEDEV `jot 16 0 | sed s/^/tap/` 9 | -------------------------------------------------------------------------------- /cmd-ot57.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | rm -f /var/db/kernel.SHA256 3 | -------------------------------------------------------------------------------- /cmd-ot6.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot62.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot7.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot71.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot72.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot73.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot74.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot8.list: -------------------------------------------------------------------------------- 1 | -useradd -m ftp 2 | -------------------------------------------------------------------------------- /cmd-ot81.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot91.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot92.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot93.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cmd-ot94.list: -------------------------------------------------------------------------------- 1 | rm -f /var/db/kernel.SHA256 2 | -------------------------------------------------------------------------------- /cvsbuild.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # recompile parts of machine for performance comparison 3 | 4 | # Copyright (c) 2018-2023 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use Date::Parse; 22 | use File::Basename; 23 | use Getopt::Std; 24 | use POSIX; 25 | 26 | use lib dirname($0); 27 | use Logcmd; 28 | use Machine; 29 | use Buildquirks; 30 | 31 | my $now = strftime("%FT%TZ", gmtime); 32 | my $scriptname = "$0 @ARGV"; 33 | 34 | my @allkernelmodes = qw(align gap sort reorder reboot); 35 | 36 | my %opts; 37 | getopts('d:D:h:m:P:r:v', \%opts) or do { 38 | print STDERR <<"EOF"; 39 | usage: cvsbuild.pl [-v] [-d date] [-D cvsdate] -h host [-m modify] [-P patch] 40 | [-r release] [kernel ...] 41 | -d date set date string and change to sub directory 42 | -D cvsdate update sources from cvs to this date 43 | -h host root\@openbsd-test-machine, login per ssh 44 | -m modify modify mode 45 | -P patch apply patch to clean kernel source, comma separated list 46 | -r release change to release sub directory 47 | -v verbose 48 | kernel ... kernel mode: @allkernelmodes 49 | align relink kernel aligning all object at page size, no randomness 50 | gap relink kernel sorting object files, but use random gap 51 | sort relink kernel sorting object files at fixed position 52 | reorder relink kernel using the reorder kernel script 53 | reboot reboot, this is always done 54 | EOF 55 | exit(2); 56 | }; 57 | $opts{h} or die "No -h specified"; 58 | !$opts{d} || $opts{d} eq "current" || str2time($opts{d}) 59 | or die "Invalid -d date '$opts{d}'"; 60 | my $date = $opts{d}; 61 | !$opts{D} || str2time($opts{D}) 62 | or die "Invalid -D cvsdate '$opts{D}'"; 63 | my $cvsdate = $opts{D}; 64 | my $patch = $opts{P}; 65 | my $modify = $opts{m}; 66 | my $release; 67 | if ($opts{r} && $opts{r} ne "current") { 68 | ($release = $opts{r}) =~ /^\d+\.\d$/ 69 | or die "Release '$opts{r}' must be major.minor format"; 70 | } 71 | 72 | my %kernelmode; 73 | foreach my $mode (@ARGV) { 74 | grep { $_ eq $mode } @allkernelmodes 75 | or die "Unknown kernel mode '$mode'"; 76 | $kernelmode{$mode} = 1; 77 | } 78 | 79 | my $performdir = dirname($0). "/.."; 80 | chdir($performdir) 81 | or die "Change directory to '$performdir' failed: $!"; 82 | $performdir = getcwd(); 83 | my $resultdir = "$performdir/results"; 84 | $resultdir .= "/$release" if $release; 85 | if ($date && $date eq "current") { 86 | my $current = readlink("$resultdir/$date") 87 | or die "Read link '$resultdir/$date' failed: $!"; 88 | -d "$resultdir/$current" 89 | or die "Test directory '$resultdir/$current' failed: $!"; 90 | $date = $current; 91 | } 92 | $resultdir .= "/$date" if $date; 93 | $resultdir .= "/$cvsdate" if $date && $cvsdate; 94 | if ($patch) { 95 | my $patchdir = "patch-". 96 | join(',', map { s,\.[^/]*,,; basename($_) } split(/,/, $patch)); 97 | my $dir = "$resultdir/$patchdir.[0-9]"; 98 | $resultdir = (glob($dir))[-1] 99 | or die "Patch directory '$dir' not found"; 100 | } 101 | if ($modify) { 102 | my $dir = "$resultdir/modify-$modify.[0-9]"; 103 | $resultdir = (glob($dir))[-1] 104 | or die "Modify directory '$dir' not found"; 105 | } 106 | chdir($resultdir) 107 | or die "Change directory to '$resultdir' failed: $!"; 108 | 109 | my ($user, $host) = split('@', $opts{h}, 2); 110 | ($user, $host) = ("root", $user) unless $host; 111 | 112 | createlog(file => "cvsbuild-$host.log", verbose => $opts{v}); 113 | logmsg("$now Script '$scriptname' started.\n"); 114 | 115 | createhost($user, $host); 116 | 117 | my %sysctl = get_version(); 118 | my ($before, $clean); 119 | if ($sysctl{'kern.version'} =~ 120 | /#cvs : D(\d{4}).(\d\d).(\d\d).(\d\d).(\d\d).(\d\d):/) { 121 | # date format is from CVS/Tag 122 | # OpenBSD 7.3-current (GENERIC.MP) #cvs : D2023.07.18.00.00.00: \ 123 | # Wed Jul 19 11:28:11 CEST 2023 124 | $before = "$1-$2-${3}T$4:$5:${6}Z"; 125 | } elsif ($sysctl{'kern.version'} =~ 126 | /: (\w{3} \w{3} ?\d?\d \d\d:\d\d:\d\d \w+ \d{4})\n/) { 127 | # date format is from snapshot 128 | # OpenBSD 7.3-current (GENERIC.MP) #1314: Tue Jul 25 17:02:17 MDT 2023 129 | $before = $1; 130 | $clean = "C"; 131 | } 132 | if ($before && $cvsdate) { 133 | my %q = quirks($before, $cvsdate); 134 | if (keys %q) { 135 | open(my $fh, '>', "quirks-$host.txt") 136 | or die "Open 'quirks-$host.txt' for writing failed: $!"; 137 | print $fh map { "$q{$_}{date} $q{$_}{comment}\n" } sort keys %q; 138 | } 139 | foreach my $cmd (quirk_commands($before, $cvsdate, \%sysctl)) { 140 | if ($cmd eq "reboot") { 141 | reboot(); 142 | } else { 143 | logcmd('ssh', "$user\@$host", $cmd); 144 | } 145 | } 146 | } 147 | 148 | $clean = "C" if $patch; 149 | update_cvs(undef, $cvsdate, "sys", $clean) if $cvsdate; 150 | if ($patch) { 151 | clean_cvs("sys") unless $cvsdate; 152 | patch_cvs($_, "sys") foreach split(/,/, $patch); 153 | } 154 | make_kernel(); 155 | if ($kernelmode{align}) { 156 | align_kernel(); 157 | } elsif ($kernelmode{gap}) { 158 | gap_kernel(); 159 | } elsif ($kernelmode{sort}) { 160 | sort_kernel(); 161 | } 162 | reorder_kernel() if $kernelmode{align} || $kernelmode{gap} || 163 | $kernelmode{sort} || $kernelmode{reorder}; 164 | get_bsdnm(); 165 | diff_cvs("sys") if $patch; 166 | reboot(); 167 | get_version(); 168 | 169 | # finish build log 170 | 171 | $now = strftime("%FT%TZ", gmtime); 172 | logmsg("$now Script '$scriptname' finished.\n"); 173 | -------------------------------------------------------------------------------- /cvslog.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # collect cvs logs between certain dates for sub branches 3 | 4 | # Copyright (c) 2018-2020 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use Date::Parse; 22 | use File::Basename; 23 | use File::Path qw(make_path); 24 | use Getopt::Std; 25 | use HTML::Entities; 26 | use POSIX; 27 | use Time::Local; 28 | use URI::Escape; 29 | 30 | use lib dirname($0); 31 | 32 | my $now = strftime("%FT%TZ", gmtime); 33 | my $scriptname = "$0 @ARGV"; 34 | 35 | my %opts; 36 | getopts('B:E:P:v', \%opts) or do { 37 | print STDERR <<"EOF"; 38 | usage: cvslog.pl [-v] -B date [-E date] -P cvspath 39 | -v verbose 40 | -B date begin date, exclusive 41 | -E date end date, inclusive 42 | -P cvspath module and path with cvs files 43 | EOF 44 | exit(2); 45 | }; 46 | my $verbose = $opts{v}; 47 | $opts{B} or die "No -B begin date"; 48 | my ($begin, $end); 49 | $begin = str2time($opts{B}) 50 | or die "Invalid -B date '$opts{B}'"; 51 | $end = str2time($opts{E} || $opts{B}) 52 | or die "Invalid -E date '$opts{E}'"; 53 | $begin <= $end 54 | or die "Begin date '$opts{B}' before end date '$opts{E}'"; 55 | $opts{P} or die "No -P cvs path"; 56 | my ($module, $path) = split("/", $opts{P}, 2); 57 | $module && $path 58 | or die "Path '$opts{P}' must consist of cvs module / path"; 59 | @ARGV and die "No arguments allowed"; 60 | 61 | # better get an errno than random kill by SIGPIPE 62 | $SIG{PIPE} = 'IGNORE'; 63 | 64 | my $performdir = dirname($0). "/.."; 65 | chdir($performdir) 66 | or die "Change directory to '$performdir' failed: $!"; 67 | $performdir = getcwd(); 68 | 69 | # collect cvs log data 70 | 71 | -f "/usr/$module/CVS/Root" 72 | or die "No cvs root at /usr/$module, do a checkout"; 73 | chdir("/usr/$module") 74 | or die "Change directory to '/usr/$module' failed: $!"; 75 | 76 | my $cvsbegin = strftime("%FZ%T", gmtime($begin)); 77 | my $cvsend = strftime("%FZ%T", gmtime($end)); 78 | my $cvsdate = "-d$cvsbegin<=$cvsend"; 79 | 80 | my @cvscmd = (qw(cvs -qR rlog -b -N), $cvsdate, "$module/$path"); 81 | print "$now Pipe from command '@cvscmd' started.\n" if $verbose; 82 | open(my $cvs, '-|', @cvscmd) 83 | or die "Open pipe from '@cvscmd' failed: $!"; 84 | 85 | my $startcommit = "-" x 28; 86 | my $finishcommit = "=" x 77; 87 | 88 | my %l; 89 | my $state = "header"; 90 | my $file; 91 | my %commit; 92 | for ((local $_, my $preview) = (scalar <$cvs>, scalar <$cvs>); 93 | defined($_); 94 | ($_, $preview) = ($preview, scalar <$cvs>)) { 95 | 96 | print if $verbose; 97 | chomp; 98 | # some commit messages contain ---------------------------- 99 | # use more context to detect real commits with heuristics 100 | if (($_ eq $startcommit && $preview =~ /^revision 1\./) || 101 | $_ eq $finishcommit) { 102 | 103 | $file or die "No file before commit: $_"; 104 | if ($state eq "header") { 105 | my @keys = keys %commit; 106 | @keys 107 | and die "Unexpected keys '@keys' in log: $_"; 108 | } elsif ($state eq "message") { 109 | my ($current, $date, $commitid, $author, $revision) = 110 | @commit{qw(current date commitid author revision)}; 111 | # maybe a bug in cvs; dead commits outside of -d appear in log 112 | if ($begin < $current && $current <= $end) { 113 | my $lc = $l{$date}{$commitid} ||= {}; 114 | if ($lc->{author}) { 115 | $lc->{author} eq $author 116 | or die "Mismatch date '$date', commitid $commitid, ". 117 | "autor '$author': $_"; 118 | } else { 119 | $lc->{author} = $author, 120 | $lc->{message} = $commit{message}, 121 | } 122 | push @{$lc->{files}}, $file; 123 | push @{$lc->{revisions}}, $revision; 124 | } 125 | undef %commit; 126 | } else { 127 | die "Unexpected state '$state' at commit: $_"; 128 | } 129 | $state = "commit"; 130 | if ($_ eq $finishcommit) { 131 | $state = "header"; 132 | undef $file; 133 | } 134 | } elsif ($state eq "header") { 135 | if (/^RCS file: (\S+)/) { 136 | $file and die "Reset file '$file' in header: $_"; 137 | $file = $1; 138 | $file =~ s,.*?/(?=$module/$path/),, 139 | or die "No cvs path '/$module/$path/' in rcs file: $_"; 140 | $file =~ s/,v$// 141 | or die "No suffix ',v' in rcs file: $_"; 142 | } 143 | } elsif ($state eq "commit") { 144 | if (/^revision (\S+)/) { 145 | $commit{revision} and die 146 | "Reset revision '$commit{revision}' in file '$file': $_"; 147 | my $revision = $1; 148 | $revision =~ /^1(\.\d+)+$/ 149 | or die "Unexpected revision '$revision' in file '$file': $_"; 150 | $commit{revision} = $revision; 151 | } elsif (/^date: /) { 152 | $commit{revision} or die "No revision in file '$file': $_"; 153 | foreach my $pair (split(";")) { 154 | $pair =~ /(\w+): (.*)/ 155 | or die "No key value pair '$pair' in '$file': $_"; 156 | $commit{$1} = $2; 157 | } 158 | my $current = str2time($commit{date}, "UTC") 159 | or die "Could not parse date '$commit{date}': $_"; 160 | $commit{current} = $current; 161 | $commit{date} = strftime("%FT%TZ", gmtime($current)); 162 | $commit{message} 163 | and die "Reset message '$commit{message}' in file '$file': $_"; 164 | $commit{message} = []; 165 | $state = "message"; 166 | } else { 167 | die "Unknown commit: $_"; 168 | } 169 | } elsif ($state eq "message") { 170 | push @{$commit{message}}, $_; 171 | } else { 172 | die "Unknown state '$state': $_"; 173 | } 174 | } 175 | if ($state eq "header") { 176 | my @keys = keys %commit; 177 | @keys 178 | and die "Unexpected keys '@keys' after log"; 179 | } else { 180 | die "Unexpected state '$state' after log"; 181 | } 182 | 183 | $now = strftime("%FT%TZ", gmtime); 184 | close($cvs) or die $! ? 185 | "Close pipe from '@cvscmd' failed: $!" : 186 | "$now Command '@cvscmd' failed: $?"; 187 | print "$now Pipe from command '@cvscmd' finished.\n" if $verbose; 188 | 189 | # write result log file 190 | 191 | chdir($performdir) 192 | or die "Change directory to '$performdir' failed: $!"; 193 | my $year = 1900 + (gmtime($begin))[5]; 194 | my $cvslogdir = "results/cvslog/$year/$module/$path"; 195 | -d $cvslogdir || make_path $cvslogdir 196 | or die "Make cvslog path '$cvslogdir' failed: $!"; 197 | 198 | my $isobegin = strftime("%FT%TZ", gmtime($begin)); 199 | my $isoend = strftime("%FT%TZ", gmtime($end)); 200 | my $logfile = "$cvslogdir/$isobegin--$isoend"; 201 | 202 | open(my $fh, '>', "$logfile.txt.new") 203 | or die "Open '$logfile.txt.new' for writing failed: $!"; 204 | open(my $html, '>', "$logfile.html.new") 205 | or die "Open '$logfile.html.new' for writing failed: $!"; 206 | 207 | print $fh "BEGIN $isobegin\n"; 208 | print $fh "END $isoend\n"; 209 | print $fh "PATH $module/$path\n"; 210 | my $commitnum = keys %l; 211 | print $fh "COMMITS $commitnum\n"; 212 | 213 | $now = strftime("%FT%TZ", gmtime); 214 | print $html <<"HEADER"; 215 | 216 | 217 | 218 | 219 | OpenBSD CVS Log 220 | 225 | 226 | 227 | 228 |

OpenBSD cvs log

229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 |
created$now
begin$isobegin
end$isoend
path$module/$path
commits$commitnum
251 | HEADER 252 | 253 | my $cvsweb = "https://cvsweb.openbsd.org"; 254 | foreach my $date (sort keys %l) { 255 | while ((undef, my $commit) = each %{$l{$date}}) { 256 | print $fh "\n"; 257 | print $fh "DATE $date\n"; 258 | my $author = $commit->{author}; 259 | print $fh "AUTHOR $author\n"; 260 | my @files = @{$commit->{files}}; 261 | my @revisions = @{$commit->{revisions}}; 262 | my $filespan = @files; 263 | my $files = ""; 264 | foreach my $f (@files) { 265 | $files .= "\n \n \n" if $files; 266 | $files .= " $f\n"; 267 | my $rev = shift @revisions; 268 | my $link = "$cvsweb/$f#rev$rev"; 269 | $files .= " log\n"; 270 | (my $prev = $rev) =~ s/(?<=\.)\d+/$&-1/e; 271 | $link = "$cvsweb/$f.diff?r1=$prev&r2=$rev"; 272 | $files .= " diff\n"; 273 | $link = "$cvsweb/$f?annotate=$rev"; 274 | $files .= " annotate"; 275 | } 276 | print $fh "FILES @files\n"; 277 | my @message = @{$commit->{message}}; 278 | my $message = join("
\n\t", map { encode_entities($_) } @message); 279 | print $fh "MESSAGE @message\n"; 280 | 281 | print $html <<"TABLE"; 282 |

283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | $files 295 | 296 | 297 | 298 | 301 | 302 |
date$date
author$author
files
message 299 | $message 300 |
303 | TABLE 304 | } 305 | } 306 | 307 | print $html <<"FOOTER"; 308 | 309 | 310 | FOOTER 311 | 312 | close($fh) 313 | or die "Close '$logfile.txt.new' after writing failed: $!"; 314 | rename("$logfile.txt.new", "$logfile.txt") 315 | or die "Rename '$logfile.txt.new' to '$logfile.txt' failed: $!"; 316 | close($html) 317 | or die "Close '$logfile.html.new' after writing failed: $!"; 318 | rename("$logfile.html.new", "$logfile.html") 319 | or die "Rename '$logfile.html.new' to '$logfile.html' failed: $!"; 320 | -------------------------------------------------------------------------------- /env-ot1.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | LOCAL_IF=em2 5 | LOCAL_MAC=90:e2:ba:a4:76:86 6 | 7 | REMOTE_SSH=ot2 8 | REMOTE_IF=em1 9 | REMOTE_MAC=90:e2:ba:d8:67:2d 10 | FAKE_MAC=12:34:56:78:9a:bc 11 | OTHER_IF=em0 12 | 13 | TARGET_SSH=ot3 14 | TARGET_IF=em3 15 | 16 | LOCAL_ADDR=10.188.81.21 17 | LOCAL_NET=10.188.81.21/24 18 | REMOTE_ADDR=10.188.81.22 19 | FAKE_ADDR=10.188.81.188 20 | OTHER_ADDR=10.188.82.22 21 | OTHER_FAKE_ADDR=10.188.82.188 22 | TARGET_ADDR=10.188.82.23 23 | FAKE_NET=10.188.80.0/24 24 | FAKE_NET_ADDR=10.188.80.188 25 | 26 | LOCAL_ADDR6=fdd7:e83e:66bc:81::21 27 | LOCAL_NET6=fdd7:e83e:66bc:81::21/64 28 | REMOTE_ADDR6=fdd7:e83e:66bc:81::22 29 | FAKE_ADDR6=fdd7:e83e:66bc:81::188 30 | OTHER_ADDR6=fdd7:e83e:66bc:82::22 31 | OTHER_FAKE1_ADDR6=fdd7:e83e:66bc:82::dead 32 | OTHER_FAKE2_ADDR6=fdd7:e83e:66bc:82::beef 33 | TARGET_ADDR6=fdd7:e83e:66bc:82::23 34 | FAKE_NET6=fdd7:e83e:66bc:80::/64 35 | FAKE_NET_ADDR6=fdd7:e83e:66bc:80::188 36 | 37 | export LOCAL_IF LOCAL_MAC 38 | export REMOTE_SSH REMOTE_IF REMOTE_MAC FAKE_MAC OTHER_IF 39 | export TARGET_SSH TARGET_IF 40 | export LOCAL_ADDR LOCAL_NET REMOTE_ADDR FAKE_ADDR 41 | export OTHER_ADDR OTHER_FAKE_ADDR 42 | export LOCAL_ADDR6 LOCAL_NET6 REMOTE_ADDR6 FAKE_ADDR6 43 | export OTHER_ADDR6 OTHER_FAKE1_ADDR6 OTHER_FAKE2_ADDR6 44 | export FAKE_NET FAKE_NET_ADDR 45 | export FAKE_NET6 FAKE_NET_ADDR6 TARGET_ADDR 46 | 47 | SRC_IF=em2 48 | SRC_MAC=00:90:e2:ba:a4:76:86 49 | PF_IFIN=em1 50 | PF_IFOUT=em0 51 | PF_MAC=90:e2:ba:d8:67:2d 52 | PF_SSH=ot2 53 | RT_SSH=ot3 54 | ECO_SSH=ot4 55 | 56 | SRC_OUT=10.188.81.21 57 | PF_IN=10.188.81.22 58 | PF_OUT=10.188.82.22 59 | RT_IN=10.188.82.23 60 | RT_OUT=10.188.83.23 61 | ECO_IN=10.188.83.24 62 | ECO_OUT=10.188.84.24 63 | RDR_IN=10.188.85.188 64 | RDR_OUT=10.188.86.188 65 | AF_IN=10.188.87.36 # /24 must be dec(ECO_IN6/120) 66 | RTT_IN=10.188.88.24 67 | RTT_OUT=10.188.89.24 68 | RPT_IN=10.188.90.21 69 | RPT_OUT=10.188.91.21 70 | 71 | SRC_OUT6=fdd7:e83e:66bc:81::21 72 | PF_IN6=fdd7:e83e:66bc:81::22 73 | PF_OUT6=fdd7:e83e:66bc:82::22 74 | RT_IN6=fdd7:e83e:66bc:82::23 75 | RT_OUT6=fdd7:e83e:66bc:83::23 76 | ECO_IN6=fdd7:e83e:66bc:83::24 77 | ECO_OUT6=fdd7:e83e:66bc:84::24 78 | RDR_IN6=fdd7:e83e:66bc:85::188 79 | RDR_OUT6=fdd7:e83e:66bc:86::188 80 | AF_IN6=fdd7:e83e:66bc:87::18 # /120 must be hex(ECO_IN/24) 81 | RTT_IN6=fdd7:e83e:66bc:88::24 82 | RTT_OUT6=fdd7:e83e:66bc:89::24 83 | RPT_IN6=fdd7:e83e:66bc:90::21 84 | RPT_OUT6=fdd7:e83e:66bc:91::21 85 | 86 | export SRC_IF SRC_MAC PF_IFIN PF_IFOUT PF_MAC PF_SSH RT_SSH ECO_SSH 87 | export SRC_OUT PF_IN PF_OUT RT_IN RT_OUT ECO_IN ECO_OUT 88 | export RDR_IN RDR_OUT AF_IN RTT_IN RTT_OUT RPT_IN RPT_OUT 89 | export SRC_OUT6 PF_IN6 PF_OUT6 RT_IN6 RT_OUT6 ECO_IN6 ECO_OUT6 90 | export RDR_IN6 RDR_OUT6 AF_IN6 RTT_IN6 RTT_OUT6 RPT_IN6 RPT_OUT6 91 | 92 | SRC_OUT_IF=em2 93 | IPS_IN_IF=em1 94 | IPS_OUT_IF=em0 95 | RT_IN_IF=em0 96 | RT_OUT_IF=em1 97 | ECO_IN_IF=em3 98 | IPS_SSH=ot2 99 | 100 | export SRC_OUT_IF IPS_IN_IF IPS_OUT_IF RT_IN_IF RT_OUT_IF ECO_IN_IF IPS_SSH 101 | 102 | LEFT_SSH=ot3 103 | LEFT_ADDR=10.188.43.23 104 | LEFT_ADDR6=fdd7:e83e:66bc:43::23 105 | 106 | RIGHT_SSH=ot4 107 | RIGHT_ADDR=10.188.43.24 108 | RIGHT_ADDR6=fdd7:e83e:66bc:43::24 109 | 110 | export LEFT_SSH LEFT_ADDR LEFT_ADDR6 111 | export RIGHT_SSH RIGHT_ADDR RIGHT_ADDR6 112 | -------------------------------------------------------------------------------- /env-ot10.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | LOCAL_IF=mcx1 5 | LOCAL_MAC=98:03:9b:82:ed:f7 6 | 7 | REMOTE_SSH=ot11 8 | REMOTE_IF=mcx1 9 | REMOTE_MAC=b8:59:9f:0e:57:55 10 | FAKE_MAC=12:34:56:78:9a:bc 11 | OTHER_IF=em0 12 | 13 | LOCAL_ADDR=10.188.31.30 14 | LOCAL_NET=10.188.31.30/24 15 | REMOTE_ADDR=10.188.31.31 16 | FAKE_ADDR=10.188.31.188 17 | OTHER_ADDR=10.188.32.31 18 | OTHER_FAKE_ADDR=10.188.32.188 19 | FAKE_NET=10.188.30.0/24 20 | FAKE_NET_ADDR=10.188.30.188 21 | 22 | LOCAL_ADDR6=fdd7:e83e:66bc:31::30 23 | LOCAL_NET6=fdd7:e83e:66bc:31::30/64 24 | REMOTE_ADDR6=fdd7:e83e:66bc:31::31 25 | FAKE_ADDR6=fdd7:e83e:66bc:31::188 26 | OTHER_ADDR6=fdd7:e83e:66bc:32::31 27 | OTHER_FAKE1_ADDR6=fdd7:e83e:66bc:32::dead 28 | OTHER_FAKE2_ADDR6=fdd7:e83e:66bc:32::beef 29 | FAKE_NET6=fdd7:e83e:66bc:30::/64 30 | FAKE_NET_ADDR6=fdd7:e83e:66bc:30::188 31 | 32 | export LOCAL_IF LOCAL_MAC 33 | export REMOTE_SSH REMOTE_IF REMOTE_MAC FAKE_MAC OTHER_IF 34 | export LOCAL_ADDR LOCAL_NET REMOTE_ADDR FAKE_ADDR 35 | export OTHER_ADDR OTHER_FAKE_ADDR 36 | export LOCAL_ADDR6 LOCAL_NET6 REMOTE_ADDR6 FAKE_ADDR6 37 | export OTHER_ADDR6 OTHER_FAKE1_ADDR6 OTHER_FAKE2_ADDR6 38 | export FAKE_NET FAKE_NET_ADDR 39 | export FAKE_NET6 FAKE_NET_ADDR6 40 | -------------------------------------------------------------------------------- /env-ot11.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | LOCAL_IF=mcx1 5 | LOCAL_MAC=b8:59:9f:0e:57:55 6 | 7 | LOCAL_ADDR=10.188.31.31 8 | LOCAL_NET=10.188.31.31/24 9 | FAKE_ADDR=10.188.31.188 10 | 11 | LOCAL_ADDR6=fdd7:e83e:66bc:31::31 12 | LOCAL_NET6=fdd7:e83e:66bc:31::31/64 13 | FAKE_ADDR6=fdd7:e83e:66bc:31::188 14 | 15 | export LOCAL_IF LOCAL_MAC 16 | export LOCAL_ADDR LOCAL_NET FAKE_ADDR 17 | export LOCAL_ADDR6 LOCAL_NET6 FAKE_ADDR6 18 | 19 | ftp_proxy=http://10.0.1.3:8000/ 20 | http_proxy=http://10.0.1.3:8000/ 21 | https_proxy=http://10.0.1.3:8000/ 22 | export ftp_proxy http_proxy https_proxy 23 | -------------------------------------------------------------------------------- /env-ot12.sh: -------------------------------------------------------------------------------- 1 | LOCAL_IF=ix0 2 | LOCAL_ADDR=10.3.0.32 3 | LOCAL_NET=10.3.0.32/24 4 | LOCAL_ADDR6=fdd7:e83e:66bc:0300::32 5 | LOCAL_NET6=fdd7:e83e:66bc:0300::32/64 6 | REMOTE_ADDR=10.3.0.33 7 | REMOTE_ADDR6=fdd7:e83e:66bc:0300::33 8 | REMOTE_SSH=ot13 9 | 10 | export LOCAL_IF LOCAL_ADDR LOCAL_NET LOCAL_ADDR6 LOCAL_NET6 11 | export REMOTE_ADDR REMOTE_ADDR6 REMOTE_SSH 12 | -------------------------------------------------------------------------------- /env-ot14.sh: -------------------------------------------------------------------------------- 1 | LOCAL_IF=ix0 2 | LOCAL_MAC=00:1b:21:0d:db:8f 3 | LOCAL_ADDR=10.3.45.34 4 | LOCAL_NET=10.3.45.34/24 5 | LOCAL_ADDR6=fdd7:e83e:66bc:0345::34 6 | LOCAL_NET6=fdd7:e83e:66bc:0345::34/64 7 | 8 | REMOTE_IF=ix1 9 | REMOTE_MAC=00:1b:21:0d:db:9b 10 | REMOTE_ADDR=10.3.45.35 11 | REMOTE_ADDR6=fdd7:e83e:66bc:0345::35 12 | REMOTE_SSH=ot15 13 | 14 | LINUX_ADDR=10.3.46.36 15 | LINUX_ADDR6=fdd7:e83e:66bc:0346::36 16 | LINUX_FORWARD_ADDR=10.3.46.36 17 | LINUX_FORWARD_ADDR6=fdd7:e83e:66bc:0346::36 18 | LINUX_RELAY_ADDR=10.3.34.34 19 | LINUX_RELAY_ADDR6=fdd7:e83e:66bc:0334::34 20 | LINUX_LINUX_ADDR=10.3.36.36 21 | LINUX_LINUX_ADDR6=fdd7:e83e:66bc:336::36 22 | LINUX_LEFT_SSH=perform@lt13 23 | 24 | LINUX_RELAY_LOCAL_ADDR=10.3.56.35 25 | LINUX_RELAY_LOCAL_ADDR6=fdd7:e83e:66bc:0356::35 26 | LINUX_RELAY_REMOTE_ADDR=10.3.46.34 27 | LINUX_RELAY_REMOTE_ADDR6=fdd7:e83e:66bc:0346::34 28 | LINUX_RIGHT_SSH=perform@lt16 29 | 30 | LOCAL_IPSEC_ADDR=10.4.34.34 31 | LOCAL_IPSEC_ADDR6=fdd7:e83e:66bc:0434::34 32 | REMOTE_IPSEC_ADDR=10.4.56.35 33 | REMOTE_IPSEC_ADDR6=fdd7:e83e:66bc:0456::35 34 | LINUX_IPSEC_ADDR=10.4.56.36 35 | LINUX_IPSEC_ADDR6=fdd7:e83e:66bc:0456::36 36 | 37 | LINUX_VEB_ADDR=10.5.0.36 38 | LINUX_VEB_ADDR6=fdd7:e83e:66bc:0500::36 39 | 40 | PFSYNC_IF=ix5 41 | PFSYNC_ADDR=10.3.14.34 42 | PFSYNC_PEER_IF=ixl1 43 | PFSYNC_PEER_ADDR=10.3.14.51 44 | PFSYNC_SSH=ot31 45 | 46 | LOCAL_ADDR_RANGE=10.3.46.40 47 | LOCAL_ADDR6_RANGE=fdd7:e83e:66bc:346::40 48 | REMOTE_ADDR_RANGE=10.3.56.50 49 | REMOTE6_ADDR_RANGE=fdd7:e83e:66bc:356::50 50 | LINUX_ADDR_RANGE=10.3.46.60 51 | LINUX_ADDR6_RANGE=fdd7:e83e:66bc:346::60 52 | 53 | export LOCAL_IF LOCAL_MAC LOCAL_ADDR LOCAL_NET LOCAL_ADDR6 LOCAL_NET6 54 | export REMOTE_IF REMOTE_MAC REMOTE_ADDR REMOTE_ADDR6 55 | export REMOTE_SSH 56 | export LINUX_ADDR LINUX_ADDR6 LINUX_FORWARD_ADDR LINUX_FORWARD_ADDR6 57 | export LINUX_RELAY_ADDR LINUX_RELAY_ADDR6 LINUX_LINUX_ADDR LINUX_LINUX_ADDR6 58 | export LINUX_LEFT_SSH 59 | export LINUX_RELAY_LOCAL_ADDR LINUX_RELAY_LOCAL_ADDR6 60 | export LINUX_RELAY_REMOTE_ADDR LINUX_RELAY_REMOTE_ADDR6 61 | export LINUX_RIGHT_SSH 62 | export LOCAL_IPSEC_ADDR REMOTE_IPSEC_ADDR LINUX_IPSEC_ADDR 63 | export LOCAL_IPSEC_ADDR6 REMOTE_IPSEC_ADDR6 LINUX_IPSEC_ADDR6 64 | export LINUX_VEB_ADDR LINUX_VEB_ADDR6 65 | export PFSYNC_IF PFSYNC_ADDR PFSYNC_PEER_IF PFSYNC_PEER_ADDR PFSYNC_SSH 66 | export LOCAL_ADDR_RANGE LOCAL_ADDR6_RANGE REMOTE_ADDR_RANGE REMOTE_ADDR6_RANGE 67 | export LINUX_ADDR_RANGE LINUX_ADDR6_RANGE 68 | -------------------------------------------------------------------------------- /env-ot19.sh: -------------------------------------------------------------------------------- 1 | # em18 is management, em18 is tripple port 2 | # em8 and em9 are onboard 3 | # em4, em5 and em12, em13 belong to quad port 4 | export MANAGEMENT_IF=em18 5 | export SKIP_IF=em18 6 | export NETLINK_LINE=3 7 | export LINUX_IF=ens1f0 8 | export LINUX_LEFT_SSH=root@lt40 9 | export LINUX_RIGHT_SSH=root@lt43 10 | 11 | # allow to manually run perform tests frag and splice on netlink hosts 12 | 13 | LOCAL_ADDR=undef 14 | LOCAL_NET=undef 15 | LOCAL_ADDR6=undef 16 | LOCAL_NET6=undef 17 | REMOTE_ADDR=undef 18 | REMOTE_ADDR6=undef 19 | REMOTE_SSH=undef 20 | export LOCAL_ADDR LOCAL_NET LOCAL_ADDR6 LOCAL_NET6 21 | export REMOTE_ADDR REMOTE_ADDR6 REMOTE_SSH 22 | 23 | LOCAL_ADDR_RANGE=10.10.31.20 24 | LOCAL_ADDR6_RANGE=fdd7:e83e:66bd:1031::20 25 | LINUX_ADDR_RANGE=10.10.32.40 26 | LINUX_ADDR6_RANGE=fdd7:e83e:66bd:1032::40 27 | export LOCAL_ADDR_RANGE LOCAL_ADDR6_RANGE LINUX_ADDR_RANGE LINUX_ADDR6_RANGE 28 | -------------------------------------------------------------------------------- /env-ot2.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | LOCAL_IF=em1 5 | LOCAL_MAC=90:e2:ba:d8:67:2d 6 | LOCAL_ADDR=10.188.81.22 7 | LOCAL_NET=10.188.81.22/24 8 | FAKE_ADDR=10.188.81.188 9 | 10 | LOCAL_ADDR6=fdd7:e83e:66bc:81::22 11 | LOCAL_NET6=fdd7:e83e:66bc:81::22 12 | FAKE_ADDR6=fdd7:e83e:66bc:81::188 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | export LOCAL_ADDR LOCAL_NET FAKE_ADDR 16 | export LOCAL_ADDR6 LOCAL_NET6 FAKE_ADDR6 17 | -------------------------------------------------------------------------------- /env-ot21.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | 9 | LOCAL_IF=cas1 10 | LOCAL_MAC=00:03:ba:ac:b9:b4 11 | 12 | LOCAL_ADDR=10.188.21.41 13 | LOCAL_NET=10.188.21.41/24 14 | FAKE_ADDR=10.188.21.188 15 | 16 | LOCAL_ADDR6=fdd7:e83e:66bc:21::41 17 | LOCAL_NET6=fdd7:e83e:66bc:21::41/64 18 | FAKE_ADDR6=fdd7:e83e:66bc:21::188 19 | 20 | export LOCAL_IF LOCAL_MAC 21 | export LOCAL_ADDR LOCAL_NET FAKE_ADDR 22 | export LOCAL_ADDR6 LOCAL_NET6 FAKE_ADDR6 23 | -------------------------------------------------------------------------------- /env-ot25.sh: -------------------------------------------------------------------------------- 1 | # em0 is management 2 | # em0, em1, em2, em3 are onboard 3 | # em6, em7 belong to quad port 4 | export MANAGEMENT_IF=em0 5 | export SKIP_IF=em0,em1,em6,em7 6 | export NETLINK_LINE=4 7 | export LINUX_IF=ens1f1 8 | export LINUX_LEFT_SSH=root@lt40 9 | export LINUX_RIGHT_SSH=root@lt43 10 | 11 | # allow to manually run perform tests frag and splice on netlink hosts 12 | 13 | export REGRESS_FAIL_EARLY=no 14 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 15 | 16 | LOCAL_IF=em1 17 | LOCAL_MAC=00:21:28:13:9c:0d 18 | 19 | LOCAL_ADDR=10.188.25.45 20 | LOCAL_NET=10.188.25.45/24 21 | FAKE_ADDR=10.188.25.188 22 | 23 | LOCAL_ADDR6=fdd7:e83e:66bc:25::45 24 | LOCAL_NET6=fdd7:e83e:66bc:25::45/64 25 | FAKE_ADDR6=fdd7:e83e:66bc:25::188 26 | 27 | export LOCAL_IF LOCAL_MAC 28 | export LOCAL_ADDR LOCAL_NET FAKE_ADDR 29 | export LOCAL_ADDR6 LOCAL_NET6 FAKE_ADDR6 30 | 31 | ftp_proxy=http://10.0.1.3:8000/ 32 | http_proxy=http://10.0.1.3:8000/ 33 | https_proxy=http://10.0.1.3:8000/ 34 | export ftp_proxy http_proxy https_proxy 35 | 36 | # allow to manually run perform tests frag and splice on netlink hosts 37 | 38 | LOCAL_ADDR_RANGE=10.10.41.20 39 | LOCAL_ADDR6_RANGE=fdd7:e83e:66bd:1041::20 40 | LINUX_ADDR_RANGE=10.10.42.40 41 | LINUX_ADDR6_RANGE=fdd7:e83e:66bd:1042::40 42 | export LOCAL_ADDR_RANGE LOCAL_ADDR6_RANGE LINUX_ADDR_RANGE LINUX_ADDR6_RANGE 43 | -------------------------------------------------------------------------------- /env-ot26.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | LOCAL_IF=em1 5 | LOCAL_MAC=00:1b:21:30:3c:51 6 | 7 | LOCAL_ADDR=10.188.51.46 8 | LOCAL_NET=10.188.51.46/24 9 | FAKE_ADDR=10.188.51.188 10 | 11 | LOCAL_ADDR6=fdd7:e83e:66bc:51::46 12 | LOCAL_NET6=fdd7:e83e:66bc:51::46/64 13 | FAKE_ADDR6=fdd7:e83e:66bc:51::188 14 | 15 | export LOCAL_IF LOCAL_MAC 16 | export LOCAL_ADDR LOCAL_NET FAKE_ADDR 17 | export LOCAL_ADDR6 LOCAL_NET6 FAKE_ADDR6 18 | 19 | ftp_proxy=http://10.0.1.3:8000/ 20 | http_proxy=http://10.0.1.3:8000/ 21 | https_proxy=http://10.0.1.3:8000/ 22 | export ftp_proxy http_proxy https_proxy 23 | -------------------------------------------------------------------------------- /env-ot27.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | LOCAL_IF=bge1 5 | LOCAL_MAC=2c:09:4d:00:04:b8 6 | 7 | LOCAL_ADDR=10.188.27.47 8 | LOCAL_NET=10.188.27.47/24 9 | FAKE_ADDR=10.188.27.188 10 | 11 | LOCAL_ADDR6=fdd7:e83e:66bc:27::47 12 | LOCAL_NET6=fdd7:e83e:66bc:27::47/64 13 | FAKE_ADDR6=fdd7:e83e:66bc:27::188 14 | 15 | export LOCAL_IF LOCAL_MAC 16 | export LOCAL_ADDR LOCAL_NET FAKE_ADDR 17 | export LOCAL_ADDR6 LOCAL_NET6 FAKE_ADDR6 18 | 19 | ftp_proxy=http://10.0.1.3:8000/ 20 | http_proxy=http://10.0.1.3:8000/ 21 | https_proxy=http://10.0.1.3:8000/ 22 | export ftp_proxy http_proxy https_proxy 23 | -------------------------------------------------------------------------------- /env-ot29.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | LOCAL_IF=em1 5 | LOCAL_MAC=d0:50:99:f9:d7:0c 6 | 7 | export LOCAL_IF LOCAL_MAC 8 | 9 | ftp_proxy=http://10.0.1.3:8000/ 10 | http_proxy=http://10.0.1.3:8000/ 11 | https_proxy=http://10.0.1.3:8000/ 12 | export ftp_proxy http_proxy https_proxy 13 | -------------------------------------------------------------------------------- /env-ot3.sh: -------------------------------------------------------------------------------- 1 | ftp_proxy=http://10.0.1.3:8000/ 2 | http_proxy=http://10.0.1.3:8000/ 3 | https_proxy=http://10.0.1.3:8000/ 4 | export ftp_proxy http_proxy https_proxy 5 | -------------------------------------------------------------------------------- /env-ot31.sh: -------------------------------------------------------------------------------- 1 | LOCAL_IF=ixl0 2 | LOCAL_MAC=3c:fd:fe:0d:03:e0 3 | LOCAL_ADDR=10.6.12.51 4 | LOCAL_NET=10.6.12.51/24 5 | LOCAL_ADDR6=fdd7:e83e:66bc:0612::51 6 | LOCAL_NET6=fdd7:e83e:66bc:0612::51/64 7 | 8 | REMOTE_IF=ixl1 9 | REMOTE_MAC=40:a6:b7:02:38:3d 10 | REMOTE_ADDR=10.6.12.52 11 | REMOTE_ADDR6=fdd7:e83e:66bc:0612::52 12 | REMOTE_SSH=ot32 13 | 14 | LINUX_ADDR=10.6.16.36 15 | LINUX_ADDR6=fdd7:e83e:66bc:0616::36 16 | LINUX_FORWARD_ADDR=10.6.16.36 17 | LINUX_FORWARD_ADDR6=fdd7:e83e:66bc:0616::36 18 | LINUX_RELAY_ADDR=10.6.31.51 19 | LINUX_RELAY_ADDR6=fdd7:e83e:66bc:0631::51 20 | LINUX_LINUX_ADDR=10.3.36.36 21 | LINUX_LINUX_ADDR6=fdd7:e83e:66bc:336::36 22 | LINUX_LEFT_SSH=perform@lt13 23 | 24 | LINUX_RELAY_LOCAL_ADDR=10.6.26.52 25 | LINUX_RELAY_LOCAL_ADDR6=fdd7:e83e:66bc:0626::52 26 | LINUX_RELAY_REMOTE_ADDR=10.6.16.51 27 | LINUX_RELAY_REMOTE_ADDR6=fdd7:e83e:66bc:0616::51 28 | LINUX_RIGHT_SSH=perform@lt16 29 | 30 | LOCAL_IPSEC_ADDR=10.7.31.51 31 | LOCAL_IPSEC_ADDR6=fdd7:e83e:66bc:0731::51 32 | REMOTE_IPSEC_ADDR=10.7.26.52 33 | REMOTE_IPSEC_ADDR6=fdd7:e83e:66bc:0726::52 34 | LINUX_IPSEC_ADDR=10.7.26.36 35 | LINUX_IPSEC_ADDR6=fdd7:e83e:66bc:0726::36 36 | LOCAL_IPSEC6_ADDR=10.8.31.51 37 | LOCAL_IPSEC6_ADDR6=fdd7:e83e:66bc:0831::51 38 | REMOTE_IPSEC6_ADDR=10.8.26.52 39 | REMOTE_IPSEC6_ADDR6=fdd7:e83e:66bc:0826::52 40 | LINUX_IPSEC6_ADDR=10.8.26.36 41 | LINUX_IPSEC6_ADDR6=fdd7:e83e:66bc:0826::36 42 | LOCAL_IPSEC_TRANS_ADDR=10.9.12.51 43 | LOCAL_IPSEC_TRANS_ADDR6=fdd7:e83e:66bc:0912::51 44 | REMOTE_IPSEC_TRANS_ADDR=10.9.12.52 45 | REMOTE_IPSEC_TRANS_ADDR6=fdd7:e83e:66bc:0912::52 46 | 47 | PFSYNC_IF=ixl1 48 | PFSYNC_ADDR=10.3.14.51 49 | PFSYNC_PEER_IF=ix3 50 | PFSYNC_PEER_ADDR=10.3.14.34 51 | PFSYNC_SSH=ot14 52 | 53 | LOCAL_ADDR_RANGE=10.6.16.10 54 | LOCAL_ADDR6_RANGE=fdd7:e83e:66bc:616::10 55 | REMOTE_ADDR_RANGE=10.6.26.20 56 | REMOTE6_ADDR_RANGE=fdd7:e83e:66bc:626::20 57 | LINUX_ADDR_RANGE=10.6.16.60 58 | LINUX_ADDR6_RANGE=fdd7:e83e:66bc:616::60 59 | 60 | export LOCAL_IF LOCAL_MAC LOCAL_ADDR LOCAL_NET LOCAL_ADDR6 LOCAL_NET6 61 | export REMOTE_IF REMOTE_MAC REMOTE_ADDR REMOTE_ADDR6 62 | export REMOTE_SSH 63 | export LINUX_ADDR LINUX_ADDR6 LINUX_FORWARD_ADDR LINUX_FORWARD_ADDR6 64 | export LINUX_RELAY_ADDR LINUX_RELAY_ADDR6 LINUX_LINUX_ADDR LINUX_LINUX_ADDR6 65 | export LINUX_LEFT_SSH 66 | export LINUX_RELAY_LOCAL_ADDR LINUX_RELAY_LOCAL_ADDR6 67 | export LINUX_RELAY_REMOTE_ADDR LINUX_RELAY_REMOTE_ADDR6 68 | export LINUX_RIGHT_SSH 69 | export LOCAL_IPSEC_ADDR REMOTE_IPSEC_ADDR LINUX_IPSEC_ADDR 70 | export LOCAL_IPSEC_ADDR6 REMOTE_IPSEC_ADDR6 LINUX_IPSEC_ADDR6 71 | export LOCAL_IPSEC6_ADDR REMOTE_IPSEC6_ADDR LINUX_IPSEC6_ADDR 72 | export LOCAL_IPSEC6_ADDR6 REMOTE_IPSEC6_ADDR6 LINUX_IPSEC6_ADDR6 73 | export LOCAL_IPSEC_TRANS_ADDR REMOTE_IPSEC_TRANS_ADDR 74 | export LOCAL_IPSEC_TRANS_ADDR6 REMOTE_IPSEC_TRANS_ADDR6 75 | export PFSYNC_IF PFSYNC_ADDR PFSYNC_PEER_IF PFSYNC_PEER_ADDR PFSYNC_SSH 76 | export LOCAL_ADDR_RANGE LOCAL_ADDR6_RANGE REMOTE_ADDR_RANGE REMOTE_ADDR6_RANGE 77 | export LINUX_ADDR_RANGE LINUX_ADDR6_RANGE 78 | -------------------------------------------------------------------------------- /env-ot33.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | -------------------------------------------------------------------------------- /env-ot35.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | -------------------------------------------------------------------------------- /env-ot4.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | -------------------------------------------------------------------------------- /env-ot41.sh: -------------------------------------------------------------------------------- 1 | # em4 is management, not enough switch ports for em2 and em3 2 | export MANAGEMENT_IF=em4 3 | export SKIP_IF=em4,em2,em3 4 | export NETLINK_LINE=1 5 | export LINUX_IF=ens2f1 6 | export LINUX_LEFT_SSH=root@lt40 7 | export LINUX_RIGHT_SSH=root@lt43 8 | 9 | # allow to manually run perform tests frag and splice on netlink hosts 10 | 11 | LOCAL_ADDR=undef 12 | LOCAL_NET=undef 13 | LOCAL_ADDR6=undef 14 | LOCAL_NET6=undef 15 | REMOTE_ADDR=undef 16 | REMOTE_ADDR6=undef 17 | REMOTE_SSH=undef 18 | export LOCAL_ADDR LOCAL_NET LOCAL_ADDR6 LOCAL_NET6 19 | export REMOTE_ADDR REMOTE_ADDR6 REMOTE_SSH 20 | 21 | LOCAL_ADDR_RANGE=10.10.11.20 22 | LOCAL_ADDR6_RANGE=fdd7:e83e:66bd:1011::20 23 | LINUX_ADDR_RANGE=10.10.12.40 24 | LINUX_ADDR6_RANGE=fdd7:e83e:66bd:1012::40 25 | export LOCAL_ADDR_RANGE LOCAL_ADDR6_RANGE LINUX_ADDR_RANGE LINUX_ADDR6_RANGE 26 | -------------------------------------------------------------------------------- /env-ot42.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=em0 2 | export SKIP_IF=em0,em1,igc2,igc3 3 | export NETLINK_LINE=2 4 | export LINUX_IF=ens2f0 5 | export LINUX_LEFT_SSH=root@lt40 6 | export LINUX_RIGHT_SSH=root@lt43 7 | 8 | # allow to manually run perform tests frag and splice on netlink hosts 9 | 10 | LOCAL_ADDR=undef 11 | LOCAL_NET=undef 12 | LOCAL_ADDR6=undef 13 | LOCAL_NET6=undef 14 | REMOTE_ADDR=undef 15 | REMOTE_ADDR6=undef 16 | REMOTE_SSH=undef 17 | export LOCAL_ADDR LOCAL_NET LOCAL_ADDR6 LOCAL_NET6 18 | export REMOTE_ADDR REMOTE_ADDR6 REMOTE_SSH 19 | 20 | LOCAL_ADDR_RANGE=10.10.21.20 21 | LOCAL_ADDR6_RANGE=fdd7:e83e:66bd:1021::20 22 | LINUX_ADDR_RANGE=10.10.22.40 23 | LINUX_ADDR6_RANGE=fdd7:e83e:66bd:1022::40 24 | export LOCAL_ADDR_RANGE LOCAL_ADDR6_RANGE LINUX_ADDR_RANGE LINUX_ADDR6_RANGE 25 | -------------------------------------------------------------------------------- /env-ot44.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | -------------------------------------------------------------------------------- /env-ot48.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=5 4 | export LINUX_IF=enp7s0 5 | export LINUX_LEFT_SSH=root@lt49 6 | export LINUX_RIGHT_SSH=root@lt59 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=52:54:00:00:9c:58 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot5.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | 9 | LOCAL_IF=em0 10 | LOCAL_MAC=90:e2:ba:7e:e8:10 11 | 12 | LOCAL_ADDR=10.188.51.25 13 | LOCAL_NET=10.188.51.25/24 14 | FAKE_ADDR=10.188.51.188 15 | 16 | LOCAL_ADDR6=fdd7:e83e:66bc:51::25 17 | LOCAL_NET6=fdd7:e83e:66bc:51::25/64 18 | FAKE_ADDR6=fdd7:e83e:66bc:51::188 19 | 20 | export LOCAL_IF LOCAL_MAC 21 | export LOCAL_ADDR LOCAL_NET FAKE_ADDR 22 | export LOCAL_ADDR6 LOCAL_NET6 FAKE_ADDR6 23 | -------------------------------------------------------------------------------- /env-ot50.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | -------------------------------------------------------------------------------- /env-ot51.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | -------------------------------------------------------------------------------- /env-ot52.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | -------------------------------------------------------------------------------- /env-ot57.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vmx2 2 | export SKIP_IF=vmx2 3 | export NETLINK_LINE=6 4 | export LINUX_IF=ens224 5 | export LINUX_LEFT_SSH=root@lt54 6 | export LINUX_RIGHT_SSH=root@lt55 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vmx1 12 | LOCAL_MAC=00:0c:29:2e:8e:b3 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot6.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | LOCAL_IF=em1 5 | LOCAL_MAC=00:04:23:d8:a7:59 6 | 7 | LOCAL_ADDR=10.188.61.26 8 | LOCAL_NET=10.188.61.26/24 9 | FAKE_ADDR=10.188.61.188 10 | 11 | LOCAL_ADDR6=fdd7:e83e:66bc:61::26 12 | LOCAL_NET6=fdd7:e83e:66bc:61::26/64 13 | FAKE_ADDR6=fdd7:e83e:66bc:61::188 14 | 15 | export LOCAL_IF LOCAL_MAC 16 | export LOCAL_ADDR LOCAL_NET FAKE_ADDR 17 | export LOCAL_ADDR6 LOCAL_NET6 FAKE_ADDR6 18 | -------------------------------------------------------------------------------- /env-ot62.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=7 4 | export LINUX_IF=eth1 5 | export LINUX_LEFT_SSH=root@lt61 6 | export LINUX_RIGHT_SSH=root@lt63 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=fe:e1:bb:d2:dc:a1 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot7.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | -------------------------------------------------------------------------------- /env-ot71.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=8 4 | export LINUX_IF=eth1 5 | export LINUX_LEFT_SSH=root@lt70 6 | export LINUX_RIGHT_SSH=root@lt75 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=fe:e1:bb:d2:18:05 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot72.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=9 4 | export LINUX_IF=eth1 5 | export LINUX_LEFT_SSH=root@lt70 6 | export LINUX_RIGHT_SSH=root@lt75 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=fe:e1:bb:d2:76:c0 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot73.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=3 4 | export LINUX_IF=eth1 5 | export LINUX_LEFT_SSH=root@lt70 6 | export LINUX_RIGHT_SSH=root@lt75 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=fe:e1:bb:d2:30:5f 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot74.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=0 4 | export LINUX_IF=eth1 5 | export LINUX_LEFT_SSH=root@lt70 6 | export LINUX_RIGHT_SSH=root@lt75 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=fe:e1:bb:d2:4e:a1 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot8.sh: -------------------------------------------------------------------------------- 1 | export REGRESS_FAIL_EARLY=no 2 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 3 | 4 | ftp_proxy=http://10.0.1.3:8000/ 5 | http_proxy=http://10.0.1.3:8000/ 6 | https_proxy=http://10.0.1.3:8000/ 7 | export ftp_proxy http_proxy https_proxy 8 | -------------------------------------------------------------------------------- /env-ot81.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=0 4 | export LINUX_IF=enp8s0 5 | export LINUX_LEFT_SSH=root@lt80 6 | export LINUX_RIGHT_SSH=root@lt85 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=52:54:00:08:36:74 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot91.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=4 4 | export LINUX_IF=enp7s0 5 | export LINUX_LEFT_SSH=root@lt90 6 | export LINUX_RIGHT_SSH=root@lt95 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=52:54:00:6d:8b:64 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot92.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=6 4 | export LINUX_IF=enp7s0 5 | export LINUX_LEFT_SSH=root@lt90 6 | export LINUX_RIGHT_SSH=root@lt95 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=52:54:00:7f:e6:bf 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot93.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=0 4 | export LINUX_IF=enp7s0 5 | export LINUX_LEFT_SSH=root@lt90 6 | export LINUX_RIGHT_SSH=root@lt95 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=52:54:00:85:ae:17 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /env-ot94.sh: -------------------------------------------------------------------------------- 1 | export MANAGEMENT_IF=vio2 2 | export SKIP_IF=vio2 3 | export NETLINK_LINE=0 4 | export LINUX_IF=enp7s0 5 | export LINUX_LEFT_SSH=root@lt90 6 | export LINUX_RIGHT_SSH=root@lt95 7 | 8 | export REGRESS_FAIL_EARLY=no 9 | export TEST_SSH_UNSAFE_PERMISSIONS=yes 10 | 11 | LOCAL_IF=vio1 12 | LOCAL_MAC=52:54:00:8e:1c:76 13 | 14 | export LOCAL_IF LOCAL_MAC 15 | -------------------------------------------------------------------------------- /favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /force-ssh.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -T 2 | # restrict ssh commands 3 | 4 | # Copyright (c) 2021-2022 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | # Allow ssh to run iperf3 or udpbench, but only with safe arguments. 19 | # Start pkill with iperf3 or udpbench argument is also allowed. 20 | # Used in authorized_keys restrict,command="force-ssh.pl iperf3 udpbench". 21 | 22 | use strict; 23 | use warnings; 24 | use Getopt::Std; 25 | 26 | # Arguments of force-ssh.pl specify which commands are allowed. 27 | my %filter; 28 | foreach (@ARGV) { 29 | /^([0-9A-Za-z]+)$/ 30 | or die "Invalid characters in force argument.\n"; 31 | $filter{iperf3} = \&filter_iperf3 if /^iperf3$/; 32 | $filter{tcpbench} = \&filter_tcpbench if /^tcpbench$/; 33 | $filter{udpbench} = \&filter_udpbench if /^udpbench$/; 34 | $filter{timeout} = \&filter_timeout if /^timeout$/; 35 | } 36 | my @allowed = sort keys %filter; 37 | 38 | # Environment from ssh tells which command line the user wants to run. 39 | my $sshcmd = $ENV{SSH_ORIGINAL_COMMAND} 40 | or die "No SSH_ORIGINAL_COMMAND in environment.\n"; 41 | $sshcmd =~ /^([ 0-9A-Za-z.:_-]+)$/ 42 | or die "Invalid characters in ssh command.\n"; 43 | my @args = split(" ", $1) 44 | or die "Split ssh command failed.\n"; 45 | my $cmd = $args[0]; 46 | 47 | if ($cmd eq "pkill") { 48 | # Run pkill with allowed command if the user wanted to kill. 49 | @args == 2 50 | or die "Only one argument for pkill allowed.\n"; 51 | $filter{$args[1]} 52 | or die "Only pkill '@allowed' allowed.\n"; 53 | } else { 54 | # Filter untrusted options of iperf3, tcpbench, or udpbench. 55 | my $sub = $filter{$cmd} 56 | or die "Only command '@allowed' allowed.\n"; 57 | $sub->(@args); 58 | } 59 | 60 | $ENV{PATH} = "/bin:/usr/bin:/usr/local/bin"; 61 | exec { $cmd } @args; 62 | die "Exec '$cmd' failed: $!\n"; 63 | 64 | # Filter out file access options. 65 | sub filter_iperf3 { 66 | shift; 67 | local @ARGV = @_; 68 | my %opts; 69 | getopts('p:f:i:A:B:V:J:d:v:hsD1c:ub:t:n:k:l:P:Rw:M:N46S:L:Z:O:T:C:', 70 | \%opts) 71 | or die "Parsing iperf3 options failed.\n"; 72 | if ($opts{c}) { 73 | $opts{c} =~ /^10\.[0-9.]+$/ || 74 | $opts{c} =~ /^f[cd][0-9a-f]{2}:[0-9a-f:]+$/i 75 | or die "Server address for iperf3 must be local.\n"; 76 | } elsif ($opts{s}) { 77 | } else { 78 | die "Client or server option for iperf3 must be present.\n"; 79 | } 80 | @ARGV <= 0 81 | or die "Too many arguments for iperf3.\n"; 82 | } 83 | 84 | # Filter out debug, kernel, unix, and rtable options. 85 | sub filter_tcpbench { 86 | shift; 87 | local @ARGV = @_; 88 | my %opts; 89 | getopts('46b:B:n:p:Rr:sS:t:T:uv', \%opts) 90 | or die "Parsing tcpbench options failed.\n"; 91 | @ARGV < 1 || $ARGV[0] =~ /^10\.[0-9.]+$/ || 92 | $ARGV[0] =~ /^f[cd][0-9a-f]{2}:[0-9a-f:]+$/i 93 | or die "Host address for tcpbench must be local.\n"; 94 | @ARGV <= 1 95 | or die "Too many arguments for tcpbench.\n"; 96 | } 97 | 98 | # Filter out remote and divert options. 99 | sub filter_udpbench { 100 | shift; 101 | local @ARGV = @_; 102 | my %opts; 103 | getopts('B:b:Dd:Hi:l:m:N:P:p:t:', \%opts) 104 | or die "Parsing udpbench options failed.\n"; 105 | @ARGV >= 1 && $ARGV[0] =~ /^(send|recv)$/ 106 | or die "Action send or recv for udpbench must be present.\n"; 107 | @ARGV < 2 || $ARGV[1] =~ /^10\.[0-9.]+$/ || 108 | $ARGV[1] =~ /^f[cd][0-9a-f]{2}:[0-9a-f:]+$/i 109 | or die "Host address for udpbench must be local.\n"; 110 | @ARGV <= 2 111 | or die "Too many arguments for udpbench.\n"; 112 | } 113 | 114 | # Filter timeout duration. 115 | sub filter_timeout { 116 | my $cmd = shift; 117 | delete $filter{$cmd}; 118 | @allowed = sort keys %filter; 119 | 120 | my $duration = shift; 121 | defined($duration) && $duration =~ /^\d+$/ 122 | or die "Numeric duration for timeout must be present.\n"; 123 | 124 | my @args = @_ 125 | or die "Missing command for timeout.\n"; 126 | $cmd = $args[0]; 127 | # Filter untrusted options of iperf3, tcpbench, or udpbench. 128 | my $sub = $filter{$cmd} 129 | or die "Only command '@allowed' allowed.\n"; 130 | $sub->(@args); 131 | } 132 | -------------------------------------------------------------------------------- /keys.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # generate gnuplot icons for legend in html graphics 3 | 4 | set -eu 5 | 6 | usage() { 7 | echo "$(basename $0): FROM TO" >&2 8 | echo "\tGenerate pngs of the gnuplot keys in a given range using" >&2 9 | echo "\timagemagick's convert. FROM and TO are positive integers." >&2 10 | exit 1 11 | } 12 | 13 | FROM="$1" 14 | TO="$2" 15 | which gnuplot >/dev/null && which convert >/dev/null || usage 16 | if [ -z "$FROM" ] || [ -n "${FROM#[0-9]*}" ] || [ "$FROM" -le "0" ] ||\ 17 | [ -z "$TO" ] || [ -n "${TO##[0-9]*}" ] || [ "$TO" -lt "$FROM" ]; then 18 | usage 19 | fi 20 | 21 | PLOT=keys.pl 22 | trap "rm -f $PLOT $PLOT.new" 0 23 | 24 | cat >$PLOT.new </dev/null 39 | 40 | for key in key_*.png; do 41 | convert $key -crop 16x24+339+218 $key 42 | done 43 | -------------------------------------------------------------------------------- /kstack.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | fg=/home/bluhm/github/FlameGraph 4 | file="${1:-kstack}" 5 | host="${2:-ot14}" 6 | 7 | # btrace -e 'profile:hz:100{@[kstack]=count()}' >~/"$file.dt" & 8 | # sleep 60; kill -INT $! 9 | 10 | ssh "$host" cat "$file.dt" | \ 11 | $fg/stackcollapse-bpftrace.pl | \ 12 | $fg/flamegraph.pl > \ 13 | /data/test/files/"$host-$file.svg" 14 | 15 | echo http://bluhm.genua.de/files/"$host-$file.svg" 16 | -------------------------------------------------------------------------------- /make.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # make build and release on machine 3 | 4 | # Copyright (c) 2016-2023 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use File::Basename; 22 | use Getopt::Std; 23 | use POSIX; 24 | 25 | use lib dirname($0); 26 | use Logcmd; 27 | use Hostctl; 28 | 29 | my $date = strftime("%FT%TZ", gmtime); 30 | my $scriptname = "$0 @ARGV"; 31 | 32 | my @allsetupmodes = qw(cvs keep kernel restart); 33 | 34 | my %opts; 35 | getopts('h:P:pv', \%opts) or do { 36 | print STDERR <<"EOF"; 37 | usage: make.pl [-pv] -h host [-P patch] setup ... 38 | -h host user and host for make release, user defaults to root 39 | -P patch apply patch to clean source or kernel source 40 | -p power down after testing 41 | -v verbose 42 | setup ... setup mode: @allsetupmodes 43 | cvs cvs update /usr/src and make obj 44 | keep keep installed host as is, skip setup 45 | kernel build kernel from source /usr/src/sys and reboot 46 | restart cvs clean, patch /usr/src, install kernel, reboot 47 | EOF 48 | exit(2); 49 | }; 50 | $opts{h} or die "No -h specified"; 51 | my $patch = $opts{P}; 52 | 53 | @ARGV or die "No setup mode specified"; 54 | my %setupmode; 55 | foreach my $mode (@ARGV) { 56 | grep { $_ eq $mode } @allsetupmodes 57 | or die "Unknown setup mode '$mode'"; 58 | $setupmode{$mode} = 1; 59 | } 60 | foreach my $mode (qw(keep)) { 61 | die "Setup mode '$mode' must be used solely" 62 | if $setupmode{$mode} && keys %setupmode != 1; 63 | } 64 | 65 | # better get an errno than random kill by SIGPIPE 66 | $SIG{PIPE} = 'IGNORE'; 67 | 68 | # create directory for this test run with timestamp 2016-07-13T12:30:42Z 69 | my $regressdir = dirname($0). "/.."; 70 | chdir($regressdir) 71 | or die "Change directory to '$regressdir' failed: $!"; 72 | $regressdir = getcwd(); 73 | my $resultdir = "$regressdir/results/$date"; 74 | mkdir $resultdir 75 | or die "Make directory '$resultdir' failed: $!"; 76 | unlink("results/current"); 77 | symlink($date, "results/current") 78 | or die "Make symlink 'results/current' failed: $!"; 79 | chdir($resultdir) 80 | or die "Change directory to '$resultdir' failed: $!"; 81 | 82 | createlog(file => "make.log", verbose => $opts{v}); 83 | logmsg("$date Script '$scriptname' started.\n"); 84 | 85 | open(my $fh, '>', "makeconf.txt") 86 | or die "Open 'makeconf.txt' for writing failed: $!"; 87 | print $fh "ARGUMENTS @ARGV\n"; 88 | print $fh "HOST $opts{h}\n"; 89 | print $fh "SETUPMODE ", join(" ", sort keys %setupmode), "\n"; 90 | close($fh); 91 | 92 | # setup remote machines 93 | 94 | usehosts(bindir => "$regressdir/bin", date => $date, 95 | host => $opts{h}, lasthost => $opts{h}, verbose => $opts{v}); 96 | (my $host = $opts{h}) =~ s/.*\@//; 97 | 98 | # do not run end block until initialized, date may change later 99 | my $odate = $date; 100 | END { 101 | if ($odate) { 102 | my @cmd = ("$regressdir/bin/bsdcons.pl", '-h', $opts{h}, '-d', $odate); 103 | system(@cmd); 104 | } 105 | if ($regressdir) { 106 | my @cmd = ("$regressdir/bin/setup-html.pl"); 107 | system(@cmd); 108 | @cmd = ("$regressdir/bin/running-html.pl"); 109 | system(@cmd); 110 | } 111 | }; 112 | if ($patch || !$setupmode{keep}) { 113 | setup_hosts(patch => $patch, mode => \%setupmode) 114 | } else { 115 | powerup_hosts(patch => $patch); 116 | } 117 | collect_version(); 118 | setup_html(); 119 | 120 | # run make release remotely 121 | 122 | chdir($resultdir) 123 | or die "Change directory to '$resultdir' failed: $!"; 124 | 125 | my @sshcmd = ('ssh', $opts{h}, 'perl', '/root/release/release.pl', 126 | '-e', "/root/release/env-$host.sh", '-v'); 127 | logcmd(@sshcmd); 128 | 129 | # get result and logs 130 | 131 | collect_result("$opts{h}:/root/release"); 132 | collect_dmesg(); 133 | setup_html(); 134 | powerdown_hosts(patch => $patch) if $opts{p}; 135 | 136 | # create html output 137 | 138 | chdir($regressdir) 139 | or die "Change directory to '$regressdir' failed: $!"; 140 | 141 | setup_html(date => 1); 142 | runcmd("bin/regress-html.pl", "-h", $host, "release"); 143 | 144 | unlink("results/latest-$host"); 145 | symlink($date, "results/latest-$host") 146 | or die "Make symlink 'results/latest-$host' failed: $!"; 147 | unlink("results/latest"); 148 | symlink($date, "results/latest") 149 | or die "Make symlink 'results/latest' failed: $!"; 150 | runcmd("bin/regress-html.pl", "-l", "release"); 151 | 152 | runcmd("bin/regress-html.pl", "release"); 153 | 154 | my $now = strftime("%FT%TZ", gmtime); 155 | logmsg("$now Script '$scriptname' finished.\n"); 156 | 157 | exit; 158 | -------------------------------------------------------------------------------- /makealign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh - 2 | # adapt kernel linker script to align all objects to page size 3 | 4 | if [[ $# -lt 8 ]]; then 5 | echo usage: makealign.sh ld.script \ 6 | locore0.o gap.o ... param.o ioconf.o vers.o swapgeneric.o 1>&2 7 | exit 2 8 | fi 9 | 10 | LDSCRIPT=$1 11 | shift 12 | OBJS="$@" 13 | 14 | PAGE_SIZE=$(sysctl -n hw.pagesize) 15 | 16 | { 17 | # create template 18 | for obj in $OBJS; 19 | do 20 | echo "\t\t. = ALIGN($PAGE_SIZE);" 21 | echo "\t\t${obj}ALIGNSECTION" 22 | done 23 | echo OBJECTS 24 | cat $LDSCRIPT 25 | } | 26 | sed "$(cat < 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use File::Find; 21 | 22 | find(\&wanted, "/usr/src/regress"); 23 | 24 | my $prevdir; 25 | sub wanted { 26 | return unless m{^Makefile$}; 27 | if ($prevdir && $File::Find::dir !~ m{^\Q$prevdir\E/}) { 28 | $prevdir =~ s{^/usr/src/regress/}{}; 29 | print $prevdir, "\n"; 30 | } 31 | $prevdir = $File::Find::dir; 32 | } 33 | $prevdir =~ s{^/usr/src/regress/}{}; 34 | print $prevdir, "\n" if $prevdir; 35 | -------------------------------------------------------------------------------- /once.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (c) 2018-2023 Alexander Bluhm 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | use strict; 18 | use warnings; 19 | use Cwd; 20 | use Date::Parse; 21 | use File::Basename; 22 | use Getopt::Std; 23 | use POSIX; 24 | 25 | use lib dirname($0); 26 | use Logcmd; 27 | use Hostctl; 28 | 29 | my $now = strftime("%FT%TZ", gmtime); 30 | my $scriptname = "$0 @ARGV"; 31 | 32 | my @allkernelmodes = qw(align gap sort reorder reboot keep); 33 | my @allmodifymodes = qw(nolro nopf notso pfsync); 34 | my @alltestmodes = qw( 35 | all net tcp udp make fs iperf tcpbench udpbench iperftcp 36 | iperfudp net4 tcp4 udp4 iperf4 tcpbench4 udpbench4 iperftcp4 iperfudp4 37 | net6 tcp6 udp6 iperf6 tcpbench6 udpbench6 iperftcp6 iperfudp6 38 | localnet localnet4 localnet6 39 | linuxnet linuxiperftcp4 linuxiperftcp6 40 | forward forward4 forward6 41 | relay relay4 relay6 42 | frag frag4 frag6 43 | splice splice4 splice6 44 | tcpsplice tcpsplice4 tcpsplice6 45 | udpsplice udpsplice4 udpsplice6 46 | ipsec ipsec4 ipsec6 ipsec44 ipsec46 ipsec64 ipsec66 47 | veb veb4 veb6 vbridge vbridge4 vbridge6 vport vport4 vport6 48 | ); 49 | 50 | my %opts; 51 | getopts('b:d:D:h:k:m:N:nP:pr:v', \%opts) or do { 52 | print STDERR <<"EOF"; 53 | usage: once.pl [-npv] [-b kstack] [-d date] [-D cvsdate] -h host [-k kernel] 54 | [-m modify] [-N repeat] [-P patch] [-r release] [test ...] 55 | -b kstack measure with btrace and create kernel stack map 56 | -d date set date string and change to sub directory, may be current 57 | -D cvsdate update sources from cvs to this date 58 | -h host user and host for performance test, user defaults to root 59 | -k kernel kernel mode: @allkernelmodes 60 | -m modify modify mode: @allmodifymodes 61 | -N repeat number of build, reboot, test repetitions per step 62 | -n do not generate gnuplot files on main release page 63 | -P patch apply patch to clean kernel source 64 | -p power down after testing 65 | -r release change to release sub directory 66 | -v verbose 67 | test ... test mode: @alltestmodes 68 | EOF 69 | exit(2); 70 | }; 71 | my $btrace = $opts{b}; 72 | !$btrace || $btrace eq "kstack" 73 | or die "Btrace -b '$btrace' not supported, use 'kstack'"; 74 | $opts{h} or die "No -h specified"; 75 | !$opts{d} || $opts{d} =~ /^(current|latest|latest-\w+)$/ || str2time($opts{d}) 76 | or die "Invalid -d date '$opts{d}'"; 77 | my $date = $opts{d}; 78 | my $cvsdate; 79 | if ($opts{D}) { 80 | my $cd = str2time($opts{D}) 81 | or die "Invalid -D cvsdate '$opts{D}'"; 82 | $cvsdate = strftime("%FT%TZ", gmtime($cd)); 83 | } 84 | my $patch = $opts{P}; 85 | $cvsdate && $patch 86 | and die "Cannot combine -D cvsdate and -P patch"; 87 | my $release; 88 | if ($opts{r} && $opts{r} ne "current") { 89 | ($release = $opts{r}) =~ /^\d+\.\d$/ 90 | or die "Release '$opts{r}' must be major.minor format"; 91 | } 92 | 93 | my $repeat = $opts{N}; 94 | !$repeat || $repeat >= 1 || $repeat =~ /^\d{3}$/ 95 | or die "Repeat -N repeat must be positive integer or three digit subdir"; 96 | !$opts{k} || grep { $_ eq $opts{k} } @allkernelmodes 97 | or die "Unknown kernel mode '$opts{k}'"; 98 | my %kernelmode; 99 | $kernelmode{$opts{k}} = 1 if $opts{k}; 100 | my $modify = $opts{m}; 101 | !$modify || grep { $_ eq $modify } @allmodifymodes 102 | or die "Unknown modify mode '$modify'"; 103 | 104 | my %testmode; 105 | foreach my $mode (@ARGV) { 106 | grep { $_ eq $mode } @alltestmodes 107 | or die "Unknown test mode '$mode'"; 108 | $testmode{$mode} = 1; 109 | } 110 | 111 | # better get an errno than random kill by SIGPIPE 112 | $SIG{PIPE} = 'IGNORE'; 113 | 114 | my $performdir = dirname($0). "/.."; 115 | chdir($performdir) 116 | or die "Change directory to '$performdir' failed: $!"; 117 | $performdir = getcwd(); 118 | my $resultdir = "$performdir/results"; 119 | if ($date && $date =~ /^(current|latest|latest-\w+)$/) { 120 | my $current = readlink("$resultdir/$date") 121 | or die "Read link '$resultdir/$date' failed: $!"; 122 | -d "$resultdir/$current" 123 | or die "Test directory '$resultdir/$current' failed: $!"; 124 | $date = basename($current); 125 | $release ||= dirname($current) if $date ne $current; 126 | } 127 | $resultdir .= "/$release" if $release; 128 | $resultdir .= "/$date" if $date; 129 | if ($date && $cvsdate) { 130 | $resultdir .= "/$cvsdate"; 131 | -d $resultdir || mkdir $resultdir 132 | or die "Make directory '$resultdir' failed: $!"; 133 | } 134 | if ($patch) { 135 | my $patchdir = "patch-". 136 | join(',', map { s,\.[^/]*$,,; basename($_) } split(/,/, $patch)); 137 | if ($kernelmode{keep}) { 138 | $resultdir = chdir_num("$resultdir/$patchdir"); 139 | } else { 140 | $resultdir = mkdir_num("$resultdir/$patchdir"); 141 | } 142 | } 143 | if ($modify) { 144 | $resultdir = mkdir_num("$resultdir/modify-$modify"); 145 | } 146 | chdir($resultdir) 147 | or die "Change directory to '$resultdir' failed: $!"; 148 | 149 | createlog(file => "once.log", verbose => $opts{v}); 150 | logmsg("$now Script '$scriptname' started.\n"); 151 | 152 | # setup remote machines 153 | 154 | usehosts(bindir => "$performdir/bin", date => $date, 155 | host => $opts{h}, verbose => $opts{v}); 156 | (my $host = $opts{h}) =~ s/.*\@//; 157 | 158 | # do not run end block until initialized, date may change later 159 | my $odate = $date; 160 | END { 161 | if ($odate) { 162 | bsdcons_hosts(cvsdate => $cvsdate, patch => $patch, modify => $modify, 163 | release => $release); 164 | relogdie(); 165 | } 166 | if ($performdir) { 167 | my @cmd = ("$performdir/bin/setup-html.pl"); 168 | system(@cmd); 169 | @cmd = ("$performdir/bin/running-html.pl"); 170 | system(@cmd); 171 | } 172 | }; 173 | powerup_hosts(cvsdate => $cvsdate, patch => $patch, modify => $modify, 174 | release => $release); 175 | if ($kernelmode{reboot}) { 176 | reboot_hosts(cvsdate => $cvsdate, patch => $patch, modify => $modify, 177 | release => $release, mode => \%kernelmode); 178 | } elsif (!$kernelmode{keep}) { 179 | cvsbuild_hosts(cvsdate => $cvsdate, patch => $patch, modify => $modify, 180 | release => $release, mode => \%kernelmode); 181 | } 182 | collect_version(); 183 | setup_html(); 184 | 185 | my @repeats; 186 | if ($repeat) { 187 | # use repeats subdirs only if there are any 188 | if ($repeat =~ /^\d{3}$/) { 189 | push @repeats, $repeat; 190 | } else { 191 | push @repeats, map { sprintf("%03d", $_) } (0 .. $repeat - 1); 192 | } 193 | } 194 | # after all regular repeats, make one with btrace turned on 195 | push @repeats, "btrace-$btrace" if $btrace; 196 | 197 | foreach my $repeatdir (@repeats ? @repeats : ".") { 198 | if (@repeats) { 199 | if ($repeatdir =~ /^btrace-/) { 200 | $repeatdir = mkdir_num($repeatdir); 201 | } else { 202 | mkdir $repeatdir 203 | or die "Make directory '$repeatdir' failed: $!"; 204 | } 205 | chdir($repeatdir) 206 | or die "Change directory to '$repeatdir' failed: $!"; 207 | } 208 | 209 | # run performance tests remotely 210 | 211 | my @sshcmd = ('ssh', $opts{h}, 'perl', '/root/perform/perform.pl'); 212 | push @sshcmd, '-b', $btrace if $repeatdir =~ /^btrace-/; 213 | push @sshcmd, '-e', "/root/perform/env-$host.sh"; 214 | push @sshcmd, '-m', $modify if $modify; 215 | push @sshcmd, '-v' if $opts{v}; 216 | push @sshcmd, keys %testmode; 217 | logcmd(@sshcmd); 218 | 219 | # get result and logs 220 | 221 | collect_result("$opts{h}:/root/perform"); 222 | 223 | if (@repeats) { 224 | # align and sort do not change kernel image randomly at each reboot. 225 | # This has been done by cvsbuild_hosts(), avoid doing it again. 226 | my %rebootmode = %kernelmode; 227 | delete @rebootmode{qw(align sort)}; 228 | 229 | unless ($rebootmode{keep} || $repeatdir eq $repeats[-1]) { 230 | reboot_hosts(cvsdate => $cvsdate, patch => $patch, 231 | modify => $modify, repeatdir => $repeatdir, 232 | release => $release, mode => \%rebootmode); 233 | } 234 | collect_version(); 235 | setup_html(); 236 | chdir("..") 237 | or die "Change directory to '..' failed: $!"; 238 | } 239 | collect_dmesg(); 240 | setup_html(); 241 | } 242 | powerdown_hosts(cvsdate => $cvsdate, patch => $patch, modify => $modify, 243 | release => $release) if $opts{p}; 244 | bsdcons_hosts(cvsdate => $cvsdate, patch => $patch, modify => $modify, 245 | release => $release); 246 | undef $odate; 247 | 248 | # create html output 249 | 250 | chdir($performdir) 251 | or die "Change directory to '$performdir' failed: $!"; 252 | 253 | if ($date) { 254 | setup_html(date => 1); 255 | my @cmd = ("bin/perform-html.pl", "-d", $date); 256 | push @cmd, "-n" if $opts{n}; 257 | push @cmd, "-r", $release if $release; 258 | push @cmd, "-v" if $opts{v}; 259 | runcmd(@cmd); 260 | 261 | unlink("results/latest"); 262 | symlink($release ? "$release/$date" : $date, "results/latest") 263 | or die "Make symlink 'results/latest' failed: $!"; 264 | } 265 | 266 | $now = strftime("%FT%TZ", gmtime); 267 | logmsg("$now Script '$scriptname' finished.\n"); 268 | 269 | exit; 270 | 271 | sub mkdir_num { 272 | my ($path) = @_; 273 | 274 | $path =~ s,\.[^/]*$,,; 275 | my $dir; 276 | for (my $suffix = 0; $suffix < 10; $suffix++) { 277 | $dir = "$path.$suffix"; 278 | if (mkdir($dir)) { 279 | return $dir; 280 | } else { 281 | $!{EEXIST} 282 | or die "Make directory '$dir' failed: $!"; 283 | } 284 | } 285 | die "Make directory '$dir' failed: $!"; 286 | } 287 | 288 | sub chdir_num { 289 | my ($path) = @_; 290 | 291 | $path =~ s,\.[^/]*$,,; 292 | my $dir; 293 | for (my $suffix = 9; $suffix >= 0; $suffix--) { 294 | $dir = "$path.$suffix"; 295 | if (chdir($dir)) { 296 | return $dir; 297 | } else { 298 | $!{ENOENT} 299 | or die "Change directory '$dir' failed: $!"; 300 | } 301 | } 302 | die "Change directory '$dir' failed: $!"; 303 | } 304 | -------------------------------------------------------------------------------- /pkg-alpine.list: -------------------------------------------------------------------------------- 1 | apk-tools 2 | bash 3 | binutils 4 | bsd-compat-headers 5 | busybox 6 | bzip2 7 | ca-certificates 8 | docs 9 | ethtool 10 | gcc 11 | ifupdown-ng 12 | iperf3 13 | iproute2 14 | iputils 15 | kmod 16 | libbsd 17 | libbsd-dev 18 | libevent 19 | libevent-dev 20 | linux-headers 21 | linux-virt-dev 22 | make 23 | man-pages 24 | mandoc 25 | musl-dev 26 | net-tools 27 | openntpd 28 | openrc 29 | openssh 30 | openssl 31 | pkgconf 32 | rsync 33 | tcpdump 34 | util-linux 35 | wget 36 | wireguard-tools 37 | xz 38 | zlib 39 | -------------------------------------------------------------------------------- /pkg-debian.list: -------------------------------------------------------------------------------- 1 | adduser 2 | bash 3 | binutils 4 | bsdextrautils 5 | bsdutils 6 | bzip2 7 | ca-certificates 8 | gcc 9 | gzip 10 | hping3 11 | ifupdown 12 | inetutils-ftp 13 | inetutils-ftpd 14 | inetutils-inetd 15 | inetutils-telnet 16 | inetutils-tools 17 | inetutils-traceroute 18 | iproute2 19 | iputils-arping 20 | iputils-clockdiff 21 | iputils-ping 22 | iputils-tracepath 23 | libbsd-dev 24 | libevent-dev 25 | make 26 | manpages 27 | netcat-openbsd 28 | nvi 29 | openntpd 30 | perl 31 | pkgconf 32 | qemu-guest-agent 33 | rsync 34 | tcpbench 35 | tcpdump 36 | tmux 37 | traceroute 38 | vim-tiny 39 | wget 40 | wireguard 41 | xz-utils 42 | -------------------------------------------------------------------------------- /pkg-ot1.list: -------------------------------------------------------------------------------- 1 | bc-gh 2 | botan2 3 | bzip2 4 | c2sp-testvectors 5 | diffstat 6 | exabgp 7 | git 8 | gmake 9 | go 10 | gsed 11 | iperf3 12 | net-snmp 13 | openldap-client-- 14 | openssl%1.1 15 | openssl%3.0 16 | openssl%3.1 17 | openssl%3.2 18 | openssl%3.3 19 | openssl-ruby-tests 20 | os-test 21 | p5-AnyEvent 22 | p5-BSD-Resource 23 | p5-BSD-Socket-Splice 24 | p5-BSD-arc4random 25 | p5-File-Slurp 26 | p5-Hash-Merge 27 | p5-IO-Socket-INET6 28 | p5-IO-Socket-SSL 29 | p5-Net-Flow 30 | p5-Net-Pcap 31 | p5-NetPacket 32 | p5-YAML 33 | p5-ldap 34 | posixtestsuite 35 | py3-tlsfuzzer 36 | rsync-- 37 | rsyslog 38 | rust 39 | rust-openssl-tests 40 | scapy 41 | sudo-- 42 | sysclean 43 | ucspi-tcp 44 | wycheproof-testvectors 45 | xz 46 | -------------------------------------------------------------------------------- /pkg-ot10.list: -------------------------------------------------------------------------------- 1 | bc-gh 2 | botan2 3 | bzip2 4 | c2sp-testvectors 5 | diffstat 6 | exabgp 7 | git 8 | gmake 9 | go 10 | gsed 11 | iperf3 12 | net-snmp 13 | openldap-client-- 14 | openssl%1.1 15 | openssl%3.0 16 | openssl%3.1 17 | openssl-ruby-tests 18 | os-test 19 | p5-AnyEvent 20 | p5-BSD-Resource 21 | p5-BSD-Socket-Splice 22 | p5-BSD-arc4random 23 | p5-File-Slurp 24 | p5-Hash-Merge 25 | p5-IO-Socket-INET6 26 | p5-IO-Socket-SSL 27 | p5-Net-Flow 28 | p5-Net-Pcap 29 | p5-NetPacket 30 | p5-YAML 31 | p5-ldap 32 | posixtestsuite 33 | py3-tlsfuzzer 34 | raspberrypi-firmware 35 | rsync-- 36 | rsyslog 37 | rust 38 | rust-openssl-tests 39 | scapy 40 | sudo-- 41 | sysclean 42 | u-boot-aarch64 43 | ucspi-tcp 44 | wycheproof-testvectors 45 | xz 46 | -------------------------------------------------------------------------------- /pkg-ot12.list: -------------------------------------------------------------------------------- 1 | bc-gh 2 | bzip2 3 | diffstat 4 | fs_mark 5 | git 6 | gmake 7 | iperf 8 | iperf3 9 | rsync-- 10 | sysclean 11 | xz 12 | -------------------------------------------------------------------------------- /pkg-ot14.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | fs_mark 4 | git 5 | gmake 6 | iperf 7 | iperf3 8 | rsync-- 9 | sysclean 10 | xz 11 | -------------------------------------------------------------------------------- /pkg-ot15.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | fs_mark 4 | git 5 | gmake 6 | iperf 7 | iperf3 8 | rsync-- 9 | sysclean 10 | xz 11 | -------------------------------------------------------------------------------- /pkg-ot19.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot2.list: -------------------------------------------------------------------------------- 1 | bc-gh 2 | botan2 3 | bzip2 4 | c2sp-testvectors 5 | diffstat 6 | exabgp 7 | git 8 | gmake 9 | go 10 | gsed 11 | iperf3 12 | net-snmp 13 | openldap-client-- 14 | openssl%1.1 15 | openssl%3.0 16 | openssl%3.1 17 | openssl-ruby-tests 18 | os-test 19 | p5-AnyEvent 20 | p5-BSD-Resource 21 | p5-BSD-Socket-Splice 22 | p5-BSD-arc4random 23 | p5-File-Slurp 24 | p5-Hash-Merge 25 | p5-IO-Socket-INET6 26 | p5-IO-Socket-SSL 27 | p5-Net-Flow 28 | p5-Net-Pcap 29 | p5-NetPacket 30 | p5-YAML 31 | p5-ldap 32 | posixtestsuite 33 | py3-tlsfuzzer 34 | rsync-- 35 | rsyslog 36 | rust 37 | rust-openssl-tests 38 | scapy 39 | sudo-- 40 | sysclean 41 | ucspi-tcp 42 | wycheproof-testvectors 43 | xz 44 | -------------------------------------------------------------------------------- /pkg-ot31.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | fs_mark 4 | git 5 | gmake 6 | iperf 7 | iperf3 8 | rsync-- 9 | splicebench 10 | sysclean 11 | udpbench 12 | xz 13 | -------------------------------------------------------------------------------- /pkg-ot32.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | fs_mark 4 | git 5 | gmake 6 | iperf 7 | iperf3 8 | rsync-- 9 | splicebench 10 | sysclean 11 | udpbench 12 | xz 13 | -------------------------------------------------------------------------------- /pkg-ot33.list: -------------------------------------------------------------------------------- 1 | bc-gh 2 | botan2 3 | bzip2 4 | c2sp-testvectors 5 | diffstat 6 | exabgp 7 | git 8 | gmake 9 | go 10 | gsed 11 | iperf3 12 | net-snmp 13 | openldap-client-- 14 | openssl%1.1 15 | openssl%3.0 16 | openssl%3.1 17 | openssl%3.2 18 | openssl%3.3 19 | openssl-ruby-tests 20 | os-test 21 | p5-AnyEvent 22 | p5-BSD-Resource 23 | p5-BSD-Socket-Splice 24 | p5-BSD-arc4random 25 | p5-File-Slurp 26 | p5-Hash-Merge 27 | p5-IO-Socket-INET6 28 | p5-IO-Socket-SSL 29 | p5-Net-Flow 30 | p5-Net-Pcap 31 | p5-NetPacket 32 | p5-YAML 33 | p5-ldap 34 | posixtestsuite 35 | py3-tlsfuzzer 36 | rsync-- 37 | rsyslog 38 | rust 39 | rust-openssl-tests 40 | scapy 41 | sudo-- 42 | sysclean 43 | ucspi-tcp 44 | wycheproof-testvectors 45 | xz 46 | -------------------------------------------------------------------------------- /pkg-ot4.list: -------------------------------------------------------------------------------- 1 | bc-gh 2 | bzip2 3 | diffstat 4 | iperf3 5 | rsync-- 6 | sysclean 7 | xz 8 | -------------------------------------------------------------------------------- /pkg-ot41.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot42.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot48.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot50.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | sysclean 6 | udpbench 7 | xz 8 | -------------------------------------------------------------------------------- /pkg-ot51.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | sysclean 6 | udpbench 7 | xz 8 | -------------------------------------------------------------------------------- /pkg-ot57.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot6.list: -------------------------------------------------------------------------------- 1 | bc-gh 2 | botan2 3 | bzip2 4 | c2sp-testvectors 5 | diffstat 6 | exabgp 7 | git 8 | gmake 9 | go 10 | gsed 11 | iperf3 12 | net-snmp 13 | openldap-client-- 14 | openssl%1.1 15 | openssl%3.0 16 | openssl%3.1 17 | openssl-ruby-tests 18 | os-test 19 | p5-AnyEvent 20 | p5-BSD-Resource 21 | p5-BSD-Socket-Splice 22 | p5-BSD-arc4random 23 | p5-File-Slurp 24 | p5-Hash-Merge 25 | p5-IO-Socket-INET6 26 | p5-IO-Socket-SSL 27 | p5-Net-Flow 28 | p5-Net-Pcap 29 | p5-NetPacket 30 | p5-YAML 31 | p5-ldap 32 | posixtestsuite 33 | py3-tlsfuzzer 34 | rsync-- 35 | rsyslog 36 | rust 37 | rust-openssl-tests 38 | scapy 39 | sudo-- 40 | sysclean 41 | ucspi-tcp 42 | wycheproof-testvectors 43 | xz 44 | -------------------------------------------------------------------------------- /pkg-ot62.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot71.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot72.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot73.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot74.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot81.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot91.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot92.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot93.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /pkg-ot94.list: -------------------------------------------------------------------------------- 1 | bzip2 2 | diffstat 3 | iperf3 4 | rsync-- 5 | splicebench 6 | sysclean 7 | udpbench 8 | xz 9 | -------------------------------------------------------------------------------- /plot.gp: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/gnuplot 2 | 3 | # Copyright (c) 2018-2019 Moritz Buhl 4 | # Copyright (c) 2020 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | # plot test results, the following variables are required: 19 | # DATA_FILE Path, plot data file, space separated, 20 | # format: "test subtest run checkout repeat value unit" 21 | # PREFIX Path, png output file 22 | # TESTS String, testnames to filter and plot, space separated, 23 | # format: "test1 subtest1 test2 sub2 ... testN subN" 24 | # 25 | # The following variables are optional: 26 | # QUIRKS String, format: "date1 descr1 date2 descr2 ... dateN descrN" 27 | # RUN_DATE UNIX time stamp, filter for a "run" value 28 | # TITLE String, plot title 29 | # UNIT String, unit for the y-axis 30 | 31 | if (!exists("DATA_FILE") || !exists("PREFIX") || !exists("TESTS")) { 32 | exit error "Please define DATA_FILE, PREFIX and TESTS." 33 | exit status 1 34 | } 35 | 36 | set datafile separator whitespace 37 | 38 | if (!exists("TITLE")) { TITLE = "" } 39 | if (!exists("UNIT")) { UNIT = "" } 40 | if (!exists("QUIRKS")) { QUIRKS = "" } 41 | if (!exists("LATEX")) { LATEX = 0 } 42 | 43 | if (exists("RUN_DATE")) { 44 | stats DATA_FILE using 4:(strcol(3) eq RUN_DATE? $6:NaN) nooutput 45 | } else { 46 | stats DATA_FILE using 4:6 nooutput 47 | } 48 | 49 | # If there are not data points, create an empty image to prevent future gnuplot 50 | # invocations. To prevent warnings, set most style settings after this check. 51 | if (!exists("STATS_records")) { 52 | set terminal png size 240,80 53 | set title TITLE."\nNO DATA" offset first 0,0 54 | set yrange [-1:1] 55 | unset tics 56 | unset border 57 | plot 0 lc rgb 'white' 58 | exit 59 | } 60 | 61 | # work around min == max 62 | if (!exists("XRANGE_MIN")) { XRANGE_MIN = STATS_min_x - 1 } 63 | if (!exists("XRANGE_MAX")) { XRANGE_MAX = STATS_max_x + 1 } 64 | if (!exists("YRANGE_MIN")) { YRANGE_MIN = 0 } 65 | if (!exists("YRANGE_MAX")) { YRANGE_MAX = STATS_max_y + 1 } 66 | 67 | set xrange[XRANGE_MIN : XRANGE_MAX] 68 | set yrange[YRANGE_MIN : YRANGE_MAX] 69 | set title TITLE 70 | set ylabel UNIT 71 | set format x "%Y-%m-%d" 72 | set timefmt "%s" 73 | set xdata time 74 | set xlabel "Checkout (date)" 75 | set tics out 76 | set border 3 77 | if (LATEX) { 78 | set output PREFIX.".tex" 79 | set terminal epslatex color size 10.5, 5 80 | } else { 81 | set output PREFIX.".png" 82 | set terminal png transparent size 1360, 768 83 | set style textbox opaque noborder fillcolor rgb "white" 84 | } 85 | unset key 86 | 87 | # draw quirks 88 | lbl_index = 65 89 | descr_suffix = "" 90 | do for [i = 1:words(QUIRKS)] { 91 | XPOS = (0.0+int(word(QUIRKS, i))-XRANGE_MIN)/(XRANGE_MAX-XRANGE_MIN) 92 | if (XPOS > 0 && XPOS < 1) { 93 | DESCR = sprintf("%c%s", lbl_index, descr_suffix) 94 | set arrow from graph XPOS,0 to graph XPOS,1 nohead lw 1 lc rgb 'black' 95 | set label DESCR at graph XPOS, graph 1 noenhanced \ 96 | offset character -.5, character 0.7 front boxed 97 | } 98 | if (lbl_index == 90) { # jump from Z to a 99 | lbl_index = lbl_index + 6 100 | } 101 | lbl_index = lbl_index + 1 102 | 103 | if (lbl_index == 123) { # jump from z to A' 104 | lbl_index = 65 105 | descr_suffix = descr_suffix . "'" 106 | } 107 | } 108 | 109 | # draw complete plot 110 | if (exists("RUN_DATE")) { 111 | plot for [test = 1:words(TESTS):2] DATA_FILE using 4:( \ 112 | strcol(3) eq RUN_DATE? ( \ 113 | strcol(1) eq word(TESTS,test)? ( \ 114 | strcol(2) eq word(TESTS,test+1)? $6:NaN \ 115 | ):NaN \ 116 | ):NaN \ 117 | ) with points lc test/2+1 pt test/2+1 118 | } else { 119 | plot for [test = 1:words(TESTS):2] DATA_FILE using 4:( \ 120 | strcol(1) eq word(TESTS,test)? ( \ 121 | strcol(2) eq word(TESTS,test+1)? $6:NaN \ 122 | ):NaN \ 123 | ) with points lc test/2+1 pt test/2+1 124 | } 125 | 126 | if (LATEX) { 127 | exit 128 | } 129 | 130 | # draw frame 131 | set output PREFIX."_0.png" 132 | plot 0 notitle lc bgnd 133 | 134 | # draw data 135 | set title tc bgnd 136 | set xtics tc bgnd 137 | set ytics tc bgnd 138 | set xlabel tc bgnd 139 | set ylabel tc bgnd 140 | set border lc bgnd 141 | unset border 142 | unset arrow 143 | unset label 144 | 145 | do for [test = 1:words(TESTS):2] { 146 | i = test/2+1 147 | set output PREFIX."_".i.".png" 148 | if (exists("RUN_DATE")) { 149 | plot DATA_FILE using 4:( \ 150 | strcol(3) eq RUN_DATE? ( \ 151 | strcol(1) eq word(TESTS,test)? ( \ 152 | strcol(2) eq word(TESTS,test+1)? $6:NaN \ 153 | ):NaN \ 154 | ):NaN \ 155 | ) with points lc i pt i 156 | } else { 157 | plot DATA_FILE using 4:( \ 158 | strcol(1) eq word(TESTS,test)? ( \ 159 | strcol(2) eq word(TESTS,test+1)? $6:NaN \ 160 | ):NaN \ 161 | ) with points lc i pt i 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /portstest.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (c) 2016-2020 Alexander Bluhm 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | use strict; 18 | use warnings; 19 | use Cwd; 20 | use Fcntl qw(SEEK_SET); 21 | use File::Basename; 22 | use Getopt::Std; 23 | use POSIX; 24 | use Time::HiRes; 25 | 26 | my %opts; 27 | getopts('e:t:v', \%opts) or do { 28 | print STDERR <<"EOF"; 29 | usage: portstest.pl [-v] [-e environment] [-t timeout] [test ...] 30 | -e environ parse environment for tests from shell script 31 | -t timeout timeout for a single test, default 1 hour 32 | -v verbose 33 | test ... explicit test list, default ports.list file 34 | EOF 35 | exit(2); 36 | }; 37 | my $timeout = $opts{t} || 60*60; 38 | environment($opts{e}) if $opts{e}; 39 | 40 | my $dir = dirname($0); 41 | chdir($dir) 42 | or die "Change directory to '$dir' failed: $!"; 43 | my $portstestdir = getcwd(); 44 | 45 | # write summary of results into result file 46 | open(my $tr, '>', "test.result") 47 | or die "Open 'test.result' for writing failed: $!"; 48 | $tr->autoflush(); 49 | $| = 1; 50 | 51 | # get ports list from command line or input file 52 | my @tests; 53 | if (@ARGV) { 54 | @tests = @ARGV; 55 | } else { 56 | open(my $tl, '<', "ports.list") 57 | or die "Open 'ports.list' for reading failed: $!"; 58 | chomp(@tests = grep { ! /^#/ && ! /^\s*$/ } <$tl>); 59 | close($tl) 60 | or die "Close 'ports.list' after reading failed: $!"; 61 | } 62 | 63 | sub bad { 64 | my ($prev, $test, $reason, $message, $log) = @_; 65 | my $nl = ""; 66 | $nl = "\n" if $prev ne ""; 67 | print $log "${nl}$reason\t$test\t$message\n" if $log; 68 | print "${nl}$reason\t$test\t$message\n\n" if $opts{v}; 69 | print $tr "$reason\t$test\t$message\n"; 70 | $log->sync() if $log; 71 | $tr->sync(); 72 | no warnings 'exiting'; 73 | next; 74 | } 75 | 76 | sub good { 77 | my ($prev, $test, $diff, $log) = @_; 78 | my $nl = ""; 79 | $nl = "\n" if $prev ne ""; 80 | my $duration = sprintf("%dm%02d.%02ds", $diff/60, $diff%60, 100*$diff%100); 81 | print $log "${nl}PASS\t$test\tDuration $duration\n" if $log; 82 | print "${nl}PASS\t$test\tDuration $duration\n\n" if $opts{v}; 83 | print $tr "PASS\t$test\tDuration $duration\n"; 84 | $log->sync() if $log; 85 | $tr->sync(); 86 | } 87 | 88 | my @paxcmd = ('pax', '-wzf', "$dir/test.log.tgz", '-s,^/usr/ports/,,'); 89 | open(my $pax, '|-', @paxcmd) 90 | or die "Open pipe to '@paxcmd' failed: $!"; 91 | $pax->autoflush(); 92 | my $paxlog; 93 | 94 | # run make test for each port 95 | foreach my $test (@tests) { 96 | print $pax $paxlog if $paxlog; 97 | undef $paxlog; 98 | 99 | my $prev = ""; 100 | my $begin = Time::HiRes::time(); 101 | my $date = strftime("%FT%TZ", gmtime($begin)); 102 | print "\nSTART\t$test\t$date\n\n" if $opts{v}; 103 | 104 | $dir = "/usr/ports/$test"; 105 | chdir($dir) 106 | or bad $prev, $test, 'NOEXIST', "Change directory to '$dir' failed: $!"; 107 | 108 | # write make output into log file 109 | open(my $log, '>', "make.log") 110 | or bad $prev, $test, 'NOLOG', "Open 'make.log' for writing failed: $!"; 111 | $log->autoflush(); 112 | $paxlog = "$dir/make.log\n"; 113 | 114 | my sub runcmd { 115 | my ($reason, @cmd) = @_; 116 | 117 | $log->truncate(0); 118 | $log->seek(0, SEEK_SET); 119 | print $log "START\t$test\t$date\n\n"; 120 | $log->sync(); 121 | 122 | defined(my $pid = open(my $out, '-|')) 123 | or bad $prev, $test, 'NORUN', "Open pipe from '@cmd' failed: $!", 124 | $log; 125 | if ($pid == 0) { 126 | close($out); 127 | open(STDIN, '<', "/dev/null") 128 | or warn "Redirect stdin to /dev/null failed: $!"; 129 | open(STDERR, '>&', \*STDOUT) 130 | or warn "Redirect stderr to stdout failed: $!"; 131 | setsid() 132 | or warn "Setsid $$ failed: $!"; 133 | exec(@cmd); 134 | warn "Exec '@cmd' failed: $!"; 135 | _exit(126); 136 | } 137 | eval { 138 | local $SIG{ALRM} = sub { die "Test running too long, aborted.\n" }; 139 | alarm($timeout); 140 | while (<$out>) { 141 | print $log $_; 142 | s/[^\s[:print:]]/_/g; 143 | print if $opts{v}; 144 | chomp($prev = $_); 145 | } 146 | alarm(0); 147 | }; 148 | kill 'KILL', -$pid; 149 | if ($@) { 150 | chomp($@); 151 | bad $prev, $test, 'NOTERM', $@, $log; 152 | } 153 | close($out) 154 | or bad $prev, $test, $reason, $! ? 155 | "Close pipe from '@cmd' failed: $!" : 156 | "Command '@cmd' failed: $?", $log; 157 | } 158 | runcmd('NOCLEAN', qw(make unlock clean)); 159 | runcmd('SKIP', qw(make fetch)); 160 | runcmd('NOEXIT', qw(make build)); 161 | runcmd('FAIL', qw(make test)); 162 | 163 | my $end = Time::HiRes::time(); 164 | good $prev, $test, $end - $begin, $log; 165 | 166 | close($log) 167 | or die "Close 'make.log' after writing failed: $!"; 168 | } 169 | 170 | print $pax $paxlog if $paxlog; 171 | close($pax) or die $! ? 172 | "Close pipe to '@paxcmd' failed: $!" : 173 | "Command '@paxcmd' failed: $?"; 174 | 175 | close($tr) 176 | or die "Close 'test.result' after writing failed: $!"; 177 | 178 | exit; 179 | 180 | # parse shell script that is setting environment for some tests 181 | # FOO=bar 182 | # FOO="bar" 183 | # export FOO=bar 184 | # export FOO BAR 185 | sub environment { 186 | my $file = shift; 187 | 188 | open(my $fh, '<', $file) 189 | or die "Open '$file' for reading failed: $!"; 190 | while (<$fh>) { 191 | chomp; 192 | s/#.*$//; 193 | s/\s+$//; 194 | s/^export\s+(?=\w+=)//; 195 | s/^export\s+\w+.*//; 196 | next if /^$/; 197 | if (/^(\w+)=(\S+)$/ or /^(\w+)="([^"]*)"/ or /^(\w+)='([^']*)'/) { 198 | $ENV{$1}=$2; 199 | } else { 200 | die "Unknown environment line in '$file': $_"; 201 | } 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /power.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # power up and down machine to save cooling power 3 | 4 | # Copyright (c) 2018-2023 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use Date::Parse; 22 | use File::Basename; 23 | use Getopt::Std; 24 | use POSIX; 25 | 26 | use lib dirname($0); 27 | use Logcmd; 28 | use Machine; 29 | 30 | my $now = strftime("%FT%TZ", gmtime); 31 | my $scriptname = "$0 @ARGV"; 32 | 33 | my @allpowermodes = qw(down up); 34 | 35 | my %opts; 36 | getopts('d:D:h:m:P:R:r:v', \%opts) or do { 37 | print STDERR <<"EOF"; 38 | usage: power.pl [-v] [-d date] [-D cvsdate] -h host [-m modify] [-P patch] 39 | [-R repeatdir] [-r release] power 40 | -d date set date string and change to sub directory, may be current 41 | -D cvsdate update sources from cvs to this date 42 | -h host root\@openbsd-test-machine, login per ssh 43 | -m modify modify mode 44 | -P patch patch name 45 | -R repdir repetition number or btrace 46 | -r release change to release sub directory 47 | -v verbose 48 | power power mode: @allpowermodes 49 | down shutdown and power off machine 50 | up machine is up or power cycle 51 | EOF 52 | exit(2); 53 | }; 54 | $opts{h} or die "No -h specified"; 55 | !$opts{d} || $opts{d} eq "current" || str2time($opts{d}) 56 | or die "Invalid -d date '$opts{d}'"; 57 | my $date = $opts{d}; 58 | !$opts{D} || str2time($opts{D}) 59 | or die "Invalid -D cvsdate '$opts{D}'"; 60 | my $cvsdate = $opts{D}; 61 | my $patch = $opts{P}; 62 | my $modify = $opts{m}; 63 | !$opts{R} || $opts{R} =~ /^\d{3}$/ 64 | or die "Invalid -R repeatdir '$opts{R}'"; 65 | my $repeatdir = $opts{R}; 66 | my $release; 67 | if ($opts{r} && $opts{r} ne "current") { 68 | ($release = $opts{r}) =~ /^\d+\.\d$/ 69 | or die "Release '$opts{r}' must be major.minor format"; 70 | } 71 | 72 | @ARGV or die "No mode specified"; 73 | my %mode; 74 | foreach my $mode (@ARGV) { 75 | grep { $_ eq $mode } @allpowermodes 76 | or die "Unknown power mode '$mode'"; 77 | $mode{$mode} = 1; 78 | } 79 | foreach my $mode (@allpowermodes) { 80 | die "Power mode '$mode' must be used solely" 81 | if $mode{$mode} && keys %mode != 1; 82 | } 83 | 84 | my $performdir = dirname($0). "/.."; 85 | chdir($performdir) 86 | or die "Change directory to '$performdir' failed: $!"; 87 | $performdir = getcwd(); 88 | my $resultdir = "$performdir/results"; 89 | $resultdir .= "/$release" if $release; 90 | if ($date && $date eq "current") { 91 | my $current = readlink("$resultdir/$date") 92 | or die "Read link '$resultdir/$date' failed: $!"; 93 | -d "$resultdir/$current" 94 | or die "Test directory '$resultdir/$current' failed: $!"; 95 | $date = $current; 96 | } 97 | $resultdir .= "/$date" if $date; 98 | $resultdir .= "/$cvsdate" if $date && $cvsdate; 99 | if ($patch) { 100 | my $patchdir = "patch-". 101 | join(',', map { s,\.[^/]*,,; basename($_) } split(/,/, $patch)); 102 | my $dir = "$resultdir/$patchdir.[0-9]"; 103 | $resultdir = (glob($dir))[-1] 104 | or die "Patch directory '$dir' not found"; 105 | } 106 | if ($modify) { 107 | my $dir = "$resultdir/modify-$modify.[0-9]"; 108 | $resultdir = (glob($dir))[-1] 109 | or die "Modify directory '$dir' not found"; 110 | } 111 | $resultdir .= "/$repeatdir" if $repeatdir; 112 | chdir($resultdir) 113 | or die "Change directory to '$resultdir' failed: $!"; 114 | 115 | my ($user, $host) = split('@', $opts{h}, 2); 116 | ($user, $host) = ("root", $user) unless $host; 117 | 118 | createlog(file => "power-$host.log", verbose => $opts{v}); 119 | logmsg("$now Script '$scriptname' started.\n"); 120 | 121 | createhost($user, $host); 122 | 123 | # execute commands 124 | 125 | power_down() if $mode{down}; 126 | power_up() if $mode{up}; 127 | 128 | # finish power log 129 | 130 | $now = strftime("%FT%TZ", gmtime); 131 | logmsg("$now Script '$scriptname' finished.\n"); 132 | 133 | exit; 134 | -------------------------------------------------------------------------------- /reboot.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # reboot machine for repeated performance test 3 | 4 | # Copyright (c) 2018-2023 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use Date::Parse; 22 | use File::Basename; 23 | use Getopt::Std; 24 | use POSIX; 25 | 26 | use lib dirname($0); 27 | use Logcmd; 28 | use Machine; 29 | 30 | my $now = strftime("%FT%TZ", gmtime); 31 | my $scriptname = "$0 @ARGV"; 32 | 33 | my @allkernelmodes = qw(align gap sort reorder reboot); 34 | 35 | my %opts; 36 | getopts('d:D:h:m:P:R:r:v', \%opts) or do { 37 | print STDERR <<"EOF"; 38 | usage: reboot.pl [-v] [-d date] [-D cvsdate] -h host [-R repeatdir] 39 | [-r release] [kernel ...] 40 | -d date set date string and change to sub directory, may be current 41 | -D cvsdate update sources from cvs to this date 42 | -h host root\@openbsd-test-machine, login per ssh 43 | -m modify modify mode 44 | -P patch apply patch to clean kernel source, comma separated list 45 | -R repdir repetition number or btrace 46 | -r release change to release sub directory 47 | -v verbose 48 | kernel kenrel mode: @allkernelmodes 49 | align relink kernel aligning all object at page size, no randomness 50 | gap relink kernel sorting object files, but use random gap 51 | sort relink kernel sorting object files at fixed position 52 | reorder relink kernel using the reorder kernel script 53 | reboot reboot, this is always done 54 | EOF 55 | exit(2); 56 | }; 57 | $opts{h} or die "No -h specified"; 58 | !$opts{d} || $opts{d} eq "current" || str2time($opts{d}) 59 | or die "Invalid -d date '$opts{d}'"; 60 | my $date = $opts{d}; 61 | !$opts{D} || str2time($opts{D}) 62 | or die "Invalid -D cvsdate '$opts{D}'"; 63 | my $cvsdate = $opts{D}; 64 | my $patch = $opts{P}; 65 | my $modify = $opts{m}; 66 | !$opts{R} || $opts{R} =~ /^\d{3}$/ 67 | or die "Invalid -R repeatdir '$opts{R}'"; 68 | my $repeatdir = $opts{R}; 69 | my $release; 70 | if ($opts{r} && $opts{r} ne "current") { 71 | ($release = $opts{r}) =~ /^\d+\.\d$/ 72 | or die "Release '$opts{r}' must be major.minor format"; 73 | } 74 | 75 | my %kernelmode; 76 | foreach my $mode (@ARGV) { 77 | grep { $_ eq $mode } @allkernelmodes 78 | or die "Unknown kernel mode '$mode'"; 79 | $kernelmode{$mode} = 1; 80 | } 81 | 82 | my $performdir = dirname($0). "/.."; 83 | chdir($performdir) 84 | or die "Change directory to '$performdir' failed: $!"; 85 | $performdir = getcwd(); 86 | my $resultdir = "$performdir/results"; 87 | $resultdir .= "/$release" if $release; 88 | if ($date && $date eq "current") { 89 | my $current = readlink("$resultdir/$date") 90 | or die "Read link '$resultdir/$date' failed: $!"; 91 | -d "$resultdir/$current" 92 | or die "Test directory '$resultdir/$current' failed: $!"; 93 | $date = $current; 94 | } 95 | $resultdir .= "/$date" if $date; 96 | $resultdir .= "/$cvsdate" if $date && $cvsdate; 97 | if ($patch) { 98 | my $patchdir = "patch-". 99 | join(',', map { s,\.[^/]*,,; basename($_) } split(/,/, $patch)); 100 | my $dir = "$resultdir/$patchdir.[0-9]"; 101 | $resultdir = (glob($dir))[-1] 102 | or die "Patch directory '$dir' not found"; 103 | } 104 | if ($modify) { 105 | my $dir = "$resultdir/modify-$modify.[0-9]"; 106 | $resultdir = (glob($dir))[-1] 107 | or die "Modify directory '$dir' not found"; 108 | } 109 | $resultdir .= "/$repeatdir" if $repeatdir; 110 | chdir($resultdir) 111 | or die "Change directory to '$resultdir' failed: $!"; 112 | 113 | my ($user, $host) = split('@', $opts{h}, 2); 114 | ($user, $host) = ("root", $user) unless $host; 115 | 116 | createlog(file => "reboot-$host.log", verbose => $opts{v}); 117 | logmsg("$now Script '$scriptname' started.\n"); 118 | 119 | createhost($user, $host); 120 | 121 | # execute commands 122 | 123 | if ($kernelmode{align}) { 124 | align_kernel(); 125 | } elsif ($kernelmode{gap}) { 126 | gap_kernel(); 127 | } elsif ($kernelmode{sort}) { 128 | sort_kernel(); 129 | } 130 | reorder_kernel() if $kernelmode{align} || $kernelmode{gap} || 131 | $kernelmode{sort} || $kernelmode{reorder}; 132 | reboot(); 133 | get_version(); 134 | 135 | # finish reboot log 136 | 137 | $now = strftime("%FT%TZ", gmtime); 138 | logmsg("$now Script '$scriptname' finished.\n"); 139 | 140 | exit; 141 | -------------------------------------------------------------------------------- /regress.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (c) 2016-2022 Alexander Bluhm 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | use strict; 18 | use warnings; 19 | use Cwd; 20 | use File::Basename; 21 | use Getopt::Std; 22 | use POSIX; 23 | use Time::HiRes; 24 | 25 | my %opts; 26 | getopts('e:t:v', \%opts) or do { 27 | print STDERR <<"EOF"; 28 | usage: regress.pl [-v] [-e environment] [-t timeout] [test ...] 29 | -e environ parse environment for tests from shell script 30 | -t timeout timeout for a single test, default 1 hour 31 | -v verbose 32 | test ... explicit test list, default test.list file 33 | EOF 34 | exit(2); 35 | }; 36 | my $timeout = $opts{t} || 60*60; 37 | environment($opts{e}) if $opts{e}; 38 | 39 | my $dir = dirname($0); 40 | chdir($dir) 41 | or die "Change directory to '$dir' failed: $!"; 42 | my $regressdir = getcwd(); 43 | 44 | # write summary of results into result file 45 | open(my $tr, '>', "test.result") 46 | or die "Open 'test.result' for writing failed: $!"; 47 | $tr->autoflush(); 48 | $| = 1; 49 | 50 | # get test list from command line or input file 51 | my @tests; 52 | if (@ARGV) { 53 | @tests = @ARGV; 54 | } else { 55 | open(my $tl, '<', "test.list") 56 | or die "Open 'test.list' for reading failed: $!"; 57 | chomp(@tests = grep { ! /^#/ && ! /^\s*$/ } <$tl>); 58 | close($tl) 59 | or die "Close 'test.list' after reading failed: $!"; 60 | } 61 | 62 | # run sudo is if is set to get password in advance 63 | my @sudocmd = qw(make -s -f - sudo); 64 | open(my $sudo, '|-', @sudocmd) 65 | or die "Open pipe to '@sudocmd' failed: $!"; 66 | print $sudo "sudo:\n\t\${SUDO} true\n"; 67 | close($sudo) or die $! ? 68 | "Close pipe to '@sudocmd' failed: $!" : 69 | "Command '@sudocmd' failed: $?"; 70 | 71 | sub bad { 72 | my ($prev, $test, $reason, $message, $log) = @_; 73 | my $nl = ""; 74 | $nl = "\n" if $prev ne ""; 75 | print $log "${nl}$reason\t$test\t$message\n" if $log; 76 | print "${nl}$reason\t$test\t$message\n\n" if $opts{v}; 77 | print $tr "$reason\t$test\t$message\n"; 78 | $log->sync() if $log; 79 | $tr->sync(); 80 | no warnings 'exiting'; 81 | next; 82 | } 83 | 84 | sub good { 85 | my ($prev, $test, $diff, $log) = @_; 86 | my $nl = ""; 87 | $nl = "\n" if $prev ne ""; 88 | my $duration = sprintf("%dm%02d.%02ds", $diff/60, $diff%60, 100*$diff%100); 89 | print $log "${nl}PASS\t$test\tDuration $duration\n" if $log; 90 | print "${nl}PASS\t$test\tDuration $duration\n\n" if $opts{v}; 91 | print $tr "PASS\t$test\tDuration $duration\n"; 92 | $log->sync() if $log; 93 | $tr->sync(); 94 | } 95 | 96 | my @paxcmd = ('pax', '-wzf', "$regressdir/test.log.tgz", 97 | '-s,^/usr/src/regress/,,'); 98 | open(my $pax, '|-', @paxcmd) 99 | or die "Open pipe to '@paxcmd' failed: $!"; 100 | $pax->autoflush(); 101 | my $paxlog; 102 | 103 | # run make regress for each test 104 | foreach my $test (@tests) { 105 | print $pax $paxlog if $paxlog; 106 | undef $paxlog; 107 | 108 | my $prev = ""; 109 | my $begin = Time::HiRes::time(); 110 | my $date = strftime("%FT%TZ", gmtime($begin)); 111 | print "\nSTART\t$test\t$date\n\n" if $opts{v}; 112 | 113 | $dir = $test =~ m,^/, ? $test : "/usr/src/regress/$test"; 114 | chdir($dir) 115 | or bad $prev, $test, 'NOEXIST', "Change directory to '$dir' failed: $!"; 116 | 117 | my $cleancmd = "make clean"; 118 | $cleancmd .= " >/dev/null" unless $opts{v}; 119 | $cleancmd .= " 2>&1"; 120 | system($cleancmd) 121 | and bad $prev, $test, 'NOCLEAN', "Command '$cleancmd' failed: $?"; 122 | print "\n" if $opts{v}; 123 | 124 | # write make output into log file 125 | open(my $log, '>', "make.log") 126 | or bad $prev, $test, 'NOLOG', "Open 'make.log' for writing failed: $!"; 127 | $log->autoflush(); 128 | $paxlog = "$dir/make.log\n"; 129 | 130 | print $log "START\t$test\t$date\n\n"; 131 | $log->sync(); 132 | 133 | my $skipped = 0; 134 | my (@xfailed, @xpassed, @failed); 135 | my @runcmd = qw(make regress); 136 | defined(my $pid = open(my $out, '-|')) 137 | or bad $prev, $test, 'NORUN', "Open pipe from '@runcmd' failed: $!", 138 | $log; 139 | if ($pid == 0) { 140 | close($out); 141 | open(STDIN, '<', "/dev/null") 142 | or warn "Redirect stdin to /dev/null failed: $!"; 143 | open(STDERR, '>&', \*STDOUT) 144 | or warn "Redirect stderr to stdout failed: $!"; 145 | setsid() 146 | or warn "Setsid $$ failed: $!"; 147 | exec(@runcmd); 148 | warn "Exec '@runcmd' failed: $!"; 149 | _exit(126); 150 | } 151 | eval { 152 | local $SIG{ALRM} = sub { die "Test running too long, aborted.\n" }; 153 | alarm($timeout); 154 | while (<$out>) { 155 | print $log $_; 156 | s/[^\s[:print:]]/_/g; 157 | print if $opts{v}; 158 | push @failed, $prev, if /^FAILED$/; 159 | push @xpassed, $prev, if /^UNEXPECTED_PASS(ED)?$/; 160 | $skipped++ if /^SKIPPED$/; 161 | push @xfailed, $prev, if /^EXPECTED_FAIL(ED)?$/; 162 | chomp($prev = $_); 163 | } 164 | alarm(0); 165 | }; 166 | kill 'KILL', -$pid; 167 | if ($@) { 168 | chomp($@); 169 | bad $prev, $test, 'NOTERM', $@, $log; 170 | } 171 | close($out) 172 | or bad $prev, $test, 'NOEXIT', $! ? 173 | "Close pipe from '@runcmd' failed: $!" : 174 | "Command '@runcmd' failed: $?", $log; 175 | 176 | bad $prev, $test, 'FAIL', join(", ", @failed), $log if @failed; 177 | bad $prev, $test, 'XPASS', join(", ", @xpassed), $log if @xpassed; 178 | bad $prev, $test, 'SKIP', "Test skipped itself", $log if $skipped; 179 | bad $prev, $test, 'XFAIL', join(", ", @xfailed), $log if @xfailed; 180 | my $end = Time::HiRes::time(); 181 | good $prev, $test, $end - $begin, $log; 182 | 183 | close($log) 184 | or die "Close 'make.log' after writing failed: $!"; 185 | } 186 | 187 | print $pax $paxlog if $paxlog; 188 | close($pax) or die $! ? 189 | "Close pipe to '@paxcmd' failed: $!" : 190 | "Command '@paxcmd' failed: $?"; 191 | 192 | # create a tgz file with all obj/regress files 193 | my $objdir = "/usr/obj/regress"; 194 | @paxcmd = ('pax', '-x', 'cpio', '-wzf', "$regressdir/test.obj.tgz"); 195 | push @paxcmd, '-v' if $opts{v}; 196 | my @toobig = qw( 197 | /diskimage 198 | /htdocs/[0-9]* 199 | /toobig 200 | /tsort/pairs[0-9]* 201 | \.core 202 | ); 203 | push @paxcmd, map { "-s,^.*$_\$,," } @toobig; 204 | push @paxcmd, ("-s,^$objdir/,,", "-s,^$objdir,,", $objdir); 205 | system(@paxcmd) 206 | and die "Command '@paxcmd' failed: $?"; 207 | 208 | close($tr) 209 | or die "Close 'test.result' after writing failed: $!"; 210 | 211 | exit; 212 | 213 | # parse shell script that is setting environment for some tests 214 | # FOO=bar 215 | # FOO="bar" 216 | # export FOO=bar 217 | # export FOO BAR 218 | sub environment { 219 | my $file = shift; 220 | 221 | open(my $fh, '<', $file) 222 | or die "Open '$file' for reading failed: $!"; 223 | while (<$fh>) { 224 | chomp; 225 | s/#.*$//; 226 | s/\s+$//; 227 | s/^export\s+(?=\w+=)//; 228 | s/^export\s+\w+.*//; 229 | next if /^$/; 230 | if (/^(\w+)=(\S+)$/ or /^(\w+)="([^"]*)"/ or /^(\w+)='([^']*)'/) { 231 | $ENV{$1}=$2; 232 | } else { 233 | die "Unknown environment line in '$file': $_"; 234 | } 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /release.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (c) 2016-2023 Alexander Bluhm 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | use strict; 18 | use warnings; 19 | use Cwd; 20 | use File::Basename; 21 | use File::Path qw(remove_tree); 22 | use Getopt::Std; 23 | use POSIX; 24 | use Time::HiRes; 25 | 26 | my @allsteps = qw(clean obj build sysmerge dev destdir reldir release chkflist); 27 | 28 | my %opts; 29 | getopts('e:t:v', \%opts) or do { 30 | print STDERR <<"EOF"; 31 | usage: release.pl [-v] [-e environment] [-t timeout] [step ...] 32 | -e environ parse environment for tests from shell script 33 | -t timeout timeout for a single test, default 1 hour 34 | -v verbose 35 | step ... build step: @allsteps 36 | EOF 37 | exit(2); 38 | }; 39 | my $timeout = $opts{t} || 5*24*60*60; 40 | environment($opts{e}) if $opts{e}; 41 | my %steps; 42 | foreach my $step (@ARGV) { 43 | grep { $_ eq $step } @allsteps 44 | or die "Unknown build step '$step'"; 45 | $steps{$step} = 1; 46 | } 47 | @ARGV and warn "Make release restricted to build steps, for debugging only\n"; 48 | 49 | my $dir = dirname($0); 50 | chdir($dir) 51 | or die "Change directory to '$dir' failed: $!"; 52 | $dir = getcwd(); 53 | my $logdir = "$dir/logs"; 54 | -d $logdir && remove_tree($logdir); 55 | mkdir $logdir 56 | or die "Make directory '$logdir' failed: $!"; 57 | 58 | # write summary of results into result file 59 | open(my $tr, '>', "test.result") 60 | or die "Open 'test.result' for writing failed: $!"; 61 | $tr->autoflush(); 62 | $| = 1; 63 | 64 | sub bad { 65 | my ($prev, $test, $reason, $message, $log) = @_; 66 | my $nl = ""; 67 | $nl = "\n" if $prev ne ""; 68 | print $log "${nl}$reason\t$test\t$message\n" if $log; 69 | print "${nl}$reason\t$test\t$message\n\n" if $opts{v}; 70 | print $tr "$reason\t$test\t$message\n"; 71 | $log->sync() if $log; 72 | $tr->sync(); 73 | no warnings 'exiting'; 74 | last; 75 | } 76 | 77 | sub good { 78 | my ($prev, $test, $diff, $log) = @_; 79 | my $nl = ""; 80 | $nl = "\n" if $prev ne ""; 81 | my $duration = sprintf("%dm%02d.%02ds", $diff/60, $diff%60, 100*$diff%100); 82 | print $log "${nl}PASS\t$test\tDuration $duration\n" if $log; 83 | print "${nl}PASS\t$test\tDuration $duration\n\n" if $opts{v}; 84 | print $tr "PASS\t$test\tDuration $duration\n"; 85 | $log->sync() if $log; 86 | $tr->sync(); 87 | } 88 | 89 | sub logmsg { 90 | my ($prev, $message, $log) = @_; 91 | print $log "$message\n" if $log; 92 | print "$message\n" if $opts{v}; 93 | $$prev = $message; 94 | } 95 | 96 | my $ncpu = `sysctl -n hw.ncpuonline`; 97 | chomp($ncpu); 98 | 99 | my @tests = ( 100 | [ clean => "rm -rf /usr/obj/*" ], 101 | [ obj => "cd /usr/src && make obj" ], 102 | [ build => "cd /usr/src && make -j$ncpu build" ], 103 | [ sysmerge => "sysmerge -b" ], 104 | [ dev => "cd /dev && ./MAKEDEV all" ], 105 | [ destdir => \&destdir ], 106 | [ reldir => \&releasedir ], 107 | [ release => "cd /usr/src/etc && time make -j$ncpu release" ], 108 | [ chkflist => "cd /usr/src/distrib/sets && sh checkflist" ], 109 | ); 110 | 111 | # run release steps as tests 112 | foreach (@tests) { 113 | my ($test, $cmd) = @$_; 114 | 115 | next if keys %steps && ! $steps{$test}; 116 | 117 | my $prev = ""; 118 | my $begin = Time::HiRes::time(); 119 | my $date = strftime("%FT%TZ", gmtime($begin)); 120 | print "\nSTART\t$test\t$date\n\n" if $opts{v}; 121 | 122 | mkdir "$logdir/$test"; 123 | my $logfile = "$logdir/$test/make.log"; 124 | open(my $log, '>', $logfile) 125 | or bad $prev, $test, 'NOLOG', "Open '$logfile' for writing failed: $!"; 126 | $log->autoflush(); 127 | 128 | print $log "START\t$test\t$date\n\n"; 129 | $log->sync(); 130 | 131 | if (ref $cmd eq 'CODE') { 132 | logmsg \$prev, "Function '$test' started.", $log; 133 | eval { $cmd->() }; 134 | if ($@) { 135 | chomp($@); 136 | bad $prev, $test, 'FAIL', $@, $log; 137 | } 138 | logmsg \$prev, "Function '$test' finished.", $log; 139 | } else { 140 | logmsg \$prev, "Command '$cmd' started.", $log; 141 | my $pid = open(my $out, '-|', $cmd) 142 | or bad $prev, $test, 'NORUN', "Open pipe from '$cmd' failed: $!", 143 | $log; 144 | eval { 145 | local $SIG{ALRM} = sub { die "Test running too long, aborted.\n" }; 146 | alarm($timeout); 147 | while (<$out>) { 148 | print $log $_; 149 | s/[^\s[:print:]]/_/g; 150 | print if $opts{v}; 151 | chomp($prev = $_); 152 | } 153 | alarm(0); 154 | }; 155 | kill 'KILL', -$pid; 156 | if ($@) { 157 | chomp($@); 158 | bad $prev, $test, 'NOTERM', $@, $log; 159 | } 160 | close($out) 161 | or bad $prev, $test, 'NOEXIT', $! ? 162 | "Close pipe from '$cmd' failed: $!" : 163 | "Command '$cmd' failed: $?", $log; 164 | logmsg \$prev, "Command '$cmd' finished.", $log; 165 | } 166 | 167 | my $end = Time::HiRes::time(); 168 | good $prev, $test, $end - $begin, $log; 169 | 170 | close($log) 171 | or die "Close '$logfile' after writing failed: $!"; 172 | } 173 | 174 | my @paxcmd = ('pax', '-wzf', "$dir/test.log.tgz", '-s,^logs/,,', 175 | '-s,^logs,,', 'logs'); 176 | system(@paxcmd) 177 | and die "Command '@paxcmd' failed: $?"; 178 | 179 | close($tr) 180 | or die "Close 'test.result' after writing failed: $!"; 181 | 182 | exit; 183 | 184 | # parse shell script that is setting environment for some tests 185 | # FOO=bar 186 | # FOO="bar" 187 | # export FOO=bar 188 | # export FOO BAR 189 | sub environment { 190 | my $file = shift; 191 | 192 | open(my $fh, '<', $file) 193 | or die "Open '$file' for reading failed: $!"; 194 | while (<$fh>) { 195 | chomp; 196 | s/#.*$//; 197 | s/\s+$//; 198 | s/^export\s+(?=\w+=)//; 199 | s/^export\s+\w+.*//; 200 | next if /^$/; 201 | if (/^(\w+)=(\S+)$/ or /^(\w+)="([^"]*)"/ or /^(\w+)='([^']*)'/) { 202 | $ENV{$1}=$2; 203 | } else { 204 | die "Unknown environment line in '$file': $_"; 205 | } 206 | } 207 | } 208 | 209 | sub destdir { 210 | my ($login, $pass, $uid, $gid) = getpwnam("build") 211 | or die "User 'build' not in passwd file"; 212 | 213 | -d "/build" || mkdir "/build" 214 | or die "Make directory '/build' failed: $!"; 215 | system("umount -f /build"); 216 | system("mount /build") 217 | and die "Mount '/build' failed: $?"; 218 | chown $uid, 0, "/build" 219 | or die "Chown '/build' to build failed: $!"; 220 | chmod 0700, "/build" 221 | or die "Chmod '/build' to 700 failed: $!"; 222 | -d "/build/dest" || mkdir "/build/dest" 223 | or die "Make directory '/build/dest' failed: $!"; 224 | 225 | $ENV{DESTDIR}="/build/dest"; 226 | } 227 | 228 | sub releasedir { 229 | my ($login, $pass, $uid, $gid) = getpwnam("build") 230 | or die "User 'build' not in passwd file"; 231 | 232 | -d "/usr/release" || mkdir "/usr/release" 233 | or die "Make directory '/usr/release' failed: $!"; 234 | chown 0, $gid, "/usr/release" 235 | or die "Chown '/usr/release' to build failed: $!"; 236 | chmod 0775, "/usr/release" 237 | or die "Chmod '/usr/release' to 775 failed: $!"; 238 | 239 | $ENV{RELEASEDIR}="/usr/release"; 240 | } 241 | -------------------------------------------------------------------------------- /run.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # run regression tests on machine 3 | 4 | # Copyright (c) 2016-2023 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use File::Basename; 22 | use Getopt::Std; 23 | use POSIX; 24 | 25 | use lib dirname($0); 26 | use Logcmd; 27 | use Hostctl; 28 | 29 | my $date = strftime("%FT%TZ", gmtime); 30 | my $scriptname = "$0 @ARGV"; 31 | 32 | my @allsetupmodes = qw(build cvs install keep kernel reboot sysupgrade upgrade); 33 | 34 | my %opts; 35 | getopts('h:P:pv', \%opts) or do { 36 | print STDERR <<"EOF"; 37 | usage: run.pl [-pv] -h host [-P patch] setup ... 38 | -h host user and host for make regress, user defaults to root 39 | -P patch apply patch to clean kernel source 40 | -p power down after testing 41 | -v verbose 42 | setup ... setup mode: @allsetupmodes 43 | build build system from source /usr/src and reboot 44 | cvs cvs update /usr/src and make obj 45 | install install from snapshot 46 | keep keep installed host as is, skip setup 47 | kernel build kernel from source /usr/src/sys and reboot 48 | reboot before running tests 49 | sysupgrade sysupgrade to snapshot 50 | upgrade upgrade with snapshot 51 | EOF 52 | exit(2); 53 | }; 54 | $opts{h} or die "No -h specified"; 55 | my $patch = $opts{P}; 56 | 57 | @ARGV or die "No mode specified"; 58 | my %setupmode; 59 | foreach my $mode (@ARGV) { 60 | grep { $_ eq $mode } @allsetupmodes 61 | or die "Unknown setup mode '$mode'"; 62 | $setupmode{$mode} = 1; 63 | } 64 | foreach my $mode (qw(install keep reboot sysupgrade upgrade)) { 65 | die "Setup mode '$mode' must be used solely" 66 | if $setupmode{$mode} && keys %setupmode != 1; 67 | } 68 | 69 | # better get an errno than random kill by SIGPIPE 70 | $SIG{PIPE} = 'IGNORE'; 71 | 72 | # create directory for this test run with timestamp 2016-07-13T12:30:42Z 73 | my $regressdir = dirname($0). "/.."; 74 | chdir($regressdir) 75 | or die "Change directory to '$regressdir' failed: $!"; 76 | $regressdir = getcwd(); 77 | my $resultdir = "$regressdir/results/$date"; 78 | mkdir $resultdir 79 | or die "Make directory '$resultdir' failed: $!"; 80 | unlink("results/current"); 81 | symlink($date, "results/current") 82 | or die "Make symlink 'results/current' failed: $!"; 83 | chdir($resultdir) 84 | or die "Change directory to '$resultdir' failed: $!"; 85 | 86 | createlog(file => "run.log", verbose => $opts{v}); 87 | logmsg("$date Script '$scriptname' started.\n"); 88 | 89 | open(my $fh, '>', "runconf.txt") 90 | or die "Open 'runconf.txt' for writing failed: $!"; 91 | print $fh "ARGUMENTS @ARGV\n"; 92 | print $fh "HOST $opts{h}\n"; 93 | print $fh "SETUPMODE ", join(" ", sort keys %setupmode), "\n"; 94 | close($fh); 95 | 96 | # setup remote machines 97 | 98 | usehosts(bindir => "$regressdir/bin", date => $date, 99 | host => $opts{h}, verbose => $opts{v}); 100 | (my $host = $opts{h}) =~ s/.*\@//; 101 | 102 | # do not run end block until initialized, date may change later 103 | my $odate = $date; 104 | END { 105 | if ($odate) { 106 | bsdcons_hosts(); 107 | relogdie(); 108 | } 109 | if ($regressdir) { 110 | my @cmd = ("$regressdir/bin/setup-html.pl"); 111 | system(@cmd); 112 | @cmd = ("$regressdir/bin/running-html.pl"); 113 | system(@cmd); 114 | } 115 | }; 116 | if ($patch || !($setupmode{keep} || $setupmode{reboot})) { 117 | setup_hosts(patch => $patch, mode => \%setupmode); 118 | } elsif (!$setupmode{reboot}) { 119 | powerup_hosts(patch => $patch); 120 | } else { 121 | reboot_hosts(patch => $patch); 122 | } 123 | collect_version(); 124 | setup_html(); 125 | 126 | # run regression tests remotely 127 | 128 | chdir($resultdir) 129 | or die "Change directory to '$resultdir' failed: $!"; 130 | 131 | my @sshcmd = ('ssh', $opts{h}, 'perl', '/root/regress/regress.pl', 132 | '-e', "/root/regress/env-$host.sh", '-v'); 133 | logcmd(@sshcmd); 134 | 135 | # get result and logs 136 | 137 | collect_result("$opts{h}:/root/regress"); 138 | collect_dmesg(); 139 | setup_html(); 140 | powerdown_hosts(patch => $patch) if $opts{p}; 141 | bsdcons_hosts(); 142 | undef $odate; 143 | 144 | # create html output 145 | 146 | chdir($regressdir) 147 | or die "Change directory to '$regressdir' failed: $!"; 148 | 149 | setup_html(date => 1); 150 | runcmd("bin/regress-html.pl", "-h", $host, "src"); 151 | 152 | unlink("results/latest-$host"); 153 | symlink($date, "results/latest-$host") 154 | or die "Make symlink 'results/latest-$host' failed: $!"; 155 | unlink("results/latest"); 156 | symlink($date, "results/latest") 157 | or die "Make symlink 'results/latest' failed: $!"; 158 | runcmd("bin/regress-html.pl", "-l", "src"); 159 | 160 | # do not create all page, it is too slow and too large 161 | #runcmd("bin/regress-html.pl", "src"); 162 | 163 | my $now = strftime("%FT%TZ", gmtime); 164 | logmsg("$now Script '$scriptname' finished.\n"); 165 | 166 | exit; 167 | -------------------------------------------------------------------------------- /running-html.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -T 2 | # collect all install and running logs into one html table 3 | 4 | # Copyright (c) 2016-2021 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use File::Basename; 22 | use HTML::Entities; 23 | use Getopt::Std; 24 | use Date::Parse; 25 | use List::Util qw(uniq); 26 | use POSIX; 27 | use URI::Escape; 28 | 29 | use lib dirname(($0 =~ m{^([/\w.-]+)$})[0]); 30 | use Html; 31 | 32 | my @now = gmtime(); 33 | my $now = strftime("%FT%TZ", @now); 34 | 35 | my %opts; 36 | getopts('va', \%opts) or do { 37 | print STDERR <<"EOF"; 38 | usage: running-html.pl [-a] [-d date] 39 | -a create running.html for all dates 40 | -v verbose 41 | EOF 42 | exit(2); 43 | }; 44 | my $verbose = $opts{v}; 45 | $| = 1 if $verbose; 46 | @ARGV and die "No arguments allowed"; 47 | 48 | my $testdir = dirname(($0 =~ m{^([/\w.-]+)$})[0]). "/../.."; 49 | chdir($testdir) 50 | or die "Change directory to '$testdir' failed: $!"; 51 | $testdir = (getcwd() =~ m{^([/\w]+)$})[0]; 52 | my $resultdir = "$testdir/results"; 53 | chdir($resultdir) 54 | or die "Change directory to '$resultdir' failed: $!"; 55 | 56 | my (%L, %V); 57 | 58 | # %L 59 | # $L{$host}{$type}{log} log file path 60 | # $L{$host}{$type}{mtime} modified time of log file 61 | # $L{$host}{$type}{hosts}[] host names with version files 62 | # $L{$host}{$type}{setup}{$host} setup log file path 63 | # $L{$host}{mtime} latest modified time of log files 64 | # %V 65 | # $V{$host}{version} version text file 66 | # $V{$host}{kerntime} kernel time from version file 67 | # $V{$host}{arch} sysctl hardware machine architecture 68 | # $V{$host}{ncpu} sysctl hardware ncpu cores 69 | # $V{$host}{mtime} latest modified time of version file 70 | 71 | my @types = qw(regress perform portstest release netlink); 72 | 73 | print "find latest logs" if $verbose; 74 | foreach my $type (@types) { 75 | my @logs = glob_log_files($type); 76 | find_latest_logs($type, @logs); 77 | } 78 | print "\n" if $verbose; 79 | 80 | print "create html running" if $verbose; 81 | create_html_running(); 82 | print "\n" if $verbose; 83 | 84 | exit 0; 85 | 86 | sub glob_log_files { 87 | my ($type) = @_; 88 | 89 | print "." if $verbose; 90 | my $resultdir = "../$type/results"; 91 | my $mon = $now[4]; 92 | my $year = $now[5] + 1900; 93 | my $dateglob = $opts{a} ? "*" : 94 | $mon == 0 ? sprintf("{%04d-%02d,%04d-%02d}-*", $year-1, 12, $year, 1) : 95 | sprintf("%04d-{%02d,%02d}-*", $year, $mon, $mon+1); 96 | my %logglob = ( 97 | regress => "run", 98 | perform => "{step,once}", 99 | portstest => "test", 100 | release => "make", 101 | netlink => "net", 102 | ); 103 | 104 | my @logs = glob("$resultdir/${dateglob}T*Z/$logglob{$type}.log"); 105 | if ($type eq "perform") { 106 | push @logs, glob( 107 | "$resultdir/[0-9]*.[0-9]/${dateglob}T*Z/$logglob{$type}.log"); 108 | } 109 | return @logs; 110 | } 111 | 112 | sub find_latest_logs { 113 | my ($type, @logs) = @_; 114 | 115 | print "." if $verbose; 116 | foreach my $log (@logs) { 117 | my $dir = dirname($log); 118 | my @hosts = map { m,/setup-(\w+).log$, } glob("$dir/setup-*.log"); 119 | foreach my $version (glob("$dir/version-*.txt")) { 120 | my $mtime = (stat($version))[9] 121 | or die "Stat '$version' failed: $!"; 122 | my ($host) = $version =~ m,/version-(\w+).txt$,; 123 | push @hosts, $host; 124 | next if $V{$host}{mtime} && $V{$host}{mtime} > $mtime; 125 | $V{$host} = { 126 | version => $version, 127 | mtime => $mtime, 128 | }; 129 | } 130 | @hosts = uniq @hosts; 131 | next unless @hosts; 132 | 133 | my $mtime = (stat($log))[9] 134 | or die "Stat '$log' failed: $!"; 135 | next if $L{$hosts[0]}{$type}{mtime} && 136 | $L{$hosts[0]}{$type}{mtime} > $mtime; 137 | my ($date) = $log =~ m,/([^/]+T[^/]+Z)/,; 138 | foreach my $host (@hosts) { 139 | $L{$host}{$type} = { 140 | date => $date, 141 | log => $log, 142 | mtime => $mtime, 143 | }; 144 | my $setup = "$dir/setup-$host.log"; 145 | if (-f $setup) { 146 | if ($host ne $hosts[0]) { 147 | delete $L{$host}{$type}{date}; 148 | $L{$host}{$type}{log} = $setup; 149 | $L{$host}{$type}{mtime} = (stat($setup))[9] 150 | or die "Stat '$setup' failed: $!"; 151 | } 152 | } 153 | next if $L{$host}{mtime} && 154 | $L{$host}{mtime} > $L{$host}{$type}{mtime}; 155 | $L{$host}{mtime} = $L{$host}{$type}{mtime}; 156 | } 157 | } 158 | } 159 | 160 | sub create_html_running { 161 | my ($html, $htmlfile) = html_open("running"); 162 | my @nav = ( 163 | Top => "../test.html", 164 | Regress => "../regress/results/latest.html", 165 | Perform => "../perform/results/perform.html", 166 | Ports => "../portstest/results/latest.html", 167 | Release => "../release/results/latest.html", 168 | Net => "../netlink/results/latest/netlink.html", 169 | Running => undef); 170 | html_header($html, "OpenBSD Running", 171 | "OpenBSD test running", 172 | @nav); 173 | print $html <<"HEADER"; 174 | 175 | 176 | 177 | 178 | 179 |
created at$now
180 | HEADER 181 | 182 | print $html "\n"; 183 | print $html " \n"; 184 | print $html " \n \n"; 185 | foreach my $type (@types) { 186 | my $link = uri_escape("../$type/results/run.html", 187 | "^A-Za-z0-9\-\._~/"); 188 | print $html " \n"; 189 | } 190 | print $html " \n"; 191 | foreach my $label (qw(arch ncpu kernel)) { 192 | print $html " \n"; 193 | } 194 | print $html " \n"; 195 | print $html " \n \n"; 196 | 197 | my @hosts = sort { $L{$b}{mtime} <=> $L{$a}{mtime} || $a cmp $b } keys %L; 198 | foreach my $host (@hosts) { 199 | print "." if $verbose; 200 | print $html " \n \n"; 201 | foreach my $type (@types) { 202 | my $tv = $L{$host}{$type}; 203 | unless ($tv) { 204 | print $html " \n"; 205 | next; 206 | } 207 | my $date = $tv->{date}; 208 | my $label = $date || "setup"; 209 | my $log = $tv->{log}; 210 | my $status = log2status($log); 211 | my $class = $status ? " class=\"status $status\"" : ""; 212 | my $link = uri_escape($log, "^A-Za-z0-9\-\._~/"); 213 | my $href = $log ? "" : ""; 214 | my $enda = $href ? "" : ""; 215 | print $html " $href$label$enda"; 216 | my $mtime = $tv->{mtime}; 217 | if ($date) { 218 | my $start = str2time($date); 219 | my $duration = $mtime - $start; 220 | print $html "
duration "; 221 | print $html $duration >= 24*60*60 ? 222 | sprintf("%.2f days", $duration / (24*60*60)) : 223 | strftime("%T", gmtime($duration)); 224 | } 225 | print $html "\n"; 226 | } 227 | print $html strftime("
\n", gmtime($L{$host}{mtime})); 228 | if ($V{$host}) { 229 | my $version = $V{$host}{version}; 230 | my %v = parse_version_file($version); 231 | print $html map { " \n" } qw(arch ncpu); 232 | my $link = uri_escape($version, "^A-Za-z0-9\-\._~/"); 233 | my $href = $version ? "" : ""; 234 | my $enda = $href ? "" : ""; 235 | print $html " \n"; 238 | } 239 | print $html " \n"; 240 | } 241 | print $html " \n"; 242 | print $html "
host$typeended$label
$hostT%TZ$v{$_}$href$v{kerntime}$enda\n"; 236 | } else { 237 | print $html "
\n"; 243 | 244 | print $html "Each row displays the status of a host.\n"; 245 | print $html "If a row is completely green, the host is unused now.\n"; 246 | print $html "Red means the failure should be examined.\n"; 247 | print $html "If a row has any yellow, wait for the test to finish.\n"; 248 | html_running_table($html); 249 | html_footer($html); 250 | html_close($html, $htmlfile, "nozip"); 251 | } 252 | -------------------------------------------------------------------------------- /setup.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # setup machine for regress test 3 | 4 | # Copyright (c) 2016-2023 Alexander Bluhm 5 | # 6 | # Permission to use, copy, modify, and distribute this software for any 7 | # purpose with or without fee is hereby granted, provided that the above 8 | # copyright notice and this permission notice appear in all copies. 9 | # 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | 18 | use strict; 19 | use warnings; 20 | use Cwd; 21 | use Date::Parse; 22 | use File::Basename; 23 | use Getopt::Std; 24 | use POSIX; 25 | 26 | use lib dirname($0); 27 | use Logcmd; 28 | use Machine; 29 | use Buildquirks; 30 | 31 | my $now = strftime("%FT%TZ", gmtime); 32 | my $scriptname = "$0 @ARGV"; 33 | 34 | my @allsetupmodes = qw( 35 | build commands cvs install kernel keep ports tools restart 36 | sysupgrade upgrade 37 | ); 38 | 39 | my %opts; 40 | getopts('d:h:P:pr:v', \%opts) or do { 41 | print STDERR <<"EOF"; 42 | usage: setup.pl [-pv] [-d date] -h host [-P patch] [-r release] setup ... 43 | -d date set date string and change to sub directory 44 | -h host root\@openbsd-test-machine, login per ssh 45 | -P patch apply patch to clean kernel source, comma separated list 46 | -p power down after setup 47 | -r release use release for install and cvs checkout, X.Y or current 48 | -v verbose 49 | setup ... setup mode: @allsetupmodes 50 | build build system from source /usr/src and reboot 51 | commands run commands needed for some tests 52 | cvs clean cvs update /usr/src and make obj 53 | install install from snapshot 54 | keep only copy version and scripts 55 | kernel build kernel from source /usr/src/sys and reboot 56 | ports cvs update /usr/ports 57 | restart cvs clean, patch /usr/src, build kernel, install, reboot 58 | sysupgrade sysupgrade to snapshot 59 | tools build and install tools needed for some tests 60 | upgrade upgrade with snapshot 61 | EOF 62 | exit(2); 63 | }; 64 | $opts{h} or die "No -h specified"; 65 | !$opts{d} || str2time($opts{d}) 66 | or die "Invalid -d date '$opts{d}'"; 67 | my $date = $opts{d}; 68 | my $patch = $opts{P}; 69 | 70 | @ARGV or die "No mode specified"; 71 | my %mode; 72 | foreach my $mode (@ARGV) { 73 | grep { $_ eq $mode } @allsetupmodes 74 | or die "Unknown setup mode '$mode'"; 75 | $mode{$mode} = 1; 76 | } 77 | my $release; 78 | if ($opts{r} && $opts{r} ne "current") { 79 | die "Upgrade to release not supported" 80 | if $mode{upgrade} || $mode{sysupgrade}; 81 | ($release = $opts{r}) =~ /^\d+\.\d$/ 82 | or die "Release '$release' must be major.minor format"; 83 | } 84 | 85 | my $regressdir = dirname($0). "/.."; 86 | chdir($regressdir) 87 | or die "Change directory to '$regressdir' failed: $!"; 88 | $regressdir = getcwd(); 89 | my $resultdir = "$regressdir/results"; 90 | $resultdir .= "/$release" if $release && $date && -d "results/$release/$date"; 91 | $resultdir .= "/$date" if $date; 92 | chdir($resultdir) 93 | or die "Change directory to '$resultdir' failed: $!"; 94 | my $bindir = "$regressdir/bin"; 95 | 96 | my ($user, $host) = split('@', $opts{h}, 2); 97 | ($user, $host) = ("root", $user) unless $host; 98 | 99 | createlog(file => "setup-$host.log", verbose => $opts{v}); 100 | logmsg("$now Script '$scriptname' started.\n"); 101 | 102 | createhost($user, $host); 103 | 104 | my $cvspath; 105 | $cvspath = "sys" if $mode{kernel}; 106 | 107 | # execute commands 108 | 109 | power_up() if (!$mode{install} && !$mode{upgrade}) || $mode{keep}; 110 | install_pxe($release) if $mode{install} && !$mode{keep}; 111 | upgrade_pxe() if $mode{upgrade} && !$mode{keep}; 112 | sysupgrade_fetch() if $mode{sysupgrade}; 113 | get_version(); 114 | copy_scripts(); 115 | checkout_cvs($release) if $mode{install} || $mode{upgrade} || 116 | $mode{sysupgrade}; 117 | update_cvs($release, undef, $cvspath) if $mode{cvs}; 118 | clean_cvs($cvspath) if ($mode{restart} && !$mode{cvs}) || $patch; 119 | if ($patch) { 120 | patch_cvs($_, $cvspath) foreach split(/,/, $patch); 121 | } 122 | update_ports($release) if $mode{ports}; 123 | make_kernel() if $mode{kernel} || $mode{build} || $mode{restart}; 124 | make_build() if $mode{build}; 125 | diff_cvs($cvspath) if $mode{kernel} || $mode{build} || $patch; 126 | reboot() if ($mode{kernel} || $mode{build} || $mode{restart} || 127 | $mode{sysupgrade}) && !$mode{keep}; 128 | get_version() if $mode{kernel} || $mode{build} || $mode{restart}; 129 | update_packages($release) if $mode{upgrade} || $mode{sysupgrade} || 130 | $mode{ports}; 131 | install_packages($release) if $mode{install} || $mode{upgrade} || 132 | $mode{sysupgrade} || $mode{ports}; 133 | build_tools() if $mode{install} || $mode{upgrade} || $mode{sysupgrade} || 134 | $mode{tools}; 135 | run_commands() if $mode{install} || $mode{upgrade} || $mode{sysupgrade} || 136 | $mode{ports} || $mode{commands}; 137 | power_down() if $opts{p}; 138 | get_bsdcons(); 139 | 140 | # finish setup log 141 | 142 | $now = strftime("%FT%TZ", gmtime); 143 | logmsg("$now Script '$scriptname' finished.\n"); 144 | 145 | exit; 146 | 147 | # copy scripts 148 | 149 | sub copy_scripts { 150 | chdir($bindir) 151 | or die "Change directory to '$bindir' failed: $!"; 152 | 153 | my @mkdirs = map { "/root/$_" } 154 | qw(regress perform portstest release netlink); 155 | runcmd('ssh', "$user\@$host", 'mkdir', '-p', @mkdirs); 156 | 157 | my @copy = grep { -f $_ } 158 | ("regress.pl", "env-$host.sh", "pkg-$host.list", "test.list", 159 | "site.list"); 160 | my @scpcmd = ('scp'); 161 | push @scpcmd, '-q' unless $opts{v}; 162 | push @scpcmd, (@copy, "$user\@$host:/root/regress"); 163 | runcmd(@scpcmd); 164 | 165 | @copy = grep { -f $_ } 166 | ("perform.pl", "netbench.pl", "makealign.sh", "env-$host.sh", 167 | "pkg-$host.list"); 168 | @scpcmd = ('scp'); 169 | push @scpcmd, '-q' unless $opts{v}; 170 | push @scpcmd, (@copy, "$user\@$host:/root/perform"); 171 | runcmd(@scpcmd); 172 | 173 | @copy = grep { -f $_ } 174 | ("portstest.pl", "env-$host.sh", "pkg-$host.list", "ports.list"); 175 | @scpcmd = ('scp'); 176 | push @scpcmd, '-q' unless $opts{v}; 177 | push @scpcmd, (@copy, "$user\@$host:/root/portstest"); 178 | runcmd(@scpcmd); 179 | 180 | @copy = grep { -f $_ } 181 | ("release.pl", "env-$host.sh"); 182 | @scpcmd = ('scp'); 183 | push @scpcmd, '-q' unless $opts{v}; 184 | push @scpcmd, (@copy, "$user\@$host:/root/release"); 185 | runcmd(@scpcmd); 186 | 187 | @copy = grep { -f $_ } 188 | ("netlink.pl", "Netstat.pm", "Kstat.pm", "netbench.pl", 189 | "env-$host.sh", "pkg-$host.list"); 190 | @scpcmd = ('scp'); 191 | push @scpcmd, '-q' unless $opts{v}; 192 | push @scpcmd, (@copy, "$user\@$host:/root/netlink"); 193 | runcmd(@scpcmd); 194 | 195 | chdir($resultdir) 196 | or die "Change directory to '$resultdir' failed: $!"; 197 | 198 | if (my %patches = quirk_patches()) { 199 | my $patchdir = "$resultdir/patches"; 200 | if (mkdir("$patchdir.tmp")) { 201 | # only one setup process may fill the directory 202 | while (my ($file, $content) = each %patches) { 203 | my $path = "$patchdir.tmp/$file.diff"; 204 | open(my $fh, '>', $path) 205 | or die "Open '$path' for writing failed: $!"; 206 | print $fh $content 207 | or die "Write content to '$path' failed: $!"; 208 | close($fh) 209 | or die "Close '$path' after writing failed: $!"; 210 | } 211 | # setup.pl might run in parallel, make directory creation atomic 212 | rename("$patchdir.tmp", $patchdir) || $!{EEXIST} || $!{ENOTEMPTY} 213 | or die "Rename '$patchdir.tmp' to '$patchdir' failed: $!"; 214 | } else { 215 | $!{EEXIST} 216 | or die "Make directory '$patchdir.tmp' failed: $!"; 217 | } 218 | foreach (1..60) { 219 | last if -d $patchdir; 220 | sleep 1; 221 | } 222 | -d $patchdir 223 | or die "Directory '$patchdir' does not exist"; 224 | @scpcmd = ('scp'); 225 | push @scpcmd, '-q' unless $opts{v}; 226 | push @scpcmd, ('-r', 'patches', "$user\@$host:/root/perform"); 227 | runcmd(@scpcmd); 228 | } 229 | } 230 | 231 | # install or update packages 232 | 233 | sub install_packages { 234 | my ($release) = @_; 235 | return unless -f "$bindir/pkg-$host.list"; 236 | 237 | logeval { 238 | logcmd('ssh', "$user\@$host", 'pkg_add', 239 | '-l', "regress/pkg-$host.list", '-Ivx', $release ? () : '-Dsnap'); 240 | }; 241 | } 242 | 243 | sub update_packages { 244 | my ($release) = @_; 245 | 246 | logeval { 247 | logcmd('ssh', "$user\@$host", 'pkg_add', 248 | '-u', '-Ivx', $release ? () : '-Dsnap'); 249 | }; 250 | } 251 | 252 | # build and install additional tools 253 | 254 | sub build_tools { 255 | return unless -f "$bindir/build-$host.list"; 256 | 257 | open(my $fh, '<', "$bindir/build-$host.list") 258 | or die "Open '$bindir/build-$host.list' for reading failed: $!"; 259 | chomp(my @tools = <$fh>); 260 | close($fh) 261 | or die "Close '$bindir/build-$host.list' after reading failed: $!"; 262 | 263 | foreach my $build (@tools) { 264 | my @scpcmd = ('scp', '-r'); 265 | push @scpcmd, '-q' unless $opts{v}; 266 | push @scpcmd, ("$bindir/../$build", "$user\@$host:/root/"); 267 | runcmd(@scpcmd); 268 | } 269 | foreach my $build (@tools) { 270 | logcmd('ssh', "$user\@$host", 'make', '-C', "/root/$build", 'all'); 271 | logcmd('ssh', "$user\@$host", 'make', '-C', "/root/$build", 'install'); 272 | } 273 | } 274 | 275 | # run additional commands 276 | 277 | sub run_commands { 278 | return unless -f "$bindir/cmd-$host.list"; 279 | 280 | open(my $fh, '<', "$bindir/cmd-$host.list") 281 | or die "Open '$bindir/cmd-$host.list' for reading failed: $!"; 282 | chomp(my @commands = <$fh>); 283 | close($fh) 284 | or die "Close '$bindir/cmd-$host.list' after reading failed: $!"; 285 | 286 | my $prev; 287 | foreach my $run (@commands) { 288 | # line continuations are concatenated with a single space 289 | if (defined($prev)) { 290 | $run =~ s/^\s*/$prev /; 291 | undef $prev; 292 | } 293 | # ignore empty lines 294 | next if $run =~ /^\s*$/; 295 | # comment starts in first column 296 | next if $run =~ /^#/; 297 | # long lines can be split with backslash 298 | if ($run =~ s/\s*\\$//) { 299 | $prev = $run; 300 | next; 301 | } 302 | # like make, ignore error when command starts with - 303 | if ($run =~ s/^-//) { 304 | logeval { logcmd('ssh', "$user\@$host", $run) }; 305 | } else { 306 | logcmd('ssh', "$user\@$host", $run); 307 | } 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /site-alpine.list: -------------------------------------------------------------------------------- 1 | /etc/hostname 2 | /etc/hosts 3 | /etc/network/interfaces 4 | /etc/ntpd.conf 5 | /etc/profile.d/proxy.sh 6 | /etc/resolv.conf 7 | /etc/ssh/ssh_host_ecdsa_key 8 | /etc/ssh/ssh_host_ecdsa_key.pub 9 | /etc/ssh/ssh_host_ed25519_key 10 | /etc/ssh/ssh_host_ed25519_key.pub 11 | /etc/ssh/ssh_host_rsa_key 12 | /etc/ssh/ssh_host_rsa_key.pub 13 | /etc/ssh/ssh_known_hosts 14 | /etc/update-extlinux.conf 15 | /root/.ssh/authorized_keys 16 | /root/.ssh/id_rsa 17 | /root/.ssh/id_rsa.pub 18 | -------------------------------------------------------------------------------- /site-debian.list: -------------------------------------------------------------------------------- 1 | /etc/apt/apt.conf 2 | /etc/apt/sources.list 3 | /etc/default/grub 4 | /etc/hostname 5 | /etc/network/interfaces 6 | /etc/openntpd/ntpd.conf 7 | /etc/resolv.conf 8 | /etc/ssh/ssh_host_ecdsa_key 9 | /etc/ssh/ssh_host_ecdsa_key.pub 10 | /etc/ssh/ssh_host_ed25519_key 11 | /etc/ssh/ssh_host_ed25519_key.pub 12 | /etc/ssh/ssh_host_rsa_key 13 | /etc/ssh/ssh_host_rsa_key.pub 14 | /etc/ssh/ssh_known_hosts 15 | /root/.ssh/authorized_keys 16 | /root/.ssh/id_rsa 17 | /root/.ssh/id_rsa.pub 18 | -------------------------------------------------------------------------------- /site.list: -------------------------------------------------------------------------------- 1 | /etc/doas.conf 2 | /etc/exports 3 | /etc/fstab.site 4 | /etc/hostname.* 5 | /etc/hosts.site 6 | /etc/iked.conf 7 | /etc/inetd.conf 8 | /etc/installurl 9 | /etc/mk.conf 10 | /etc/mygate 11 | /etc/myname 12 | /etc/ntpd.conf 13 | /etc/pf.conf 14 | /etc/rc.conf.local 15 | /etc/rc.d/nonxt_reflect 16 | /etc/rc.firsttime 17 | /etc/rc.local 18 | /etc/relayd.conf 19 | /etc/resolv.conf 20 | /etc/snmpd.conf 21 | /etc/soii.key 22 | /etc/ssh/ssh_host_ecdsa_key 23 | /etc/ssh/ssh_host_ecdsa_key.pub 24 | /etc/ssh/ssh_host_ed25519_key 25 | /etc/ssh/ssh_host_ed25519_key.pub 26 | /etc/ssh/ssh_host_rsa_key 27 | /etc/ssh/ssh_host_rsa_key.pub 28 | /etc/ssh/ssh_known_hosts 29 | /etc/sysctl.conf 30 | /etc/vm.conf 31 | /root/.cvsrc 32 | /root/.profile 33 | /root/.ssh/authorized_keys 34 | /root/.ssh/id_rsa 35 | /root/.ssh/id_rsa.pub 36 | -------------------------------------------------------------------------------- /tables.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Moritz Buhl 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 'use strict'; 17 | 18 | function merge_rows() { 19 | const utilization = document.getElementsByClassName('utilization')[0]; 20 | const otbody = utilization.children[1]; 21 | const tbody = otbody.cloneNode(1); 22 | 23 | let otr = []; 24 | for (const trc of tbody.children) { 25 | const tr = trc.children; 26 | const len = trc.childElementCount; 27 | if (!otr.length) { 28 | for (let i = 0; i < len; i++) { 29 | otr[i] = tr[i]; 30 | } 31 | continue; 32 | } 33 | 34 | if (len != otr.length) { 35 | console.warn(`inhomogeneous cell count: ${len} vs ${otr.length}.`); 36 | return; 37 | } 38 | for (let i = 0; i < 6; i++) { 39 | if (tr[i].innerText && otr[i].innerText == tr[i].innerText) { 40 | let rowspan = Number(otr[i].getAttribute('rowspan')); 41 | if (!rowspan) { 42 | rowspan = 1; 43 | } 44 | otr[i].setAttribute('rowspan', rowspan + 1); 45 | tr[i].hidden = 1; 46 | } else { 47 | tr[i].hidden = 0; 48 | otr[i] = tr[i]; 49 | } 50 | } 51 | } 52 | 53 | otbody.replaceWith(tbody); 54 | } 55 | 56 | function sort_by_col(ev) { 57 | const utilization = document.getElementsByClassName('utilization')[0]; 58 | const otbody = utilization.children[1]; 59 | const tbody = otbody.cloneNode(0); 60 | const thead = utilization.children[0].children[0].children; 61 | let col; 62 | let rows = []; 63 | 64 | for (col = 0; col < thead.length; col++) { 65 | if (thead[col] == ev.target) break; 66 | } 67 | 68 | for (const tr of otbody.children) { 69 | rows.push(tr); 70 | } 71 | 72 | rows.sort((a,b) => { 73 | let c = col; 74 | do { 75 | if (c > 5) 76 | c = 1; 77 | if (a.children[c].innerText == b.children[c].innerText) { 78 | c++; 79 | } else 80 | break; 81 | } while (c != col); 82 | 83 | /* XXX: return >= depending on arrow */ 84 | return a.children[c].innerText < b.children[c].innerText; 85 | }); 86 | 87 | for (const tr of rows) { 88 | tbody.appendChild(tr); 89 | } 90 | 91 | tbody.innerHTML = tbody.innerHTML.replaceAll('hidden=""', '').replaceAll( 92 | 'rowspan=', 'foo='); // XXX 93 | 94 | otbody.replaceWith(tbody); 95 | merge_rows(); 96 | } 97 | 98 | function filter_by_target(ev) { 99 | const utilization = document.getElementsByClassName('utilization')[0]; 100 | const otbody = utilization.children[1]; 101 | const tbody = otbody.cloneNode(0); 102 | const par = ev.target.parentElement.children; 103 | let col; 104 | let match = [], others = []; 105 | 106 | for (col = 0; col < par.length; col++) { 107 | if (par[col] == ev.target) break; 108 | } 109 | 110 | for (const tr of otbody.children) { 111 | if (tr.children[col].innerText == ev.target.innerText) 112 | match.push(tr); 113 | else 114 | others.push(tr); 115 | } 116 | 117 | for (const tr of match) { 118 | tbody.appendChild(tr); 119 | } 120 | for (const tr of others) { 121 | tbody.appendChild(tr); 122 | } 123 | 124 | tbody.innerHTML = tbody.innerHTML.replaceAll('hidden=""', '').replaceAll( 125 | 'rowspan=', 'foo='); // XXX 126 | 127 | otbody.replaceWith(tbody); 128 | merge_rows(); 129 | const descs = utilization.children[1].getElementsByClassName('desc'); 130 | for (let i = 0; i < descs.length; i++) { 131 | let td = descs[i]; 132 | td.onclick = filter_by_target; 133 | } 134 | } 135 | 136 | window.addEventListener("load", () => { 137 | merge_rows(); 138 | const utilization = document.getElementsByClassName('utilization')[0]; 139 | const thead_tr = utilization.children[0].children[0].children; 140 | const descs = utilization.children[1].getElementsByClassName('desc'); 141 | 142 | thead_tr[1].innerHTML = "IP"; 143 | thead_tr[2].innerHTML = "Transport"; 144 | thead_tr[3].innerHTML = "Direction"; 145 | thead_tr[4].innerHTML = "Test"; 146 | thead_tr[5].innerHTML = "Modifier"; 147 | for (let i = 1; i <= 5; i++) { 148 | thead_tr[i].innerHTML += " →"; 149 | thead_tr[i].classList.add("desc"); 150 | /* XXX: add on-click listeners for td.descs */ 151 | thead_tr[i].addEventListener("click", sort_by_col); 152 | } 153 | for (let i = 0; i < descs.length; i++) { 154 | let td = descs[i]; 155 | td.onclick = filter_by_target; 156 | } 157 | }); 158 | -------------------------------------------------------------------------------- /test.list: -------------------------------------------------------------------------------- 1 | bin/cat 2 | bin/chmod 3 | bin/csh 4 | bin/ed 5 | bin/expr 6 | bin/ksh 7 | bin/ln 8 | bin/md5 9 | bin/pax 10 | bin/ps 11 | bin/test 12 | etc/MAKEDEV 13 | gnu/egcs/gcc-bounds 14 | gnu/egcs/gcc-builtins 15 | gnu/lib/libexecinfo 16 | gnu/usr.bin/perl 17 | include/bitstring 18 | lib/csu 19 | lib/libagentx 20 | lib/libc/_setjmp 21 | lib/libc/alloca 22 | lib/libc/arc4random-fork 23 | lib/libc/atexit 24 | lib/libc/basename 25 | lib/libc/cephes 26 | lib/libc/cxa-atexit 27 | lib/libc/db 28 | lib/libc/dirname 29 | lib/libc/elf_aux_info 30 | lib/libc/env 31 | lib/libc/explicit_bzero 32 | lib/libc/ffs 33 | lib/libc/fmemopen 34 | lib/libc/fnmatch 35 | lib/libc/fpclassify 36 | lib/libc/fread 37 | lib/libc/gcvt 38 | lib/libc/getaddrinfo 39 | lib/libc/getcap 40 | lib/libc/getopt 41 | lib/libc/getopt_long 42 | lib/libc/glob 43 | lib/libc/hsearch 44 | lib/libc/ieeefp 45 | lib/libc/ifnameindex 46 | lib/libc/ldexp 47 | lib/libc/locale 48 | lib/libc/longjmp 49 | lib/libc/malloc 50 | lib/libc/mkstemp 51 | lib/libc/modf 52 | lib/libc/netdb 53 | lib/libc/open_memstream 54 | lib/libc/orientation 55 | lib/libc/popen 56 | lib/libc/printf 57 | lib/libc/qsort 58 | lib/libc/regex 59 | lib/libc/setjmp 60 | lib/libc/setjmp-fpu 61 | lib/libc/setjmp-signal 62 | lib/libc/sigsetjmp 63 | lib/libc/sigthr 64 | lib/libc/sleep 65 | lib/libc/sprintf 66 | lib/libc/stdio_threading 67 | lib/libc/stpncpy 68 | lib/libc/strchr 69 | lib/libc/strerror 70 | lib/libc/strlcat 71 | lib/libc/strlcpy 72 | lib/libc/strnlen 73 | lib/libc/strtod 74 | lib/libc/strtol 75 | lib/libc/strtonum 76 | lib/libc/sys 77 | lib/libc/telldir 78 | lib/libc/time 79 | lib/libc/timekeep 80 | lib/libc/timingsafe 81 | lib/libc/uuid 82 | lib/libc/vis 83 | lib/libc/wprintf 84 | lib/libcrypto/CA 85 | lib/libcrypto/aead 86 | lib/libcrypto/aes 87 | lib/libcrypto/aeswrap 88 | lib/libcrypto/asn1 89 | lib/libcrypto/base64 90 | lib/libcrypto/bf 91 | lib/libcrypto/bio 92 | lib/libcrypto/bn 93 | lib/libcrypto/c2sp 94 | lib/libcrypto/cast 95 | lib/libcrypto/certs 96 | lib/libcrypto/chacha 97 | lib/libcrypto/cms 98 | lib/libcrypto/crypto 99 | lib/libcrypto/ct 100 | lib/libcrypto/curve25519 101 | lib/libcrypto/des 102 | lib/libcrypto/dh 103 | lib/libcrypto/dsa 104 | lib/libcrypto/ec 105 | lib/libcrypto/ecdh 106 | lib/libcrypto/ecdsa 107 | lib/libcrypto/err 108 | lib/libcrypto/evp 109 | lib/libcrypto/exdata 110 | lib/libcrypto/free 111 | lib/libcrypto/gcm128 112 | lib/libcrypto/hkdf 113 | lib/libcrypto/hmac 114 | lib/libcrypto/idea 115 | lib/libcrypto/ige 116 | lib/libcrypto/init 117 | lib/libcrypto/lhash 118 | lib/libcrypto/md 119 | lib/libcrypto/mlkem 120 | lib/libcrypto/objects 121 | lib/libcrypto/ocsp 122 | lib/libcrypto/pbkdf2 123 | lib/libcrypto/pem 124 | lib/libcrypto/pkcs7 125 | lib/libcrypto/poly1305 126 | lib/libcrypto/rand 127 | lib/libcrypto/rc2 128 | lib/libcrypto/rc4 129 | lib/libcrypto/rmd 130 | lib/libcrypto/rsa 131 | lib/libcrypto/sha 132 | lib/libcrypto/sha2 133 | lib/libcrypto/sm3 134 | lib/libcrypto/sm4 135 | lib/libcrypto/symbols 136 | lib/libcrypto/utf8 137 | lib/libcrypto/wycheproof 138 | lib/libcrypto/x509 139 | lib/libedit 140 | lib/libevent 141 | lib/libexpat 142 | lib/libfuse 143 | lib/libkeynote 144 | lib/libm/cephes 145 | lib/libm/complex 146 | lib/libm/exp 147 | lib/libm/fenv 148 | lib/libm/floor 149 | lib/libm/fpaccuracy 150 | lib/libm/lgamma 151 | lib/libm/modf 152 | lib/libm/msun 153 | lib/libm/nextafter 154 | lib/libm/rint 155 | lib/libm/round 156 | lib/libm/tgamma 157 | lib/libm/toint 158 | lib/libm/trivial1 159 | lib/libpthread 160 | lib/libradius 161 | lib/libskey 162 | lib/libsndio 163 | lib/libssl/api 164 | lib/libssl/asn1 165 | lib/libssl/buffer 166 | lib/libssl/bytestring 167 | lib/libssl/ciphers 168 | lib/libssl/client 169 | lib/libssl/dtls 170 | lib/libssl/exporter 171 | lib/libssl/handshake 172 | lib/libssl/interop 173 | lib/libssl/key_schedule 174 | lib/libssl/openssl-ruby 175 | lib/libssl/pqueue 176 | lib/libssl/quic 177 | lib/libssl/record 178 | lib/libssl/record_layer 179 | lib/libssl/rust-openssl 180 | lib/libssl/server 181 | lib/libssl/shutdown 182 | lib/libssl/ssl 183 | lib/libssl/symbols 184 | lib/libssl/tls 185 | lib/libssl/tlsext 186 | lib/libssl/tlsfuzzer 187 | lib/libssl/tlslegacy 188 | lib/libssl/unit 189 | lib/libssl/verify 190 | lib/libtls/config 191 | lib/libtls/gotls 192 | lib/libtls/keypair 193 | lib/libtls/signer 194 | lib/libtls/tls 195 | lib/libtls/verify 196 | lib/libusbhid 197 | lib/libutil 198 | lib/libz 199 | libexec/ftpd 200 | libexec/ld.so 201 | misc/c++abi 202 | misc/exceptions 203 | misc/os-test 204 | misc/posixtestsuite 205 | misc/sse2 206 | sbin/bioctl 207 | sbin/disklabel 208 | sbin/ifconfig 209 | sbin/iked/dh 210 | sbin/iked/live 211 | sbin/iked/parser 212 | sbin/iked/test_helper 213 | sbin/ipsecctl 214 | sbin/isakmpd 215 | sbin/newfs 216 | sbin/pfctl 217 | sbin/route 218 | sbin/slaacd 219 | sys/altivec_ast 220 | sys/arch/amd64/ddb 221 | sys/arch/amd64/dump_tables 222 | sys/arch/amd64/fpu 223 | sys/arch/amd64/vmm 224 | sys/arch/hppa 225 | sys/arch/i386 226 | sys/arch/m88k 227 | sys/arch/sparc64 228 | sys/btcfi 229 | sys/copy 230 | sys/crypto/aes 231 | sys/crypto/aesctr 232 | sys/crypto/aesxts 233 | sys/crypto/chachapoly 234 | sys/crypto/cmac 235 | sys/crypto/enc 236 | sys/crypto/gmac 237 | sys/crypto/hmac 238 | sys/crypto/key_wrap 239 | sys/ddb 240 | sys/dev/fdesc 241 | sys/dev/kcov 242 | sys/dev/softraid 243 | sys/dev/video 244 | sys/dev/vnd 245 | sys/dev/wscons 246 | sys/ffs 247 | sys/fifofs 248 | sys/fileops 249 | sys/kern/accept 250 | sys/kern/access 251 | sys/kern/bind 252 | sys/kern/clock_gettime 253 | sys/kern/cmsgsize 254 | sys/kern/descrip 255 | sys/kern/dup2 256 | sys/kern/dup2_accept 257 | sys/kern/dup2_self 258 | sys/kern/exec_self 259 | sys/kern/execve 260 | sys/kern/exit 261 | sys/kern/extent 262 | sys/kern/fchdir 263 | sys/kern/fchown 264 | sys/kern/fcntl_dup 265 | sys/kern/flock 266 | sys/kern/fork-exit 267 | sys/kern/ftruncate 268 | sys/kern/futex 269 | sys/kern/getpeereid 270 | sys/kern/getrusage 271 | sys/kern/gettimeofday 272 | sys/kern/itimer 273 | sys/kern/kqueue 274 | sys/kern/main-thread-exited 275 | sys/kern/mbuf 276 | sys/kern/minherit 277 | sys/kern/mmap 278 | sys/kern/mmap-fail 279 | sys/kern/mmap2 280 | sys/kern/mmap3 281 | sys/kern/mount 282 | sys/kern/nanosleep 283 | sys/kern/noexec 284 | sys/kern/open 285 | sys/kern/pipe 286 | sys/kern/pledge 287 | sys/kern/poll 288 | sys/kern/pread 289 | sys/kern/preadv 290 | sys/kern/ptmget 291 | sys/kern/ptrace 292 | sys/kern/ptrace2 293 | sys/kern/pty 294 | sys/kern/pwrite 295 | sys/kern/pwritev 296 | sys/kern/rcvtimeo 297 | sys/kern/realpath 298 | sys/kern/realpath-unmount 299 | sys/kern/recvwait 300 | sys/kern/rlimit-file 301 | sys/kern/select 302 | sys/kern/setuid 303 | sys/kern/signal/cansig 304 | sys/kern/signal/earlysig 305 | sys/kern/signal/fpsig 306 | sys/kern/signal/sig-stop 307 | sys/kern/signal/sig-stop2 308 | sys/kern/signal/sig-stop3 309 | sys/kern/signal/sigaltstack_fork 310 | sys/kern/signal/sigfpe 311 | sys/kern/signal/siginfo-fault 312 | sys/kern/signal/siginfo_addr 313 | sys/kern/signal/sigio 314 | sys/kern/signal/signal-stress 315 | sys/kern/signal/sigpending 316 | sys/kern/signal/sigprof 317 | sys/kern/signal/sigpthread 318 | sys/kern/signal/sigsuspend 319 | sys/kern/sosplice/error 320 | sys/kern/sosplice/loop 321 | sys/kern/sosplice/perf 322 | sys/kern/sosplice/scapy 323 | sys/kern/sosplice/tcp 324 | sys/kern/sosplice/udp 325 | sys/kern/stackjmp 326 | sys/kern/stackpivot 327 | sys/kern/syscall_segment 328 | sys/kern/sysvmsg 329 | sys/kern/sysvsem 330 | sys/kern/sysvshm 331 | sys/kern/unalign 332 | sys/kern/unfdpass 333 | sys/kern/unixsockets 334 | sys/kern/unp-write-closed 335 | sys/kern/unveil 336 | sys/kern/unveil-unmount 337 | sys/kern/wait 338 | sys/kern/xonly 339 | sys/mfs_noperm 340 | sys/net/etherip 341 | sys/net/gif 342 | sys/net/loop 343 | sys/net/mpath 344 | sys/net/pair 345 | sys/net/pf_divert 346 | sys/net/pf_forward 347 | sys/net/pf_fragment 348 | sys/net/pf_opts 349 | sys/net/pf_policy 350 | sys/net/pf_print 351 | sys/net/pf_state 352 | sys/net/pf_table 353 | sys/net/pf_trans 354 | sys/net/pflog 355 | sys/net/pflow 356 | sys/net/rdomains 357 | sys/net/rtable 358 | sys/net/vxlan 359 | sys/net/wg 360 | sys/netinet/arp 361 | sys/netinet/autoport 362 | sys/netinet/bindconnect 363 | sys/netinet/broadcast_bind 364 | sys/netinet/carp 365 | sys/netinet/frag 366 | sys/netinet/in_pcbbind 367 | sys/netinet/ipsec 368 | sys/netinet/mcast 369 | sys/netinet/pmtu 370 | sys/netinet/recvmsg 371 | sys/netinet/sendsrcaddr 372 | sys/netinet/tcpthread 373 | sys/netinet/udpthread 374 | sys/netinet6/autoport 375 | sys/netinet6/frag6 376 | sys/netinet6/mcast6 377 | sys/netinet6/nd6 378 | sys/netinet6/pktinfo_addr 379 | sys/netinet6/recvmsg 380 | sys/netinet6/rh0 381 | sys/netinet6/rip6cksum 382 | sys/netinet6/srcaddr 383 | sys/nfs 384 | sys/ptrace 385 | sys/sys/tree 386 | sys/uvm/blist 387 | sys/uvm/minherit_zero 388 | sys/uvm/mmap0 389 | sys/uvm/mmap_4g 390 | sys/uvm/mmap_fixed 391 | sys/uvm/mmap_hint 392 | sys/uvm/mmap_mod 393 | sys/uvm/mmap_noreplace 394 | sys/uvm/mmap_size 395 | sys/uvm/mmap_write_self 396 | sys/uvm/vnode 397 | usr.bin/apply 398 | usr.bin/basename 399 | usr.bin/bc 400 | usr.bin/calendar 401 | usr.bin/colrm 402 | usr.bin/column 403 | usr.bin/ctfdump 404 | usr.bin/cut 405 | usr.bin/cvs 406 | usr.bin/dc 407 | usr.bin/diff 408 | usr.bin/diff3 409 | usr.bin/dirname 410 | usr.bin/doas 411 | usr.bin/file 412 | usr.bin/fmt 413 | usr.bin/fold 414 | usr.bin/ftp 415 | usr.bin/grep 416 | usr.bin/gzip 417 | usr.bin/join 418 | usr.bin/jot 419 | usr.bin/lam 420 | usr.bin/lastcomm 421 | usr.bin/libtool 422 | usr.bin/m4 423 | usr.bin/mail 424 | usr.bin/make 425 | usr.bin/mandoc 426 | usr.bin/nc 427 | usr.bin/netstat 428 | usr.bin/openssl 429 | usr.bin/patch 430 | usr.bin/pkg-config 431 | usr.bin/rcs 432 | usr.bin/rev 433 | usr.bin/rsync 434 | usr.bin/rsync-unit 435 | usr.bin/sdiff 436 | usr.bin/sed 437 | usr.bin/seq 438 | usr.bin/signify 439 | usr.bin/snmp 440 | usr.bin/sort 441 | usr.bin/ssh 442 | usr.bin/tail 443 | usr.bin/tsort 444 | usr.bin/ul 445 | usr.bin/wc 446 | usr.bin/xargs 447 | usr.sbin/acme-client 448 | usr.sbin/arp 449 | usr.sbin/bgpd/config 450 | usr.sbin/bgpd/integrationtests 451 | usr.sbin/bgpd/unittests 452 | usr.sbin/btrace 453 | usr.sbin/httpd 454 | usr.sbin/ifstated 455 | usr.sbin/installboot 456 | usr.sbin/ldapd 457 | usr.sbin/mtree 458 | usr.sbin/ocspcheck 459 | usr.sbin/ospf6d 460 | usr.sbin/ospfd 461 | usr.sbin/pkg_add 462 | usr.sbin/relayd 463 | usr.sbin/rpki-client 464 | usr.sbin/snmpd 465 | usr.sbin/syslogd 466 | usr.sbin/vmd 467 | -------------------------------------------------------------------------------- /test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Copyright (c) 2016-2023 Alexander Bluhm 4 | # 5 | # Permission to use, copy, modify, and distribute this software for any 6 | # purpose with or without fee is hereby granted, provided that the above 7 | # copyright notice and this permission notice appear in all copies. 8 | # 9 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | use strict; 18 | use warnings; 19 | use Cwd; 20 | use File::Basename; 21 | use Getopt::Std; 22 | use POSIX; 23 | 24 | use lib dirname($0); 25 | use Logcmd; 26 | use Hostctl; 27 | 28 | my $date = strftime("%FT%TZ", gmtime); 29 | my $scriptname = "$0 @ARGV"; 30 | 31 | my @allsetupmodes = qw(commands keep ports); 32 | 33 | my %opts; 34 | getopts('h:pv', \%opts) or do { 35 | print STDERR <<"EOF"; 36 | usage: test.pl [-pv] -h host setup ... 37 | -h host user and host for make test, user defaults to root 38 | -p power down after testing 39 | -v verbose 40 | setup ... setup mode: @allsetupmodes 41 | commands run commands needed for ports tests 42 | ports cvs update /usr/ports 43 | keep keep installed host as is, skip setup 44 | EOF 45 | exit(2); 46 | }; 47 | $opts{h} or die "No -h specified"; 48 | 49 | @ARGV or die "No setup mode specified"; 50 | my %setupmode; 51 | foreach my $mode (@ARGV) { 52 | grep { $_ eq $mode } @allsetupmodes 53 | or die "Unknown setup mode '$mode'"; 54 | $setupmode{$mode} = 1; 55 | } 56 | foreach my $mode (qw(keep)) { 57 | die "Setup mode '$mode' must be used solely" 58 | if $setupmode{$mode} && keys %setupmode != 1; 59 | } 60 | 61 | # better get an errno than random kill by SIGPIPE 62 | $SIG{PIPE} = 'IGNORE'; 63 | 64 | # create directory for this test run with timestamp 2016-07-13T12:30:42Z 65 | my $regressdir = dirname($0). "/.."; 66 | chdir($regressdir) 67 | or die "Change directory to '$regressdir' failed: $!"; 68 | $regressdir = getcwd(); 69 | my $resultdir = "$regressdir/results/$date"; 70 | mkdir $resultdir 71 | or die "Make directory '$resultdir' failed: $!"; 72 | unlink("results/current"); 73 | symlink($date, "results/current") 74 | or die "Make symlink 'results/current' failed: $!"; 75 | chdir($resultdir) 76 | or die "Change directory to '$resultdir' failed: $!"; 77 | 78 | createlog(file => "test.log", verbose => $opts{v}); 79 | logmsg("$date Script '$scriptname' started.\n"); 80 | 81 | open(my $fh, '>', "testconf.txt") 82 | or die "Open 'testconf.txt' for writing failed: $!"; 83 | print $fh "ARGUMENTS @ARGV\n"; 84 | print $fh "HOST $opts{h}\n"; 85 | print $fh "SETUPMODE ", join(" ", sort keys %setupmode), "\n"; 86 | close($fh); 87 | 88 | # setup remote machines 89 | 90 | usehosts(bindir => "$regressdir/bin", date => $date, 91 | host => $opts{h}, lasthost => $opts{h}, verbose => $opts{v}); 92 | (my $host = $opts{h}) =~ s/.*\@//; 93 | 94 | # do not run end block until initialized, date may change later 95 | my $odate = $date; 96 | END { 97 | if ($odate) { 98 | my @cmd = ("$regressdir/bin/bsdcons.pl", '-h', $opts{h}, '-d', $odate); 99 | system(@cmd); 100 | } 101 | if ($regressdir) { 102 | my @cmd = ("$regressdir/bin/setup-html.pl"); 103 | system(@cmd); 104 | @cmd = ("$regressdir/bin/running-html.pl"); 105 | system(@cmd); 106 | } 107 | }; 108 | if (!$setupmode{keep}) { 109 | setup_hosts(mode => \%setupmode); 110 | } else { 111 | powerup_hosts(); 112 | } 113 | collect_version(); 114 | setup_html(); 115 | 116 | # run port tests remotely 117 | 118 | chdir($resultdir) 119 | or die "Change directory to '$resultdir' failed: $!"; 120 | 121 | my @sshcmd = ('ssh', $opts{h}, 'perl', '/root/portstest/portstest.pl', 122 | '-e', "/root/portstest/env-$host.sh", '-v'); 123 | logcmd(@sshcmd); 124 | 125 | # get result and logs 126 | 127 | collect_result("$opts{h}:/root/portstest"); 128 | collect_dmesg(); 129 | setup_html(); 130 | powerdown_hosts() if $opts{p}; 131 | 132 | # create html output 133 | 134 | chdir($regressdir) 135 | or die "Change directory to '$regressdir' failed: $!"; 136 | 137 | setup_html(date => 1); 138 | runcmd("bin/regress-html.pl", "-h", $host, "ports"); 139 | 140 | unlink("results/latest-$host"); 141 | symlink($date, "results/latest-$host") 142 | or die "Make symlink 'results/latest-$host' failed: $!"; 143 | unlink("results/latest"); 144 | symlink($date, "results/latest") 145 | or die "Make symlink 'results/latest' failed: $!"; 146 | runcmd("bin/regress-html.pl", "-l", "ports"); 147 | 148 | # do not create all page, it is too slow and too large 149 | #runcmd("bin/regress-html.pl", "ports"); 150 | 151 | my $now = strftime("%FT%TZ", gmtime); 152 | logmsg("$now Script '$scriptname' finished.\n"); 153 | 154 | exit; 155 | -------------------------------------------------------------------------------- /testsuite-html.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # collect all os-test and posixtestsuite results and create a html table 3 | # os-test and posixtestsuite package must be installed 4 | 5 | # Copyright (c) 2018-2023 Alexander Bluhm 6 | # 7 | # Permission to use, copy, modify, and distribute this software for any 8 | # purpose with or without fee is hereby granted, provided that the above 9 | # copyright notice and this permission notice appear in all copies. 10 | # 11 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 | # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | 19 | use strict; 20 | use warnings; 21 | use Cwd; 22 | use File::Basename; 23 | use File::Path qw(make_path); 24 | use Getopt::Std; 25 | 26 | my @allsuitemodes = qw(os-test posixtestsuite); 27 | 28 | my %opts; 29 | getopts('h:p:v', \%opts) or do { 30 | print STDERR <<"EOF"; 31 | usage: testsuite-html.pl [-h host] -p publish [suite ...] 32 | -h host user and host for version information, user defaults to root 33 | -p publish directory where the test suite results are created 34 | -v verbose 35 | suite ... test suite: @allsuitemodes 36 | EOF 37 | exit(2); 38 | }; 39 | my $verbose = $opts{v}; 40 | $| = 1 if $verbose; 41 | my $publish = $opts{p} or die "No -p specified"; 42 | $publish = getcwd(). "/". $publish if substr($publish, 0, 1) ne "/"; 43 | 44 | @ARGV or @ARGV = @allsuitemodes; 45 | 46 | my %mode; 47 | foreach my $mode (@ARGV) { 48 | grep { $_ eq $mode } @allsuitemodes 49 | or die "Unknown test suite '$mode'"; 50 | $mode{$mode} = 1; 51 | } 52 | 53 | my $regressdir = dirname($0). "/.."; 54 | chdir($regressdir) 55 | or die "Change directory to '$regressdir' failed: $!"; 56 | $regressdir = getcwd(); 57 | my $resultdir = "$regressdir/results"; 58 | chdir($resultdir) 59 | or die "Change directory to '$resultdir' failed: $!"; 60 | 61 | my ($user, $host); 62 | if ($opts{h}) { 63 | ($user, $host) = split('@', $opts{h} || "", 2); 64 | ($user, $host) = ("root", $user) unless $host; 65 | } 66 | 67 | print "glob obj files" if $verbose; 68 | my @obj_files = glob_obj_files($host); 69 | print "\nextract result files" if $verbose; 70 | extract_result_files(@obj_files); 71 | if ($mode{'os-test'}) { 72 | print "\nwrite html os-test file" if $verbose; 73 | write_html_ostest_file(); 74 | } 75 | if ($mode{posixtestsuite}) { 76 | print "\nwrite html posixtestsuite file" if $verbose; 77 | write_html_posixtestsuite_file(); 78 | } 79 | print "\n" if $verbose; 80 | 81 | exit; 82 | 83 | sub glob_obj_files { 84 | my ($host) = @_; 85 | $host ||= "*"; 86 | my @obj; 87 | foreach (glob("latest-$host")) { 88 | print "." if $verbose; 89 | 90 | my $date = readlink or next; 91 | -d $date or next; 92 | my $obj = "$date/test.obj.tgz"; 93 | -f $obj or next; 94 | push @obj, $obj; 95 | } 96 | return @obj; 97 | } 98 | 99 | sub extract_result_files { 100 | my $testdir = "$publish/os-test"; 101 | -d "$testdir/out" || make_path("$testdir/out") 102 | or die "Make path '$testdir/out' failed: $!"; 103 | $testdir = "$publish/posixtestsuite"; 104 | -d "$testdir/out" || make_path("$testdir/out") 105 | or die "Make path '$testdir/out' failed: $!"; 106 | chdir($publish) 107 | or die "Change directory to '$publish' failed: $!"; 108 | 109 | foreach my $obj (@_) { 110 | print "." if $verbose; 111 | 112 | # parse obj file 113 | my ($date, $short) = $obj =~ m,(([^/]+)T[^/]+Z)/test.obj.tgz, 114 | or next; 115 | my $version = (sort glob("$resultdir/$date/version-*.txt"))[0] 116 | or die "No version file for date '$date'"; 117 | open(my $fh, '<', $version) 118 | or die "Open '$version' for reading failed: $!"; 119 | my ($kernel, $time, $location, $arch); 120 | while (<$fh>) { 121 | # OpenBSD 6.3-current (GENERIC.MP) #14: Thu Apr 26 21:03:52 MDT 2018 122 | if (/^kern.version=(.*: (\w+ \w+ +\d+ .*))$/) { 123 | $kernel = $1; 124 | $time = $2; 125 | <$fh> =~ /(\S+)/; 126 | $kernel .= "\n $1"; 127 | $location = $1; 128 | } 129 | /^hw.machine=(\w+)$/ and $arch = $1; 130 | } 131 | # test results with kernel from snapshot build only 132 | next unless $location =~ /^deraadt@\w+.openbsd.org:/; 133 | # Thu Apr 26 21:03:52 MDT 2018 134 | my (undef, $monthname, $day, undef, undef, $year) = split(" ", $time); 135 | my %mn2m; 136 | my $i = 0; 137 | foreach (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)) { 138 | $mn2m{$_} = ++$i; 139 | } 140 | my $snap = sprintf("%04d-%02d-%02d", $year, $mn2m{$monthname}, $day); 141 | my $out = "out/$snap-$host"; 142 | 143 | my @pax = ("pax", "-zrf", "$resultdir/$obj", 144 | "-s,.*\.core\$,,", 145 | "-s,.*\.c\$,,", 146 | "-s,.*\.sh\$,,"); 147 | push @pax, "-s,^misc/os-test/,$publish/os-test/$out/," 148 | if $mode{'os-test'}; 149 | push @pax, "-s,^misc/posixtestsuite/,$publish/posixtestsuite/$out/,", 150 | if $mode{posixtestsuite}; 151 | push @pax, "-s,.*,,"; 152 | system(@pax) 153 | and die "Command '@pax' failed: $?"; 154 | } 155 | } 156 | 157 | sub write_html_ostest_file { 158 | my $outdir = "$publish/os-test/out"; 159 | chdir($outdir) 160 | or die "Change directory to '$outdir' failed: $!"; 161 | my @oslist = reverse sort grep { -d } glob("*"); 162 | my @suites = qw(io udp); 163 | my @cmd = ("os-test-html", "--enable-suites-overview", 164 | "--suite-list=@suites", "--os-list=@oslist"); 165 | 166 | my $testdir = "$publish/os-test"; 167 | chdir($testdir) 168 | or die "Change directory to '$testdir' failed: $!"; 169 | 170 | my $htmlfile = "os-test.html"; 171 | unlink("$htmlfile.new"); 172 | 173 | print "." if $verbose; 174 | defined(my $pid = fork()) 175 | or die "Fork failed: $!"; 176 | if ($pid == 0) { 177 | open(STDOUT, '>', "$htmlfile.new") 178 | or die "Redirect '$htmlfile.new' to stdout failed: $!"; 179 | exec { "/usr/local/bin/os-test-html" } @cmd; 180 | die "Exec '/usr/local/bin/os-test-html' failed: $!"; 181 | } 182 | (my $waitpid = wait()) > 1 183 | or die "Wait failed: $!"; 184 | $? and die "Command '@cmd' failed: $?"; 185 | 186 | rename("$htmlfile.new", "$htmlfile") 187 | or die "Rename '$htmlfile.new' to '$htmlfile' failed: $!"; 188 | 189 | print "." if $verbose; 190 | system("gzip -f -c $htmlfile >$htmlfile.gz.new") 191 | and die "Gzip '$htmlfile' failed: $?"; 192 | rename("$htmlfile.gz.new", "$htmlfile.gz") 193 | or die "Rename '$htmlfile.gz.new' to '$htmlfile.gz' failed: $!"; 194 | } 195 | 196 | sub write_html_posixtestsuite_file { 197 | my $outdir = "$publish/posixtestsuite/out"; 198 | chdir($outdir) 199 | or die "Change directory to '$outdir' failed: $!"; 200 | my @oslist = reverse sort grep { -d } glob("*"); 201 | my @cmd = ("posixtestsuite-html", "-o", "@oslist"); 202 | 203 | my $testdir = "$publish/posixtestsuite"; 204 | chdir($testdir) 205 | or die "Change directory to '$testdir' failed: $!"; 206 | 207 | my $htmlfile = "posixtestsuite.html"; 208 | unlink("$htmlfile.new"); 209 | 210 | print "." if $verbose; 211 | defined(my $pid = fork()) 212 | or die "Fork failed: $!"; 213 | if ($pid == 0) { 214 | open(STDOUT, '>', "$htmlfile.new") 215 | or die "Redirect '$htmlfile.new' to stdout failed: $!"; 216 | exec { "/usr/local/bin/posixtestsuite-html" } @cmd; 217 | die "Exec '/usr/local/bin/posixtestsuite-html' failed: $!"; 218 | } 219 | (my $waitpid = wait()) > 1 220 | or die "Wait failed: $!"; 221 | $? and die "Command '@cmd' failed: $?"; 222 | 223 | rename("$htmlfile.new", "$htmlfile") 224 | or die "Rename '$htmlfile.new' to '$htmlfile' failed: $!"; 225 | 226 | print "." if $verbose; 227 | system("gzip -f -c $htmlfile >$htmlfile.gz.new") 228 | and die "Gzip '$htmlfile' failed: $?"; 229 | rename("$htmlfile.gz.new", "$htmlfile.gz") 230 | or die "Rename '$htmlfile.gz.new' to '$htmlfile.gz' failed: $!"; 231 | } 232 | --------------------------------------------------------------------------------