From 791598aeb17a30231ad141e11101f01f5025e705 Mon Sep 17 00:00:00 2001 From: jbjohnso Date: Mon, 10 Jan 2011 20:25:35 +0000 Subject: [PATCH] -Fix output when logout packet times out -Adjust RCVBUF as possible in IPMI to increase outstanding transactions when the default value is low. -Have IPMI throttle outstanding transactions based on the available size of the buffer to minimize UDP loss due to buffer overflow. git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@8599 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd --- xCAT-server/lib/perl/xCAT/IPMI.pm | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/xCAT-server/lib/perl/xCAT/IPMI.pm b/xCAT-server/lib/perl/xCAT/IPMI.pm index 426962c75..a8137dc95 100644 --- a/xCAT-server/lib/perl/xCAT/IPMI.pm +++ b/xCAT-server/lib/perl/xCAT/IPMI.pm @@ -18,6 +18,8 @@ use IO::Socket::INET; use IO::Select; use Data::Dumper; use Digest::MD5 qw/md5/; +my $pendingpackets=0; +my $maxpending; #determined dynamically based on rcvbuf detection my $ipmi2support = eval { require Digest::SHA1; Digest::SHA1->import(qw/sha1/); @@ -78,6 +80,19 @@ sub new { } unless ($socket) { $socket = IO::Socket::INET->new(Proto => 'udp'); + if (-r "/proc/sys/net/core/rmem_max") { # we can detect the maximum allowed socket, read it. + my $sysctl; + open ($sysctl,"<","/proc/sys/net/core/rmem_max"); + my $maxrcvbuf=<$sysctl>; + my $rcvbuf = $socket->sockopt(SO_RCVBUF); + if ($maxrcvbuf > $rcvbuf) { + $socket->sockopt(SO_RCVBUF,$maxrcvbuf/2); + } + $maxpending=$maxrcvbuf/1500; #probably could have maxpending go higher, but just go with typical MTU as a guess + } else { #We do not have a way to determine how high we could set RCVBUF, so read the current value and run with it + my $rcvbuf = $socket->sockopt(SO_RCVBUF); + $maxpending=$rcvbuf/1500; #probably could have maxpending go higher, but just go with typical MTU as a guess + } $select->add($socket); } my $bmc_n; @@ -124,7 +139,7 @@ sub logout { sub logged_out { my $rsp = shift; my $self = shift; - if ($rsp->{code} == 0) { + if (defined $rsp->{code} and $rsp->{code} == 0) { $self->{logged}=0; if ( $self->{onlogout}) { $self->{onlogout}->("SUCCESS",$self->{onlogout_args}); @@ -333,6 +348,7 @@ sub waitforrsp { if ($sessions_waiting{$_}->{timeout} <= $curtime) { #retry or fail.. my $session = $sessions_waiting{$_}->{ipmisession}; delete $sessions_waiting{$_}; + $pendingpackets-=1; $session->timedout(); next; } @@ -382,6 +398,7 @@ sub route_ipmiresponse { ($port,$host) = sockaddr_in($sockaddr); $host = inet_ntoa($host); if ($bmc_handlers{$host}) { + $pendingpackets-=1; $bmc_handlers{$host}->handle_ipmi_packet(@rsp); } } @@ -749,7 +766,11 @@ sub sendpayload { #push integrity data } } + while ($pendingpackets > $maxpending) { #if we hit our ceiling, wait until a slot frees up + $self->waitforrsp(); + } $socket->send(pack("C*",@msg),0,$self->{peeraddr}); + $pendingpackets+=1; if ($self->{sequencenumber}) { #if using non-zero, increment, otherwise.. $self->{sequencenumber} += 1; $self->{sequencenumberbytes} = [$self->{sequencenumber}&0xff,($self->{sequencenumber}>>8)&0xff,($self->{sequencenumber}>>16)&0xff,($self->{sequencenumber}>>24)&0xff];