Add test that exchanges database description packets with ospfd.
authorbluhm <bluhm@openbsd.org>
Fri, 16 Jan 2015 17:06:43 +0000 (17:06 +0000)
committerbluhm <bluhm@openbsd.org>
Fri, 16 Jan 2015 17:06:43 +0000 (17:06 +0000)
From Florian Riehm.

12 files changed:
regress/usr.sbin/ospfd/Client.pm
regress/usr.sbin/ospfd/LICENSE
regress/usr.sbin/ospfd/Makefile
regress/usr.sbin/ospfd/Packet.pm
regress/usr.sbin/ospfd/args-ddstate.pl [new file with mode: 0644]
regress/usr.sbin/ospfd/args-ifstate-ism2.pl
regress/usr.sbin/ospfd/args-ifstate-pri-ism-ospfd.pl
regress/usr.sbin/ospfd/args-ifstate-pri-ism.pl
regress/usr.sbin/ospfd/args-ifstate-pri-ospfd-ism.pl
regress/usr.sbin/ospfd/args-ifstate-pri-ospfd.pl
regress/usr.sbin/ospfd/args-ifstate.pl
regress/usr.sbin/ospfd/args-none.pl

index ef0e1fb..fad2248 100644 (file)
@@ -1,7 +1,7 @@
-#      $OpenBSD: Client.pm,v 1.3 2014/08/18 22:58:19 bluhm Exp $
+#      $OpenBSD: Client.pm,v 1.4 2015/01/16 17:06:43 bluhm Exp $
 
-# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org>
-# Copyright (c) 2014 Florian Riehm <mail@friehm.de>
+# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org>
+# Copyright (c) 2014-2015 Florian Riehm <mail@friehm.de>
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -17,6 +17,7 @@
 
 use strict;
 use warnings;
+use feature "state";
 
 package Client;
 use parent 'Proc';
@@ -84,6 +85,8 @@ sub handle_ip {
        "ospfd area is $ospf{area_id_str}: expected $area");
     if ($ospf{type} == 1) {
        handle_hello();
+    } elsif ($ospf{type} == 2) {
+       handle_dd();
     } else {
        warn "ospf type is not supported: $ospf{type}";
     }
@@ -123,7 +126,43 @@ sub handle_hello {
     }
     if ($reason) {
        print "wait for hello because of: $reason\n";
-    } else {
+    } elsif (!$wait || $wait->{dr} || $wait->{bdr} || $wait->{nbrs}) {
+       $cv->send();
+    }
+}
+
+sub handle_dd {
+    my %dd = consume_dd(\$handle->{rbuf});
+
+    my $compare = sub {
+       my $expect = shift;
+       foreach my $key (qw(options bits)) {
+           if ($expect->{"dd_$key"}) {
+               $dd{$key} == $expect->{"dd_$key"} or
+                   return sprintf("dd key '%s' is 0x%x: expected 0x%x\n",
+                       $key, $dd{$key}, $expect->{"dd_$key"});
+           }
+       }
+       if ($expect->{dd_seq}) {
+           $dd{dd_sequence_number} == $expect->{dd_seq} or
+               return sprintf("dd_sequence_number is 0x%x: expected 0x%x\n",
+                   $dd{dd_sequence_number}, $expect->{dd_seq});
+       }
+       return "";
+    };
+
+    my $error = $compare->($check);
+    return $cv->croak("check: $error") if $error;
+    print "check dd successful\n";
+
+    my $reason;
+    if ($wait) {
+       $reason = $compare->($wait);
+    }
+    if ($reason) {
+       print "wait for dd because of: $reason\n";
+    } elsif (!$wait || $wait->{dd_bits} || $wait->{dd_options} ||
+       $wait->{dd_seq}) {
        $cv->send();
     }
 }
@@ -193,6 +232,51 @@ sub interface_state_machine {
     return \%state;
 }
 
