Ejemplo n.º 1
0
/* called to setup the UL stack statistics/logging */
void
ci_tcp_stats_init(ci_netif* ni, ci_tcp_state* ts)
{
  int val;

  ci_assert( ni && ts );
  LOG_STATS( ci_log("%s(%p, %p)", __FUNCTION__, ni, ts ));

  ts->stats_fmt = CI_IP_STATS_OUTPUT_DEFAULT;
  val = CI_TCONST_STATS; /* mS */

  NI_CONF(ni).tconst_stats = val ? ci_tcp_time_ms2ticks(ni, val) : 0;
  
  LOG_STATS( ci_log("Statistics: %u ticks, %dmS, (format:%s)",
					NI_CONF(ni).tconst_stats, val,			 
					ts->stats_fmt ? "Text" : "XML" ));
  ci_tcp_stats_init_data( &ts->stats_snapshot );
  ci_tcp_stats_init_data( &ts->stats_cumulative );

  /* Setting the timeout to -1 implies collection through sockopt */
  if( val )
	ci_tcp_stats_action( ni, ts, CI_IP_STATS_START,
                         CI_IP_STATS_OUTPUT_DEFAULT, NULL, NULL );
}
Ejemplo n.º 2
0
void ci_tcp_listenq_insert(ci_netif* ni, ci_tcp_socket_listen* tls,
                           ci_tcp_state_synrecv* tsr)
{
  int is_first;

  tls->n_listenq++;

  ci_tcp_listenq_bucket_insert(ni, tls,
                               ci_ni_aux_p2bucket(ni, tls->bucket),
                               tsr, 0);

  if( OO_SP_NOT_NULL(tsr->local_peer) )
    return;

  is_first = ci_ni_dllist_is_empty(ni, &tls->listenq[0]);
  ci_ni_dllist_push_tail(ni, &tls->listenq[0], ci_tcp_synrecv2link(tsr));
  tsr->retries = 0;
  tsr->timeout = ci_tcp_time_now(ni) + NI_CONF(ni).tconst_rto_initial;

  ++tls->n_listenq_new;
  if( is_first )
    ci_tcp_listen_timer_set(ni, tls, tsr->timeout);
}
Ejemplo n.º 3
0
/* Called when the statistics report timer fires OR at start/end of
* the session or for a manual update through a sockopt 
* \param ni netif context
* \param ts TCP state context
* \param reason Action to perform
* \param type Type of output (0=default, 1 = text, 2 = XML)
* \param ptr Pointer to the memory where statistics is put on STATS_GET 
*            action. It has no sense with other actions and should be set to
*            NULL.
* \param which Type of statistics to report (TCP, netif or both)
*/
extern void ci_tcp_stats_action(__NI_STRUCT__ *ni,
                                __STATE_STRUCT__ *ts,
                                ci_ip_stats_action_type action,
                                ci_ip_stats_output_fmt fmt,
                                void *data,
                                socklen_t *size)
{
  ci_iptime_t it;

  ci_assert(ni);
  ci_assert( IPTIMER_STATE(ni) );
  ci_assert(ts);

  LOG_STATS( ci_log( "%s( %p, %p, %d, %d, %p )", __FUNCTION__, ni, ts, 
             action, fmt, data));

  /* update snapshot timestamp */
  ci_ip_time_get(IPTIMER_STATE(ni), &it);

  /* ci_ip_time_ticks2ms() is not defined in KERNEL space */
#ifndef __KERNEL__
  ts->stats_snapshot.now = ci_ip_time_ticks2ms(ni, it);
#endif

  switch (action) {
  case CI_IP_STATS_START:
    ci_tcp_stats_init_data( &ts->stats_snapshot);
    ci_tcp_stats_init_data( &ts->stats_cumulative);
    
    it = NI_CONF(ni).tconst_stats;
    ci_tcp_stats_handle_timer(ni, ts, it );
    break;
    
  case CI_IP_STATS_GET:
    if ((data != NULL) && (size != NULL) && (*size >= 2 * sizeof(ci_ip_stats))){
      /* assumed to be a valid user memory area to update */
      ci_ip_sock_stats* ii = (ci_ip_sock_stats*)data;
      memcpy( &ii[0], &ts->stats_snapshot, sizeof(*ii) );
      memcpy( &ii[1], &ts->stats_cumulative, sizeof(*ii));
      *size = 2 * sizeof(ci_ip_sock_stats);
    }
    break;

  case CI_IP_STATS_REPORT:
#if CI_CFG_SEND_STATS_TO_LOG
    ci_tcp_stats_report(ni, ts, ni->state->stats_fmt, NULL, 0);
#else
    if ((data != NULL) && (size != NULL)) 
    {
      *size = ci_tcp_stats_report(ni, ts, ni->state->stats_fmt, data, *size);
    }
#endif
    break;

  case CI_IP_STATS_END:
  case CI_IP_STATS_FLUSH:
    ci_tcp_stats_update( ts );

    /* Stop stats timer on CI_IP_STATS_END */
    it = action != CI_IP_STATS_END ? NI_CONF(ni).tconst_stats : 0;
    ci_tcp_stats_handle_timer(ni, ts, it );
    break;

  default:
    break;
  }
}
Ejemplo n.º 4
0
/* [fd] is unused in the kernel version */
int ci_tcp_getsockopt(citp_socket* ep, ci_fd_t fd, int level,
		      int optname, void *optval, socklen_t *optlen )
{
  ci_sock_cmn* s = ep->s;
#if defined(__linux__) || \
    defined(__sun__) && defined(TCP_KEEPALIVE_THRESHOLD) || \
    defined(__sun__) && defined(TCP_KEEPALIVE_ABORT_THRESHOLD)
  ci_tcp_socket_cmn *c = &(SOCK_TO_WAITABLE_OBJ(s)->tcp.c);
#endif
  ci_netif* netif = ep->netif;
  unsigned u = 0;

  /* NOTE: The setsockopt() call is reflected into the os socket to
   * keep the two in sync - it's assumed that we know everything
   * to allow us to give good answers here - and therefore we don't
   * bother the os with the get call */

  /* ?? what to do about optval and optlen checking
   * Kernel can raise EFAULT, here we are a little in the dark.
   *  - sockcall_intercept.c checks that optlen is non-NULL and if *optlen
   *    is non-zero that optval is non-NULL, returning EFAULT if false
   */

  if(level == SOL_SOCKET) {
    /* Common SOL_SOCKET handler */
    return ci_get_sol_socket(netif, s, optname, optval, optlen);

  } else if (level ==  IPPROTO_IP) {
    /* IP level options valid for TCP */
    return ci_get_sol_ip(ep, s, fd, optname, optval, optlen);

#if CI_CFG_FAKE_IPV6
  } else if (level ==  IPPROTO_IPV6 && s->domain == AF_INET6) {
    /* IP6 level options valid for TCP */
    return ci_get_sol_ip6(ep, s, fd, optname, optval, optlen);
#endif

  } else if (level == IPPROTO_TCP) {
    /* TCP level options valid for TCP */
    switch(optname){
    case TCP_NODELAY:
      /* gets status of TCP Nagle algorithm  */
      u = ((s->s_aflags & CI_SOCK_AFLAG_NODELAY) != 0);
      goto u_out;
    case TCP_MAXSEG:
      /* gets the MSS size for this connection */
      if ((s->b.state & CI_TCP_STATE_TCP_CONN)) {
        u = tcp_eff_mss(SOCK_TO_TCP(s));
      } else {
        u = 536;
      }
      goto u_out;
# ifdef TCP_CORK
    case TCP_CORK:
      /* don't send partial framses, all partial frames sent
      ** when the option is cleared */
      u = ((s->s_aflags & CI_SOCK_AFLAG_CORK) != 0);
      goto u_out;
# endif


    case TCP_KEEPIDLE:
      {
        /* idle time for keepalives  */
        u = (unsigned) c->t_ka_time_in_secs;
      }
      goto u_out;
    case TCP_KEEPINTVL:
      {
        /* time between keepalives */
        u = (unsigned) c->t_ka_intvl_in_secs;
      }
      goto u_out;
    case TCP_KEEPCNT:
      {
        /* number of keepalives before giving up */
        u = c->ka_probe_th;
      }
      goto u_out;
    case TCP_INFO:
      /* struct tcp_info to be filled */
      return ci_tcp_info_get(netif, s, (struct ci_tcp_info*) optval);
    case TCP_DEFER_ACCEPT:
      {
        u = 0;
        if( c->tcp_defer_accept != OO_TCP_DEFER_ACCEPT_OFF ) {
          u = ci_ip_time_ticks2ms(netif, NI_CONF(netif).tconst_rto_initial);
          u = ((u + 500) / 1000) << c->tcp_defer_accept;
        }
        goto u_out;
      }
    case TCP_QUICKACK:
      {
        u = 0;
        if( s->b.state & CI_TCP_STATE_TCP_CONN ) {
          ci_tcp_state* ts = SOCK_TO_TCP(s);
          u = ci_tcp_is_in_faststart(ts);
        }
        goto u_out;
      }
    default:
      LOG_TC( log(LPF "getsockopt: unimplemented or bad option: %i", 
                  optname));
      RET_WITH_ERRNO(ENOPROTOOPT);
    }
  } else {
    SOCKOPT_RET_INVALID_LEVEL(s);
  }

  return 0;

 u_out:
  return ci_getsockopt_final(optval, optlen, level, &u, sizeof(u));
}