#!/usr/bin/perl

use strict;
use NF2::RegressLib;
use NF2::PacketLib;
use RegressRouterLib;

use reg_defines_reference_router;

my $NUM_PORTS = 2;
my $NUM_PKTS = 300;

sleep 4;

my @interfaces = ("nf2c0", "nf2c1", "nf2c2", "nf2c3", "eth1", "eth2");
nftest_init(\@ARGV,\@interfaces,);
nftest_start(\@interfaces);


my $routerMAC0 = "00:ca:fe:00:00:01";
my $routerMAC1 = "00:ca:fe:00:00:02";
my $routerMAC2 = "00:ca:fe:00:00:03";
my $routerMAC3 = "00:ca:fe:00:00:04";

my $routerIP0 = "192.168.0.40";
my $routerIP1 = "192.168.1.40";
my $routerIP2 = "192.168.2.40";
my $routerIP3 = "192.168.3.40";

my $dstIP0 = "192.168.0.50";

my $dstMac0 = "aa:bb:cc:dd:ee:01";
my $dstMac1 = "aa:bb:cc:dd:ee:02";
my $dstMac2 = "aa:bb:cc:dd:ee:03";
my $dstMac3 = "aa:bb:cc:dd:ee:04";

my $ALLSPFRouters = "224.0.0.5";


# Write the mac and IP addresses
nftest_add_dst_ip_filter_entry ('nf2c0', 0, $routerIP0);
nftest_add_dst_ip_filter_entry ('nf2c1', 1, $routerIP1);
nftest_add_dst_ip_filter_entry ('nf2c2', 2, $routerIP2);
nftest_add_dst_ip_filter_entry ('nf2c3', 3, $routerIP3);
nftest_add_dst_ip_filter_entry ('nf2c0', 4, $ALLSPFRouters);
nftest_add_dst_ip_filter_entry ('nf2c0', 5, $dstIP0);


nftest_set_router_MAC ('nf2c0', $routerMAC0);
nftest_set_router_MAC ('nf2c1', $routerMAC1);
nftest_set_router_MAC ('nf2c2', $routerMAC2);
nftest_set_router_MAC ('nf2c3', $routerMAC3);

my $total_errors = 0;
my $temp_val = 0;

for (my $portid = 0; $portid < $NUM_PORTS ; $portid++) {
  # Clear the counters
  nftest_regwrite("nf2c0", ROUTER_OP_LUT_NUM_FILTERED_PKTS_REG(), 0);


  # set parameters
  my $DA = ($portid == 0) ? $routerMAC0 : $routerMAC1;
  my $SA = "aa:bb:cc:dd:ee:ff";
  my $EtherType = 0x800;
  my $TTL = 64;
  my $DST_IP = $dstIP0;
  my $SRC_IP = "192.168.0.1";;
  my $VERSION = 0x4;
  my $nextHopMAC = "dd:55:dd:66:dd:77";


  # create mac header
  my $MAC_hdr = NF2::Ethernet_hdr->new(DA => $DA,
				       SA => $SA,
				       Ethertype => $EtherType
				      );

  #create IP header
  my $IP_hdr = NF2::IP_hdr->new(ttl => $TTL,
				version => $VERSION,
				src_ip => $SRC_IP,
				dst_ip => $DST_IP
			       );

  # precreate random packets
  my @portPkts = nftest_precreate_pkts($NUM_PKTS, $MAC_hdr->packed . $IP_hdr->packed);

  # loop for 300 packets 
  for (my $i = 0; $i < $NUM_PKTS ; $i++) {
    # get packed packet string
    my $sent_pkt = $portPkts[int(rand($NUM_PKTS))];

    if ($portid == 0) {
      # send packet out of eth1->nf2c0 
      nftest_send('eth1', $sent_pkt);
      nftest_expect('nf2c0', $sent_pkt);
    } elsif ($portid == 1) {
      # send packet out of eth2->nf2c1 
      nftest_send('eth2', $sent_pkt);
      nftest_expect('nf2c1', $sent_pkt);
    } else {
      print "ERROR: Not a valid port \n";
    }
  }
  sleep 4;

  # Read the counters

    $temp_val = nftest_regread_expect('nf2c0', ROUTER_OP_LUT_NUM_FILTERED_PKTS_REG, $NUM_PKTS);
    # print "20 $temp_error_val \n";
    if ($temp_val != $NUM_PKTS) {
      print "Expected $NUM_PKTS destination IP filter packets Received $temp_val\n";
      $total_errors++;
    }
}

#-------------------
my $unmatched_hoh = nftest_finish();

while ( my ($ifacename, $ref) = each(%$unmatched_hoh) ) {
  while ( my ($pkt, $count) = each(%$ref) ) {
    my $unpacked_pkt = unpack('H*', $pkt);
    if ($count < 0) {
      $count = -$count;
      print "Missing packets on $ifacename:\n   $unpacked_pkt\n    with count $count\n";
    } else {
      print "Unexpected packets on $ifacename:\n   $unpacked_pkt\n    with count $count\n";
    }
    $total_errors += $count;
  }
}
# -------------

if ($total_errors==0) {
  print "SUCCESS!\n";
  exit 0;
} else {
  print "FAIL: $total_errors errors\n";
  exit 1;
}

