Пример #1
0
static
void
ChargeAdd(int pktlen)
{
    struct timeval now;

    g_ctc_packets++;
    if (g_ctc_packets > TOPO_CTC_PACKETS_MAX)
	g_ctc_packets = TOPO_CTC_PACKETS_MAX;

    g_ctc_bytes += pktlen;
    if (g_ctc_bytes > TOPO_CTC_BYTES_MAX)
	g_ctc_bytes = TOPO_CTC_BYTES_MAX;

#ifdef  __DEBUG__
    IF_TRACED(TRC_CHARGE)
	dbgprintf("ChargeAdd: CTC now has bytes=" FMT_UINT32 " & packets=" FMT_UINT32 "\n",
		g_ctc_bytes, g_ctc_packets);
    END_TRACE
#endif

    /* Reset charge timer */
    gettimeofday(&now, NULL);
    timeval_add_ms(&now, TOPO_CHARGE_TIMEOUT);
    CANCEL(g_charge_timer);
    g_charge_timer = event_add(&now, state_charge_timeout, /*state:*/NULL);
}
Пример #2
0
static
void
ChargeConsume(int pktlen)
{
    struct timeval now;

    if (g_ctc_packets)
        g_ctc_packets--;

    if (g_ctc_bytes)
        g_ctc_bytes -= pktlen;

#ifdef  __DEBUG__
    IF_TRACED(TRC_CHARGE)
	dbgprintf("ChargeConsume: CTC now has bytes=" FMT_UINT32 " & packets=" FMT_UINT32 "\n",
		g_ctc_bytes, g_ctc_packets);
    END_TRACE
#endif

    /* Reset charge timer */

    gettimeofday(&now, NULL);
    timeval_add_ms(&now, TOPO_CHARGE_TIMEOUT);
    CANCEL(g_charge_timer);
    g_charge_timer = event_add(&now, state_charge_timeout, /*state:*/NULL);
}
Пример #3
0
void
band_ChooseHelloTime(void)
{
    band_t *b = &g_band;

    uint32_t delay = random_uniform(b->Ni);

    if (TRACE(TRC_BAND))
        dbgprintf("ChooseHelloTime: delay=%u; ", delay);

    /* if the delay falls within this block, set a timer to send the Hello */
    if (delay < BAND_ALPHA && !g_hello_timer)
    {
        struct timeval now;
        gettimeofday(&now, NULL);
        timeval_add_ms(&now, BAND_MUL_FRAME(delay));
        g_hello_timer = event_add(&now, state_hello_delay_timeout, /*state:*/NULL);
        if (TRACE(TRC_BAND))
            dbgprintf("will hello at %ld.%06ld\n", now.tv_sec, now.tv_usec);
    }
    else
    {
        if (TRACE(TRC_BAND))
            dbgprintf("idle this block, so no Hello\n");
    }
}
Пример #4
0
static void
_ipmidetectd_loop (void)
{
  struct pollfd *pfds = NULL;
  unsigned int i;

  _ipmidetectd_setup ();

  assert (nodes_count);

  /* +1 fd for the server fd */
  if (!(pfds = (struct pollfd *)malloc ((fds_count + 1)*sizeof (struct pollfd))))
    err_exit ("malloc: %s", strerror (errno));

  while (exit_flag)
    {
      struct timeval now, timeout;
      unsigned int timeout_ms;
      int num;

      if (gettimeofday (&now, NULL) < 0)
        err_exit ("gettimeofday: %s", strerror (errno));

      if (timeval_gt (&now, &ipmidetectd_next_send))
        {
          _ipmidetectd_send_pings ();

          if (gettimeofday (&now, NULL) < 0)
            err_exit ("gettimeofday: %s", strerror (errno));

          timeval_add_ms (&now, conf.ipmiping_period, &ipmidetectd_next_send);
        }

      _setup_pfds (pfds);

      timeval_sub (&ipmidetectd_next_send, &now, &timeout);
      timeval_millisecond_calc (&timeout, &timeout_ms);

      if ((num = poll (pfds, fds_count + 1, timeout_ms)) < 0)
        err_exit ("poll: %s", strerror (errno));

      if (num)
        {
          for (i = 0; i < fds_count; i++)
            {
              if (pfds[i].revents & POLLERR)
                _receive_ping (fds[i]);
              else if (pfds[i].revents & POLLIN)
                _receive_ping (fds[i]);
            }

          if (pfds[fds_count].revents & POLLIN)
            _send_ping_data ();
        }
    }
}
Пример #5
0
/* Restart the inactivity timer for the session associated with the current event */
void
restart_inactivity_timer(uint32_t timeout)
{
    struct timeval now;

    if (g_this_event.ssn == NULL  ||  g_this_event.ssn->ssn_is_valid != TRUE)   return;

    gettimeofday(&now, NULL);
    timeval_add_ms(&now, timeout);
    CANCEL(g_this_event.ssn->ssn_InactivityTimer);
    g_this_event.ssn->ssn_InactivityTimer = event_add(&now, state_inactivity_timeout, g_this_event.ssn);
}
Пример #6
0
void
band_InitStats(void)
{
    band_t *b = &g_band;
    struct timeval now;

    b->Ni = BAND_NMAX;
    b->r = BAND_BLOCK_TIME;
    b->begun = FALSE;

    if (TRACE(TRC_BAND))
        dbgprintf("InitStats: Ni=%u r=%u\n",
                  b->Ni, b->r);

    gettimeofday(&now, NULL);
    timeval_add_ms(&now, BAND_BLOCK_TIME);

    assert(g_block_timer == NULL);
    g_block_timer = event_add(&now, state_block_timeout, /*state:*/NULL);
}
Пример #7
0
void
band_UpdateStats(void)
{
    band_t *b = &g_band;
    struct timeval now;

    /* TODO: assumes platform timers are perfect!  Should really measure the time
     * now and calculate the actual time waited for. */
    uint32_t Ta = BAND_BLOCK_TIME;

    uint32_t value = BAND_MUL_FRAME(b->r * b->Ni) / (Ta * 1000);
    uint32_t bound = ((b->Ni * BAND_GAMMA) + (BAND_ALPHA * BAND_BETA -1))
                     / (BAND_ALPHA * BAND_BETA);
    b->Ni = TOPOMIN(100*BAND_NMAX, TOPOMAX(bound, value));

    if (b->begun) {
        if (b->Ni < BAND_NMAX/2) {
            b->Ni *= 2;
        } else if (b->Ni < BAND_NMAX) {
            b->Ni = BAND_NMAX;
        }
    }
    b->begun = FALSE;

    if (TRACE(TRC_BAND))
        dbgprintf("UpdateStats: Ni=%u r=%u\n",
                  b->Ni, b->r);

    if (!g_block_timer)
    {
        gettimeofday(&now, NULL);
        timeval_add_ms(&now, BAND_BLOCK_TIME);
        g_block_timer = event_add(&now, state_block_timeout, /*state:*/NULL);
    }
    else
    {
        warn("UpdateStats: block timer still running?!?\n");
    }
}
Пример #8
0
END_TEST

