From e4c76de0829c06070481c1b0e2667042bc8ee67b Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Sun, 2 Feb 2014 09:23:30 -0500 Subject: [PATCH] Do not count empty SOL data as keepalive data If the console layer sends an SOL payload with zero data (which is valid to do) the session object would treat that as keeping the session alive on the BMC side. Many BMCs do not consider empty SOL payload packets toward session activity. Accomodate by having the keepalive deferral not be triggered by such packets. Change-Id: I8d278dbc48fae296c754ce9bc8f05bc92b560374 --- pyghmi/ipmi/console.py | 22 ++++++++++++++++------ pyghmi/ipmi/private/session.py | 13 +++++++++++-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/pyghmi/ipmi/console.py b/pyghmi/ipmi/console.py index 486c8481..f1feabc9 100644 --- a/pyghmi/ipmi/console.py +++ b/pyghmi/ipmi/console.py @@ -167,6 +167,10 @@ class Console(object): return session.Session.wait_for_rsp(timeout=timeout) def _sendpendingoutput(self): + self._sendoutput(self.pendingoutput) + self.pendingoutput = "" + + def _sendoutput(self, output): self.myseq += 1 self.myseq &= 0xf if self.myseq == 0: @@ -176,22 +180,26 @@ class Console(object): self.ackedseq, self.ackedseq, self.sendbreak) - payload += self.pendingoutput - self.lasttextsize = len(self.pendingoutput) - self.pendingoutput = "" + payload += output + self.lasttextsize = len(output) + needskeepalive = False + if self.lasttextsize == 0: + needskeepalive = True self.awaitingack = True payload = struct.unpack("%dB" % len(payload), payload) self.lastpayload = payload - self.send_payload(payload) + self.send_payload(payload, needskeepalive=needskeepalive) - def send_payload(self, payload, payload_type=1, retry=True): + def send_payload(self, payload, payload_type=1, retry=True, + needskeepalive=False): while not (self.connected or self.broken): session.Session.wait_for_rsp(timeout=10) if not self.ipmi_session.logged: raise exc.IpmiException('Session no longer connected') self.ipmi_session.send_payload(payload, payload_type=payload_type, - retry=retry) + retry=retry, + needskeepalive=needskeepalive) def _print_info(self, info): self._print_data({'info': info}) @@ -276,6 +284,8 @@ class Console(object): newtext = struct.pack("B"*len(newtext), *newtext) self.pendingoutput = newtext + self.pendingoutput self._sendpendingoutput() + if len(self.pendingoutput) > 0: + self._sendpendingoutput() elif self.awaitingack: # session marked us as happy, but we are not #this does mean that we will occasionally retry a packet #sooner than retry suggests, but that's no big deal diff --git a/pyghmi/ipmi/private/session.py b/pyghmi/ipmi/private/session.py index fa2398cb..0f541946 100644 --- a/pyghmi/ipmi/private/session.py +++ b/pyghmi/ipmi/private/session.py @@ -450,7 +450,16 @@ class Session(object): retry=retry, delay_xmit=delay_xmit) def send_payload(self, payload=None, payload_type=None, retry=True, - delay_xmit=None): + delay_xmit=None, needskeepalive=False): + """Send payload over the IPMI Session + + :param needskeepalive: If the payload is expected not to count as + 'active' by the BMC, set this to True + to avoid Session considering the + job done because of this payload. + Notably, 0-length SOL packets + are prone to confusion. + """ if payload is not None and self.lastpayload is not None: #we already have a packet outgoing, make this # a pending payload @@ -543,7 +552,7 @@ class Session(object): self.netpacket = struct.pack("!%dB" % len(message), *message) #advance idle timer since we don't need keepalive while sending packets #out naturally - if self in Session.keepalive_sessions: + if self in Session.keepalive_sessions and not needskeepalive: Session.keepalive_sessions[self]['timeout'] = _monotonic_time() + \ 25 + (random.random() * 4.9) self._xmit_packet(retry, delay_xmit=delay_xmit)