#!/usr/bin/perl

use strict;
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval nanosleep clock_gettime clock_getres clock_nanosleep clock stat );

my $i;
my $mx = $ARGV[0];
my $tp = $ARGV[1];
my $dv = "eth0";

if (! defined($tp)) {
  $tp = "macvlan";
}

print "Stopping udev-post, haldaemon, killing udevd.\n";
system("service udev-post stop");
system("service haldaemon stop");
system("killall udevd");

print "Creating $mx $tp.\n";

my $t0 = [gettimeofday];

for ($i = 0; $i<$mx; $i++) {
  my $cmd;
  if ($tp eq "macvlan") {
    my $nm = $dv . "#" . $i;
    $cmd = "./local/sbin/ip link add link $dv up name $nm type macvlan";
  }
  elsif ($tp eq "vlan") {
    my $nm = $dv . "." . $i;
    $cmd = "./local/sbin/ip link add link $dv up name $nm type vlan id $i";
  }
  elsif ($tp eq "veth") {
    my $nm = "veth$i";
    $cmd = "./local/sbin/ip link add link $dv up name $nm type veth peer name ${nm}b";
  }
  system($cmd);
}

my $took = tv_interval($t0);
my $per = $took / $mx;
print "Created $mx $tp in $took seconds ($per per interface).\n";

$t0 = [gettimeofday];
for ($i = 0; $i<$mx; $i++) {
  my $nm;
  if ($tp eq "macvlan") {
    $nm = $dv . "#" . $i;
  }
  elsif ($tp eq "vlan") {
    $nm = $dv . "." . $i;
  }
  elsif ($tp eq "veth") {
    $nm = "veth$i";
  }

  my $ip1 = $i % 250;
  my $ip2 = int($i / 250);
  my $cmd = "./local/sbin/ip addr add 10.1.${ip2}.${ip1} dev $nm";
  system($cmd);
  if ($tp eq "veth") {
    $nm = $nm . "b";
    $cmd = "./local/sbin/ip addr add 10.1.${ip2}.${ip1} dev $nm";
    system($cmd);
  }
}

my $took = tv_interval($t0);
my $per = $took / $mx;
print "Added IP addresses in $took seconds ($per per addr).\n";

$t0 = [gettimeofday];
for ($i = 0; $i<$mx; $i++) {
  my $nm;
  if ($tp eq "macvlan") {
    $nm = $dv . "#" . $i;
  }
  elsif ($tp eq "vlan") {
    $nm = $dv . "." . $i;
  }
  elsif ($tp eq "veth") {
    $nm = "veth$i";
  }
  my $cmd = "./local/sbin/ip link delete $nm";
  system($cmd);
}

my $took = tv_interval($t0);
my $per = $took / $mx;
print "Deleted $mx $tp in $took seconds. ($per per interface)\n";
