#! /usr/bin/perl # Check Linux media settings using ethtool # anders@fupp.net, 2007-09-19 use Getopt::Std; getopts('i:s:d:a:hm'); $ENV{'PATH'} = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"; sub usage { print "Usage: check_ethtool [-i ] [-s 10|100|1000|10000]\n"; print "[-m (speed is minimum)] [-d ] [-a (autoneg)] [-h (help)]\n"; exit(1); } if ($opt_h) { usage; } unless (defined($opt_a)) { $opt_a = "ignored"; } # Assume full duplex unless (defined($opt_d)) { $opt_d = "full"; } if ($opt_i) { $if = $opt_i; } else { # Try to guess interface name $iflist = `ip -o r get 8.8.8.8`; unless ($? == 0) { print "No ip command or problems with it? No interface specified with -i either.\n"; exit(2); } foreach $ifline (split(/\n/, $iflist)) { next if ($ifline =~ /bond/i); if ($ifline =~ /\s+dev\s+(\S+)/) { $if = $1; # Use first pick last; } } unless (defined($if)) { print "Could not find primary interface with ip command. No interface specified with -i either.\n"; exit(2); } } %modes = (); $ethlines = ""; foreach $line (`sudo ethtool $if 2>&1`) { chomp($line); $ethlines .= $line . "\n"; if ($line =~ /^(\s+|)([\w -]+):\s+(\w+)/) { $key = $2; $val = $3; $key =~ s@\s@_@g; $key =~ tr@A-Z@a-z@; $val =~ tr@A-Z@a-z@; if ($key eq "speed") { $val =~ s@\D+@@g; } if ($key eq "auto-negotiation") { $key = "autoneg"; } $modes{"$key"} = $val; } } if ($? != 0) { $ethlines =~ s@\n@ @g; $ethlines =~ s@\s{2,}@ @g; print "Ethtool exited with error: $ethlines\n"; exit(2); } if ($opt_s) { $speed = $opt_s; } else { $speed = 0; # if ($ethlines =~ /Advertised link modes:\s+(.*)\n\t\w/im) { if ($ethlines =~ /Supported link modes:\s+(.*?)\n\t\w/is) { # Grab modes over multiple lines $ethlines = $1; # Change any whitespace to space $ethlines =~ s@\s+@ @gs; # Strip non digits $ethlines =~ s@[^\d\s]@@g; foreach $sspeed (split(/\s+/, $ethlines)) { if ($sspeed > $curspeed) { $speed = $sspeed; } } # print "ethlines: $ethlines\n"; } } if ($speed == 0) { print "Could not find supported link modes for interface $if. No speed defined with -s either.\n"; exit 2; } $speedok = 0; if ($opt_m) { if ($modes{"speed"} >= $speed) { $speedok = 1; } $speedtxt = "minimum"; } else { if ($modes{"speed"} eq $speed) { $speedok = 1; } $speedtxt = "exact"; } # Do not care about autoneg if it is not supported if ($modes{"supports_auto-negotiation"} eq "no") { $opt_a = "ignored"; } if ($speedok == 0 || $opt_d ne $modes{"duplex"} || ($opt_a ne "ignored" && $opt_a ne $modes{"autoneg"})) { print "Media settings error on $if. Expected $speed ($speedtxt) $opt_d autoneg=$opt_a, got " . $modes{"speed"} . " " . $modes{"duplex"} . " " . $modes{"autoneg"} . "\n"; exit(2); } else { print "Media settings OK on $if " . $modes{"speed"} . " ($speedtxt match with $speed) " . $modes{"duplex"} . " autoneg=" . $modes{"autoneg"}; if ($opt_a eq "ignored") { print " (autoneg ignored)"; } print "\n"; exit(0); }