From a011a88653145536d065ba5e2bd029e3771231ea Mon Sep 17 00:00:00 2001 From: "Zane C. Bowers-Hadley" Date: Sat, 10 Jun 2023 15:55:57 -0500 Subject: [PATCH] add Linux Softnet Stat extend (#470) --- snmp/linux_softnet_stat | 144 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100755 snmp/linux_softnet_stat diff --git a/snmp/linux_softnet_stat b/snmp/linux_softnet_stat new file mode 100755 index 0000000..f7987a3 --- /dev/null +++ b/snmp/linux_softnet_stat @@ -0,0 +1,144 @@ +#!/usr/bin/env perl + +=head1 DESCRIPTION + +This is a SNMP extend for monitoring /proc/net/softnet_stat on Linux for use with LibreNMS. + +For more information, see L. + +=head1 SWITCHES + +=head2 -p + +Pretty print the JSON. If used with -b, this switch will be ignored. + +=head2 -b + +Gzip the output and convert to Base64. + +=cut + +use strict; +use warnings; +use JSON; +use Getopt::Std; +use File::Slurp; +use MIME::Base64; +use Gzip::Faster; + +$Getopt::Std::STANDARD_HELP_VERSION = 1; + +sub main::VERSION_MESSAGE { + print "Linux softnet stats extend 0.0.1\n"; +} + +sub main::HELP_MESSAGE { + +} + +#this will be dumped to json at the end +my %tojson; +$tojson{totals} = { + backlog_length => 0, + cpu_collision => 0, + flow_limit => 0, + packet_dropped => 0, + packets => 0, + received_rps => 0, + time_squeeze => 0, +}; +$tojson{cores} = []; +$tojson{core_count} = 0; +$tojson{budget} = `sysctl net.core.netdev_budget 2> /dev/null`; +$tojson{budget_usecs} = `sysctl net.core.netdev_budget_usecs 2> /dev/null`; +chomp( $tojson{budget} ); +chomp( $tojson{budget_usecs} ); +$tojson{budget} =~ s/.*\=[\ \t]*//; +$tojson{budget_usecs} =~ s/.*\=[\ \t]*//; + +if ( $tojson{budget} !~ /^[0-9]+$/ ) { + $tojson{budget} = 'unknown'; +} +if ( $tojson{budget_usecs} !~ /^[0-9]+$/ ) { + $tojson{budget_usecs} = 'unknown'; +} + +#gets the options +my %opts = (); +getopts( 'pb', \%opts ); + +my $j = JSON->new; + +if ( $opts{p} && !$opts{b} ) { + $j->pretty(1); + $j->canonical(1); +} + +## +## read it all in +## + +my $lines_raw = read_file('/proc/net/softnet_stat'); +my @lines_split = split( /\n/, $lines_raw ); + +# not all linux kernel versions include softnet_backlog_len or index +my @to_total = keys( %{ $tojson{totals} } ); +foreach my $line (@lines_split) { + my %found; + ( + $found{packets}, $found{packet_drop}, $found{time_squeeze}, $found{zero4}, + $found{zero5}, $found{zero6}, $found{zero7}, $found{zero8}, + $found{cpu_collision}, $found{received_rps}, $found{flow_limit}, $found{backlog_length}, + $found{index} + ) = split( /[\ \t]+/, $line ); + + push( + @{ $tojson{cores} }, + { + core => $tojson{core_count}, + } + ); + + foreach my $item (@to_total) { + if ( !defined( $found{$item} ) ) { + $found{$item} = 0; + } else { + $found{$item} = hex( $found{$item} ); + } + $tojson{totals}{$item} += $found{$item}; + $tojson{cores}[ $tojson{core_count} ]{$item} = $found{$item}; + } + + $tojson{core_count}++; +} ## end foreach my $line (@lines_split) + +## +## print the results +## + +my %head_hash; +$head_hash{'data'} = \%tojson; +$head_hash{'version'} = 1; +$head_hash{'error'} = 0; +$head_hash{'errorString'} = ''; + +my $return_string = $j->encode( \%head_hash ); + +if ( !$opts{p} && !$opts{b} ) { + print $return_string. "\n"; + exit 0; +} elsif ( !$opts{b} ) { + print $return_string; + exit 0; +} + +my $compressed = encode_base64( gzip($return_string) ); +$compressed =~ s/\n//g; +$compressed = $compressed . "\n"; +if ( length($compressed) > length($return_string) ) { + print $return_string. "\n"; +} else { + print $compressed; +} + +exit 0;