+sub send_dd {
+    my $state = shift;
+    my $ip_number = unpack("N", pack("C4", split(/\./, $ism_ip)));
+    my $ip = join(".", unpack("C4", pack("N", $ip_number)));
+    my $rtrid_number = unpack("N", pack("C4", split(/\./, $ism_rtrid)));
+    my $rtrid = join(".", unpack("C4", pack("N", $rtrid_number)));
+    state $dd_count = 0;
+
+    my %ether = (
+       src_str => $ism_mac,
+       dst_str => "01:00:5e:00:00:05",  # don't know the real dst mac
+       type    => 0x0800,               # ipv4
+    );
+    my %ip = (
+       v       => 4,               # ipv4
+       hlen    => 20,
+       tos     => 0xc0,
+       id      => $dd_count++,     # increment for debugging
+       off     => 0,               # no fragment
+       ttl     => 1,               # only for direct connected
+       p       => 89,              # protocol ospf
+       src_str => $ip,
+       dst_str => $ospfd_ip,
+    );
+    my %ospf = (
+       version       => 2,           # ospf v2
+       type          => 2,           # dd
+       router_id_str => $rtrid,
+       area_id_str   => $area,
+       autype        => 0,           # no authentication
+    );
+    my %dd = (
+       interface_mtu => 1500,
+       options => 0x02,
+       bits => $state->{dd_bits},
+       dd_sequence_number => 999,      # some value
+    );
+    $handle->push_write(
+       construct_ether(\%ether,
+       construct_ip(\%ip,
+       construct_ospf(\%ospf,
+       construct_dd(\%dd))))
+    );
+}
+
 sub ism_set_state {
     my $state = shift;
 
@@ -200,6 +284,10 @@ sub ism_set_state {
     for (my $i = 0; $i < @states; $i++) {
        $isms[$i] ||= interface_state_machine();
        %{$isms[$i]} = (%{$isms[$i]}, %{$states[$i]});
+       if ($states[$i]{dd_bits}) {
+           send_dd($states[$i]);
+           delete $states[$i]{dd_bits};
+       }
     }
 }
 
index ff350f9..8b9a922 100644 (file)
@@ -1,5 +1,5 @@
-# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org>
-# Copyright (c) 2014 Florian Riehm <mail@friehm.de>
+# Copyright (c) 2010-2015 Alexander Bluhm <bluhm@openbsd.org>
+# Copyright (c) 2014-2015 Florian Riehm <mail@friehm.de>
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
index a87e748..6071802 100644 (file)
@@ -1,9 +1,9 @@
-#      $OpenBSD: Makefile,v 1.3 2014/11/25 23:13:54 daniel Exp $
+#      $OpenBSD: Makefile,v 1.4 2015/01/16 17:06:43 bluhm Exp $
 
 # The following ports must be installed for the regression tests:
 # p5-AnyEvent          provide framework for multiple event loops
 # p5-Hash-Merge                merge associative arrays
-# p5-YAML               YAML ain't a markup language
+# p5-YAML              YAML ain't a markup language
 #
 # Check wether all required perl packages are installed.  If some
 # are missing print a warning and skip the tests, but do not fail.
index 28c02a5..7933cb7 100644 (file)
@@ -1,6 +1,7 @@
-#      $OpenBSD: Packet.pm,v 1.2 2014/07/11 22:28:51 bluhm Exp $
+#      $OpenBSD: Packet.pm,v 1.3 2015/01/16 17:06:43 bluhm Exp $
 
-# Copyright (c) 2014 Alexander Bluhm <bluhm@openbsd.org>
+# Copyright (c) 2014-2015 Alexander Bluhm <bluhm@openbsd.org>
+# Copyright (c) 2015 Florian Riehm <mail@friehm.de>
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -27,11 +28,13 @@ our @EXPORT = qw(
     consume_ip
     consume_ospf
     consume_hello
+    consume_dd
     construct_ether
     construct_arp
     construct_ip
     construct_ospf
     construct_hello
+    construct_dd
 );
 
 sub ip_checksum {
@@ -227,6 +230,21 @@ sub consume_hello {
     return %fields;
 }
 
+sub consume_dd {
+    my $packet = shift;
+
+    length($$packet) >= 8
+       or croak "dd packet too short: ". length($$packet);
+    my $dd = substr($$packet, 0, 8, "");
+    my %fields;
+    @fields{qw(interface_mtu options bits dd_sequence_number)} =
+       unpack("n C C N", $dd);
+    $fields{bits} <= 7
+       or croak "All bits except of I-, M- and MS-bit must be zero";
+
+    return %fields;
+}
+
 sub construct_hello {
     my $fields = shift;
 
@@ -255,4 +273,13 @@ sub construct_hello {
     return $packet;
 }
 
+sub construct_dd {
+    my $fields = shift;
+
+    my $packet = pack("n C C N",
+       @$fields{qw(interface_mtu options bits dd_sequence_number)});
+
+    return $packet;
+}
+
 1;
diff --git a/regress/usr.sbin/ospfd/args-ddstate.pl b/regress/usr.sbin/ospfd/args-ddstate.pl
new file mode 100644 (file)
index 0000000..72ed496
--- /dev/null
@@ -0,0 +1,44 @@
+use strict;
+use warnings;
+use Default qw($ospfd_ip $ospfd_rtrid);
+
+our %tst_args = (
+    client => {
+       tasks => [
+           {
+               name => "receive hello with dr 0.0.0.0 bdr 0.0.0.0, ".
+                   "enter $ospfd_rtrid as our neighbor",
+               check => {
+                   dr  => "0.0.0.0",
+                   bdr => "0.0.0.0",
+                   nbrs => [],
+               },
+               state => {
+                   nbrs => [ $ospfd_rtrid ],
+               },
+           },
+           {
+               name => "neighbor asserting itself as master. " .
+                   "We proclaim to be master, because of higher router id.",
+               wait => {
+                   dd_bits => 7, # I|M|MS
+               },
+               state => {
+                   dd_bits => 7,
+               },
+               timeout => 10, # not specified in rfc
+           },
+           {
+               name => "check if neighbor is slave, initialization is done ".
+                   "and neighbour has applied our dd sequence number.",
+               wait => {
+                   dd_bits => 0x2, # M
+                   dd_seq => 999,
+               },
+               timeout => 10, # not specified in rfc
+           },
+       ],
+    },
+);
+
+1;
index ce236c1..aa53bcf 100644 (file)
@@ -2,7 +2,6 @@
 
 use strict;
 use warnings;
-use Client;
 use Default qw($ospfd_ip $ospfd_rtrid);
 
 our %tst_args = (
index 20966a6..f9c5775 100644 (file)
@@ -4,7 +4,6 @@
 
 use strict;
 use warnings;
-use Client;
 use Default qw($area $tun_number $ospfd_ip $ospfd_rtrid);
 
 our %tst_args = (
index bd0e0c6..f0c3277 100644 (file)
@@ -4,7 +4,6 @@
 
 use strict;
 use warnings;
-use Client;
 use Default qw($area $tun_number $ospfd_ip $ospfd_rtrid);
 
 our %tst_args = (
index b451e5b..f1de202 100644 (file)
@@ -4,7 +4,6 @@
 
 use strict;
 use warnings;
-use Client;
 use Default qw($area $tun_number $ospfd_ip $ospfd_rtrid);
 
 our %tst_args = (
index 146680b..8f2eb16 100644 (file)
@@ -4,7 +4,6 @@
 
 use strict;
 use warnings;
-use Client;
 use Default qw($area $tun_number $ospfd_ip $ospfd_rtrid);
 
 our %tst_args = (
index 430d38f..e504bb3 100644 (file)
@@ -1,6 +1,5 @@
 use strict;
 use warnings;
-use Client;
 use Default qw($ospfd_ip $ospfd_rtrid);
 
 our %tst_args = (
index edfd798..bebb393 100644 (file)
@@ -3,7 +3,6 @@
 
 use strict;
 use warnings;
-use Client;
 use Default qw($ospfd_ip);
 
 our %tst_args = (