コード例 #1
0
ファイル: timer.c プロジェクト: wanggx/Linux1.0
/* 每个struct sock的时钟函数 */
void
net_timer (unsigned long data)
{
  struct sock *sk = (struct sock*)data;
  /* 相当于获取时钟的类型吧, */
  int why = sk->timeout;
  /* timeout is overwritten by 'delete_timer' and 'reset_timer' */

  /* 判断sock是否已被其他进程使用,或者当前是否正在执行网络的下半部分,
    * 如果当前正在执行网络的下半部分,则重新设置sock的timer,同时添加到
    * 内核时钟当中,等待下次执行 
    */
  if (sk->inuse || in_inet_bh()) {
    sk->timer.expires = 10;
    add_timer(&sk->timer);
    return;
  }

  /* 设置sock为用 */
  sk->inuse = 1;

  DPRINTF ((DBG_TMR, "net_timer: found sk=%X why = %d\n", sk, why));
  if (sk->wfront && 
      before(sk->window_seq, sk->wfront->h.seq) &&
      sk->send_head == NULL &&
      sk->ack_backlog == 0 &&
      sk->state != TCP_TIME_WAIT)
    reset_timer(sk, TIME_PROBE0, sk->rto);
  else if (sk->keepopen)
    reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);

  /* Always see if we need to send an ack. */
  /* 看看还有没有收到的数据包没有应答 */
  if (sk->ack_backlog) {
    /* sock发送确认数据包*/
    sk->prot->read_wakeup (sk);
    if (! sk->dead)
      wake_up_interruptible (sk->sleep);
  }

  /* Now we need to figure out why the socket was on the timer. */
  switch (why) {
    case TIME_DONE:
	if (! sk->dead || sk->state != TCP_CLOSE) {
	  printk ("non dead socket in time_done\n");
	  release_sock (sk);
	  break;
	}
	destroy_sock (sk);
	break;
    case TIME_DESTROY:
	/* We've waited for a while for all the memory associated with
	 * the socket to be freed.  We need to print an error message.
	 */
	/* 如果sock的发送缓冲区和接收缓冲区都为空,则直接在后面的语句当中释放 */
	if(sk->wmem_alloc!=0 || sk->rmem_alloc!=0)
	{
		DPRINTF ((DBG_TMR, "possible memory leak.  sk = %X\n", sk));
		sk->wmem_alloc++;	/* So it DOESNT go away */
		destroy_sock (sk);
		sk->wmem_alloc--;	/* Might now have hit 0 - fall through and do it again if so */
		sk->inuse = 0;	/* This will be ok, the destroy won't totally work */
	}
	if(sk->wmem_alloc==0 && sk->rmem_alloc==0)
		destroy_sock(sk);	/* Socket gone, DONT update sk->inuse! */
	break;
    case TIME_CLOSE:
	/* We've waited long enough, close the socket. */
	sk->state = TCP_CLOSE;
	delete_timer (sk);
	/* Kill the ARP entry in case the hardware has changed. */
	arp_destroy_maybe (sk->daddr);
	if (!sk->dead)
	  wake_up_interruptible (sk->sleep);
	sk->shutdown = SHUTDOWN_MASK;
	reset_timer (sk, TIME_DESTROY, TCP_DONE_TIME);
	release_sock (sk);
	break;
    case TIME_PROBE0:   /* 窗口探测定时器,也被称为坚持定时器 */
	tcp_send_probe0(sk);
	release_sock (sk);
	break;
    case TIME_WRITE:	/* 超时重传定时器 */   /* try to retransmit. */
	/* It could be we got here because we needed to send an ack.
	 * So we need to check for that.
	 */
	if (sk->send_head) {
	  if (jiffies < (sk->send_head->when + sk->rto)) {
	    reset_timer (sk, TIME_WRITE, 
			 (sk->send_head->when + sk->rto - jiffies));
	    release_sock (sk);
	    break;
	  }
	  /* printk("timer: seq %d retrans %d out %d cong %d\n", sk->send_head->h.seq,
	     sk->retransmits, sk->packets_out, sk->cong_window); */
	  DPRINTF ((DBG_TMR, "retransmitting.\n"));
          /* 调用tcp协议的超时重传函数 */
	  sk->prot->retransmit (sk, 0);
	  if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
	    || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) {
	    DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 1\n"));
	    arp_destroy_maybe (sk->daddr);
	    ip_route_check (sk->daddr);
	  }
	  if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) {
	    DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 2\n"));
	    sk->err = ETIMEDOUT;
	    if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2
	      || sk->state == TCP_LAST_ACK) {
	      sk->state = TCP_TIME_WAIT;
	      reset_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
	    } else {
	      sk->prot->close (sk, 1);
	      break;
	    }
	  }
	}
	release_sock (sk);
	break;
    case TIME_KEEPOPEN:          /* 保活定时器 */
	/* Send something to keep the connection open. */
	if (sk->prot->write_wakeup)
	  sk->prot->write_wakeup (sk);
	sk->retransmits++;  /* 因为是重发定时,所以会增加超时重发次数 */
	if (sk->shutdown == SHUTDOWN_MASK) {
	  sk->prot->close (sk, 1);
	  sk->state = TCP_CLOSE;
	}

	if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
	  || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) {
	  DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 1\n"));
	  arp_destroy_maybe (sk->daddr);
	  ip_route_check (sk->daddr);
	  release_sock (sk);
	  break;
	}
	if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) {
	  DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 2\n"));
	  arp_destroy_maybe (sk->daddr);
	  sk->err = ETIMEDOUT;
	  if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) {
	    sk->state = TCP_TIME_WAIT;
	    if (!sk->dead)
	      wake_up_interruptible (sk->sleep);
	    release_sock (sk);
	  } else {
	    sk->prot->close (sk, 1);
	  }
	  break;
	}
	release_sock (sk);
	break;
    default:
	printk ("net timer expired - reason unknown, sk=%08X\n", (int)sk);
	release_sock (sk);
	break;
  }
}
コード例 #2
0
ファイル: tcp_timer.c プロジェクト: rohsaini/mkunity
void tcp_retransmit_timer(unsigned long data)
{
	struct sock *sk = (struct sock*)data;
	int why = sk->ip_xmit_timeout;

	/*
	 *	We are reset. We will send no more retransmits.
	 */
	 
	if(sk->zapped)
		return;
		
	/* 
	 *	Only process if socket is not in use
	 */

	if (sk->users) 
	{
		/* Try again in 1 second */
		sk->retransmit_timer.expires = jiffies+HZ;
		add_timer(&sk->retransmit_timer);
		return;
	}

	if (sk->ack_backlog && !sk->dead) 
		sk->data_ready(sk,0);

	/* Now we need to figure out why the socket was on the timer. */

	switch (why) 
	{
	/* Window probing */
	case TIME_PROBE0:
		tcp_send_probe0(sk);
		tcp_write_timeout(sk);
		break;

	/* Retransmitting */
	case TIME_WRITE:
		tcp_time_write_timeout(sk);
		break;

	/* Sending Keepalives */
	case TIME_KEEPOPEN:
		/* 
		 * this reset_timer() call is a hack, this is not
		 * how KEEPOPEN is supposed to work.
		 */
		tcp_reset_xmit_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
		/* Send something to keep the connection open. */
		if (sk->prot->write_wakeup)
			  sk->prot->write_wakeup (sk);
		sk->retransmits++;
		sk->prot->retransmits++;
		tcp_write_timeout(sk);
		break;

	default:
		printk (KERN_ERR "rexmit_timer: timer expired - reason unknown\n");
		break;
	}
}