/*******************************************************************************
 * timeval_add_ms
 */

START_TEST(test_timeval_add_ms)
{
	timeval_t tv;

	tv.tv_sec = 0;
	tv.tv_usec = 0;
	timeval_add_ms(&tv, 0);
	ck_assert_int_eq(tv.tv_sec, 0);
	ck_assert_int_eq(tv.tv_usec, 0);

	timeval_add_ms(&tv, 1);
	ck_assert_int_eq(tv.tv_sec, 0);
	ck_assert_int_eq(tv.tv_usec, 1000);

	timeval_add_ms(&tv, 0);
	ck_assert_int_eq(tv.tv_sec, 0);
	ck_assert_int_eq(tv.tv_usec, 1000);

	timeval_add_ms(&tv, 999);
	ck_assert_int_eq(tv.tv_sec, 1);
	ck_assert_int_eq(tv.tv_usec, 0);

	timeval_add_ms(&tv, 0);
	ck_assert_int_eq(tv.tv_sec, 1);
	ck_assert_int_eq(tv.tv_usec, 0);

	timeval_add_ms(&tv, 1000);
	ck_assert_int_eq(tv.tv_sec, 2);
	ck_assert_int_eq(tv.tv_usec, 0);

	timeval_add_ms(&tv, 1500);
	ck_assert_int_eq(tv.tv_sec, 3);
	ck_assert_int_eq(tv.tv_usec, 500000);
}
Пример #9
0
bool_t
set_emit_timer(void)
{
    topo_emitee_desc_t *ed;

    assert(g_emit_remaining > 0);
    assert(g_emit_timer == NULL);

    /* get the next emitee_desc and schedule a callback when it is due
     * to be transmitted */
    ed = g_emitdesc;
    if (ed->ed_pause != 0)
    {
	struct timeval now;
	gettimeofday(&now, NULL);
	timeval_add_ms(&now, ed->ed_pause);
	g_emit_timer = event_add(&now, state_emit_timeout, NULL);
        return TRUE;
    } else {
	/* no pause; return PAUSE=FALSE */
	return FALSE;
    }
}
Пример #10
0
void
ipmipower_ping_process_pings (int *timeout)
{
  int i, send_pings_flag = 0;
  struct timeval cur_time, result;
  unsigned int ms_time;

  assert (timeout);

  if (!cmd_args.common_args.hostname)
    return;

  if (!cmd_args.ping_interval)
    return;

  if (gettimeofday (&cur_time, NULL) < 0)
    {
      IPMIPOWER_ERROR (("gettimeofday: %s", strerror (errno)));
      exit (EXIT_FAILURE);
    }

  if (timeval_gt (&cur_time, &next_ping_sends_time) || force_discovery_sweep)
    {
      force_discovery_sweep = 0;
      timeval_add_ms (&cur_time, cmd_args.ping_interval, &next_ping_sends_time);
      send_pings_flag++;
    }

  for (i = 0; i < ics_len; i++)
    {
      uint8_t buf[IPMIPOWER_PACKET_BUFLEN];
      int ret, len;

      if (send_pings_flag)
        {
          int dropped = 0;
          
          memset (buf, '\0', IPMIPOWER_PACKET_BUFLEN);

          /* deal with packet heuristics */
          if (cmd_args.ping_packet_count && cmd_args.ping_percent)
            {
              if (ics[i].ping_packet_count_send == cmd_args.ping_packet_count)
                {
                  if ((((double)(ics[i].ping_packet_count_send - ics[i].ping_packet_count_recv))/ics[i].ping_packet_count_send) > ((double)cmd_args.ping_percent/100))
                    ics[i].link_state = IPMIPOWER_LINK_STATE_BAD;
                  else
                    ics[i].link_state = IPMIPOWER_LINK_STATE_GOOD;

                  ics[i].ping_packet_count_send = 0;
                  ics[i].ping_packet_count_recv = 0;
                }
            }

          if (cmd_args.ping_consec_count)
            {
              if (!ics[i].ping_last_packet_recv_flag)
                ics[i].ping_consec_count = 0;
              ics[i].ping_last_packet_recv_flag = 0;
            }

          /* must increment count before setting message tag, so we
           * can check sequence number correctly later on
           */
          ics[i].ping_sequence_number_counter++;

	  /* Workaround
	   *
	   * Some motherboards don't support RMCP ping/pong :-(
	   *
	   * Discovered on Intel Windmill, Quanta Winterfell, and Wiwynn Windmill
	   */
	  if (cmd_args.common_args.section_specific_workaround_flags & IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING)
	    {
	      fiid_obj_t obj_rmcp_hdr = NULL;
	      fiid_obj_t obj_lan_session_hdr = NULL;
	      fiid_obj_t obj_lan_msg_hdr = NULL;
	      fiid_obj_t obj_cmd = NULL;

	      if (!(obj_rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (!(obj_lan_session_hdr = fiid_obj_create (tmpl_lan_session_hdr)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (!(obj_lan_msg_hdr = fiid_obj_create (tmpl_lan_msg_hdr_rq)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (!(obj_cmd = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rq)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (fill_rmcp_hdr_ipmi (obj_rmcp_hdr) < 0)
		{
		  IPMIPOWER_ERROR (("fill_rmcp_hdr_ipmi: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (fill_lan_session_hdr (IPMI_AUTHENTICATION_TYPE_NONE,
					0,
					0,
					obj_lan_session_hdr) < 0)
		{
		  IPMIPOWER_ERROR (("fill_lan_session_hdr: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (fill_lan_msg_hdr (IPMI_SLAVE_ADDRESS_BMC,
				    IPMI_NET_FN_APP_RQ,
				    IPMI_BMC_IPMB_LUN_BMC,
				    (ics[i].ping_sequence_number_counter % (IPMI_RQ_SEQ_MAX + 1)),
				    obj_lan_msg_hdr) < 0)
		{
		  IPMIPOWER_ERROR (("fill_lan_msg_hdr: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (fill_cmd_get_channel_authentication_capabilities (IPMI_CHANNEL_NUMBER_CURRENT_CHANNEL,
								    IPMI_PRIVILEGE_LEVEL_USER,
								    IPMI_GET_IPMI_V15_DATA,
								    obj_cmd) < 0)
		{
		  IPMIPOWER_ERROR (("fill_cmd_get_channel_authentication_capabilities: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if ((len = assemble_ipmi_lan_pkt (obj_rmcp_hdr,
						obj_lan_session_hdr,
						obj_lan_msg_hdr,
						obj_cmd,
						NULL,
						0,
						buf,
						IPMIPOWER_PACKET_BUFLEN,
						IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
		{
		  IPMIPOWER_ERROR (("assemble_ipmi_lan_pkt: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

#ifndef NDEBUG
	      if (cmd_args.rmcpdump)
		{
		  char hdrbuf[DEBUG_UTIL_HDR_BUFLEN];
		  const char *str_cmd = NULL;

		  str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES);

		  debug_hdr_str (DEBUG_UTIL_TYPE_IPMI_1_5,
				 DEBUG_UTIL_DIRECTION_REQUEST,
				 DEBUG_UTIL_FLAGS_DEFAULT,
				 str_cmd,
				 hdrbuf,
				 DEBUG_UTIL_HDR_BUFLEN);
		  
		  if (ipmi_dump_lan_packet (STDERR_FILENO,
					    ics[i].hostname,
					    hdrbuf,
					    NULL,
					    buf,
					    len,
					    tmpl_lan_msg_hdr_rq,
					    tmpl_cmd_get_channel_authentication_capabilities_rq) < 0)
		    IPMIPOWER_DEBUG (("ipmi_dump_lan_packet: %s", strerror (errno)));
		}
#endif /* NDEBUG */

	      fiid_obj_destroy (obj_rmcp_hdr);
	      fiid_obj_destroy (obj_lan_session_hdr);
	      fiid_obj_destroy (obj_lan_msg_hdr);
	      fiid_obj_destroy (obj_cmd);
	    }
	  else			/* !IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING */
	    {
	      fiid_obj_t rmcp_hdr = NULL;
	      fiid_obj_t rmcp_ping = NULL;

	      if (!(rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (!(rmcp_ping = fiid_obj_create (tmpl_cmd_asf_presence_ping)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (fill_rmcp_hdr_asf (rmcp_hdr) < 0)
		{
		  IPMIPOWER_ERROR (("fill_rmcp_hdr_asf: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (fill_cmd_asf_presence_ping ((ics[i].ping_sequence_number_counter %
					       (RMCP_ASF_MESSAGE_TAG_MAX + 1)),
					      rmcp_ping) < 0)
		{
		  IPMIPOWER_ERROR (("fill_cmd_asf_presence_ping: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if ((len = assemble_rmcp_pkt (rmcp_hdr,
					    rmcp_ping,
					    buf,
					    IPMIPOWER_PACKET_BUFLEN,
					    IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
		{
		  IPMIPOWER_ERROR (("assemble_rmcp_pkt: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

#ifndef NDEBUG
	      if (cmd_args.rmcpdump)
		{
		  char hdrbuf[DEBUG_UTIL_HDR_BUFLEN];
		  
		  debug_hdr_str (DEBUG_UTIL_TYPE_NONE,
				 DEBUG_UTIL_DIRECTION_NONE,
				 DEBUG_UTIL_FLAGS_DEFAULT,
				 DEBUG_UTIL_RMCPPING_STR,
				 hdrbuf,
				 DEBUG_UTIL_HDR_BUFLEN);
		  
		  if (ipmi_dump_rmcp_packet (STDERR_FILENO,
					     ics[i].hostname,
					     hdrbuf,
					     NULL,
					     buf,
					     len,
					     tmpl_cmd_asf_presence_ping) < 0)
		    IPMIPOWER_DEBUG (("ipmi_dump_rmcp_packet: %s", strerror (errno)));
		}
#endif /* NDEBUG */

	      fiid_obj_destroy (rmcp_hdr);
	      fiid_obj_destroy (rmcp_ping);
	    } /* !IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING */

          if ((ret = cbuf_write (ics[i].ping_out, buf, len, &dropped)) < 0)
            {
              IPMIPOWER_ERROR (("cbuf_write: %s", strerror (errno)));
              exit (EXIT_FAILURE);
            }

          if (ret != len)
            {
              IPMIPOWER_ERROR (("cbuf_write: incorrect bytes written %d", ret));
              exit (EXIT_FAILURE);
            }

          if (dropped)
            IPMIPOWER_DEBUG (("cbuf_write: dropped %d bytes", dropped));

          ics[i].last_ping_send.tv_sec = cur_time.tv_sec;
          ics[i].last_ping_send.tv_usec = cur_time.tv_usec;

          if (cmd_args.ping_packet_count && cmd_args.ping_percent)
            ics[i].ping_packet_count_send++;
        }

      /* Did we receive something? */
      memset (buf, '\0', IPMIPOWER_PACKET_BUFLEN);
      len = ipmipower_cbuf_peek_and_drop (ics[i].ping_in, buf, IPMIPOWER_PACKET_BUFLEN);
      if (len > 0)
        {
          uint8_t message_type = 0, ipmi_supported = 0;
          uint64_t val;

	  /* Workaround
	   *
	   * Some motherboards don't support RMCP ping/pong :-(
	   *
	   * Discovered on Intel Windmill, Quanta Winterfell, and Wiwynn Windmill
	   */
	  if (cmd_args.common_args.section_specific_workaround_flags & IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING)
	    {
	      fiid_obj_t obj_rmcp_hdr = NULL;
	      fiid_obj_t obj_lan_session_hdr = NULL;
	      fiid_obj_t obj_lan_msg_hdr = NULL;
	      fiid_obj_t obj_cmd = NULL;
	      fiid_obj_t obj_lan_msg_trlr = NULL;
	      int checksum_ret = 0;
	      int unassemble_ret = 0;
	      int cmd_ret = 0;

	      if (!(obj_rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (!(obj_lan_session_hdr = fiid_obj_create (tmpl_lan_session_hdr)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (!(obj_lan_msg_hdr = fiid_obj_create (tmpl_lan_msg_hdr_rs)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (!(obj_cmd = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rs)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (!(obj_lan_msg_trlr = fiid_obj_create (tmpl_lan_msg_trlr)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

#ifndef NDEBUG
	      if (cmd_args.rmcpdump)
		{
		  char hdrbuf[DEBUG_UTIL_HDR_BUFLEN];
		  const char *str_cmd = NULL;

		  str_cmd = ipmi_cmd_str (IPMI_NET_FN_APP_RQ, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES);

		  debug_hdr_str (DEBUG_UTIL_TYPE_IPMI_1_5,
				 DEBUG_UTIL_DIRECTION_RESPONSE,
				 DEBUG_UTIL_FLAGS_DEFAULT,
				 str_cmd,
				 hdrbuf,
				 DEBUG_UTIL_HDR_BUFLEN);
		  
		  if (ipmi_dump_lan_packet (STDERR_FILENO,
					    ics[i].hostname,
					    hdrbuf,
					    NULL,
					    buf,
					    len,
					    tmpl_lan_msg_hdr_rs,
					    tmpl_cmd_get_channel_authentication_capabilities_rs) < 0)
		    IPMIPOWER_DEBUG (("ipmi_dump_lan_packet: %s", strerror (errno)));
		}
#endif /* NDEBUG */

	      if ((checksum_ret = ipmi_lan_check_packet_checksum (buf, len)) < 0)
		{
		  IPMIPOWER_ERROR (("ipmi_lan_check_packet_checksum: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (checksum_ret
		  && ((unassemble_ret = unassemble_ipmi_lan_pkt (buf,
								 len,
								 obj_rmcp_hdr,
								 obj_lan_session_hdr,
								 obj_lan_msg_hdr,
								 obj_cmd,
								 obj_lan_msg_trlr,
								 IPMI_INTERFACE_FLAGS_DEFAULT)) < 0))
		{
		  IPMIPOWER_ERROR (("unassemble_ipmi_lan_pkt: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      /* achu: check for cmd type, but don't bother checking
	       * sequence numbers or completion code.  The fact it
	       * returns is sufficient.  We just need to make sure we
	       * get something back from the BMC to ensure the machine
	       * is still there.
	       */

	      if (checksum_ret
		  && unassemble_ret
		  && ((cmd_ret = ipmi_check_cmd (obj_cmd, IPMI_CMD_GET_CHANNEL_AUTHENTICATION_CAPABILITIES)) < 0))
		{
		  IPMIPOWER_ERROR (("ipmi_check_cmd: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}
	      
	      if (checksum_ret && unassemble_ret && cmd_ret)
		{
		  /* We'll say this is equivalent to what pong response from RMCP */
		  message_type = RMCP_ASF_MESSAGE_TYPE_PRESENCE_PONG;
		  ipmi_supported = 1;
		}

	      fiid_obj_destroy (obj_rmcp_hdr);
	      fiid_obj_destroy (obj_lan_session_hdr);
	      fiid_obj_destroy (obj_lan_msg_hdr);
	      fiid_obj_destroy (obj_cmd);
	      fiid_obj_destroy (obj_lan_msg_trlr);
	    }
	  else			/* !IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING */
	    {
	      fiid_obj_t rmcp_hdr = NULL;
	      fiid_obj_t rmcp_pong = NULL;

	      if (!(rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (!(rmcp_pong = fiid_obj_create (tmpl_cmd_asf_presence_pong)))
		{
		  IPMIPOWER_ERROR (("fiid_obj_create: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

#ifndef NDEBUG
	      if (cmd_args.rmcpdump)
		{
		  char hdrbuf[DEBUG_UTIL_HDR_BUFLEN];
		  
		  debug_hdr_str (DEBUG_UTIL_TYPE_NONE,
				 DEBUG_UTIL_DIRECTION_NONE,
				 DEBUG_UTIL_FLAGS_DEFAULT,
				 DEBUG_UTIL_RMCPPING_STR,
				 hdrbuf,
				 DEBUG_UTIL_HDR_BUFLEN);
		  
		  if (ipmi_dump_rmcp_packet (STDERR_FILENO,
					     ics[i].hostname,
					     hdrbuf,
					     NULL,
					     buf,
					     len,
					     tmpl_cmd_asf_presence_pong) < 0)
		    IPMIPOWER_DEBUG (("ipmi_dump_rmcp_packet: %s", strerror (errno)));
		}
#endif /* NDEBUG */

	      if ((ret = unassemble_rmcp_pkt (buf,
					      len,
					      rmcp_hdr,
					      rmcp_pong,
					      IPMI_INTERFACE_FLAGS_DEFAULT)) < 0)
		{
		  IPMIPOWER_ERROR (("unassemble_rmcp_pkt: %s", strerror (errno)));
		  exit (EXIT_FAILURE);
		}

	      if (ret)
		{
		  /* achu: check for ipmi_support and pong type, but don't
		   * check for message tag.  On occassion, I have witnessed
		   * BMCs send message tags "out of sync".  For example, you
		   * send 8, BMC returns 7.  You send 9, BMC returns 8.  We
		   * really don't care if the BMC is out of sync.  We just
		   * need to make sure we get something back from the BMC to
		   * ensure the machine is still there.
		   */
		  
		  if (FIID_OBJ_GET (rmcp_pong,
				    "message_type",
				    &val) < 0)
		    {
		      IPMIPOWER_ERROR (("FIID_OBJ_GET: 'message_type': %s",
					fiid_obj_errormsg (rmcp_pong)));
		      exit (EXIT_FAILURE);
		    }
		  message_type = val;
		  
		  if (FIID_OBJ_GET (rmcp_pong,
				    "supported_entities.ipmi_supported",
				    &val) < 0)
		    {
		      IPMIPOWER_ERROR (("FIID_OBJ_GET: 'supported_entities.ipmi_supported': %s",
					fiid_obj_errormsg (rmcp_pong)));
		      exit (EXIT_FAILURE);
		    }
		  ipmi_supported = val;
		}

	      fiid_obj_destroy (rmcp_hdr);
	      fiid_obj_destroy (rmcp_pong);
	    }

	  if (message_type == RMCP_ASF_MESSAGE_TYPE_PRESENCE_PONG && ipmi_supported)
	    {
	      if (cmd_args.ping_packet_count && cmd_args.ping_percent)
		ics[i].ping_packet_count_recv++;
	      
	      if (cmd_args.ping_consec_count)
		{
		  /* Don't increment twice, its possible a previous pong
		   * response was late, and we quickly receive two
		   * pong responses
		   */
		  if (!ics[i].ping_last_packet_recv_flag)
		    ics[i].ping_consec_count++;
		  
		  ics[i].ping_last_packet_recv_flag++;
		}
	      
	      if (cmd_args.ping_packet_count && cmd_args.ping_percent)
		{
		  if (ics[i].link_state == IPMIPOWER_LINK_STATE_GOOD)
		    ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_DISCOVERED;
		  else
		    {
		      if (cmd_args.ping_consec_count
			  && ics[i].ping_consec_count >= cmd_args.ping_consec_count)
			ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_DISCOVERED;
		      else
			ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_BADCONNECTION;
		    }
		}
	      else
		{
		  ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_DISCOVERED;
		}
	      ics[i].last_ping_recv.tv_sec = cur_time.tv_sec;
	      ics[i].last_ping_recv.tv_usec = cur_time.tv_usec;
	      
	    }
     	} /* !IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_IPMIPING */

      /* Is the node gone?? */
      timeval_sub (&cur_time, &ics[i].last_ping_recv, &result);
      timeval_millisecond_calc (&result, &ms_time);
      if (ms_time >= cmd_args.ping_timeout)
        ics[i].discover_state = IPMIPOWER_DISCOVER_STATE_UNDISCOVERED;
    }

  timeval_sub (&next_ping_sends_time, &cur_time, &result);
  timeval_millisecond_calc (&result, &ms_time);
  *timeout = ms_time;
}