Beispiel #1
0
/**
 * @skb_list can be invalid after the function call, don't try to use it.
 */
static void
ss_do_send(struct sock *sk, SsSkbList *skb_list)
{
	struct tcp_sock *tp = tcp_sk(sk);
	struct sk_buff *skb;
	int size, mss = tcp_send_mss(sk, &size, MSG_DONTWAIT);

	SS_DBG("%s: cpu=%d sk=%p queue_empty=%d send_head=%p"
	       " sk_state=%d mss=%d size=%d\n", __func__,
	       smp_processor_id(), sk, tcp_write_queue_empty(sk),
	       tcp_send_head(sk), sk->sk_state, mss, size);

	if (unlikely(!ss_sock_active(sk)))
		return;
	ss_sock_cpu_check(sk);

	while ((skb = ss_skb_dequeue(skb_list))) {
		skb->ip_summed = CHECKSUM_PARTIAL;
		skb_shinfo(skb)->gso_segs = 0;

		/*
		 * TODO Mark all data with PUSH to force receiver to consume
		 * the data. Currently we do this for debugging purposes.
		 * We need to do this only for complete messages/skbs.
		 * Actually tcp_push() already does it for the last skb.
		 * MSG_MORE should be used, probably by connection layer.
		 */
		tcp_mark_push(tp, skb);

		SS_DBG("%s: entail skb=%p data_len=%u len=%u\n",
		       __func__, skb, skb->data_len, skb->len);

		ss_skb_entail(sk, skb);

		tp->write_seq += skb->len;
		TCP_SKB_CB(skb)->end_seq += skb->len;
	}

	SS_DBG("%s: sk=%p send_head=%p sk_state=%d\n", __func__,
	       sk, tcp_send_head(sk), sk->sk_state);

	tcp_push(sk, MSG_DONTWAIT, mss, TCP_NAGLE_OFF|TCP_NAGLE_PUSH, size);
}
/*
 * BST_TMR_DELAY_SOCK_SYNC timeout.
 * If sock is ready, get sock sync properties and post them to daemon
 */
static void delay_sock_bastet_timeout(struct sock *sk)
{
	int err;
	struct bst_set_sock_sync_prop sock_p;
	struct bastet_sock *bsk = sk->bastet;

	/* Accurating time */
	if (time_after(bsk->bastet_timeout, jiffies)) {
		sk_reset_timer(sk, &bsk->bastet_timer, bsk->bastet_timeout);
		return;
	}

	/* We must reset timer event, bastet_delay_sock_sync_notify depends on it
	 * this code must be put after accurating time
	 */
	bsk->bastet_timer_event = BST_TMR_EVT_INVALID;

	/* In repair mode or userspace needs repair, do not sync sock */
	if (unlikely(tcp_sk(sk)->repair || bsk->need_repair)) {
		BASTET_LOGE("sk: %p in repair mode", sk);
		return;
	}

	if (TCP_ESTABLISHED != sk->sk_state) {
		BASTET_LOGE("sk: %p sk_state is not TCP_ESTABLISHED", sk);
		return;
	}

	if (BST_SOCK_VALID != bsk->bastet_sock_state) {
		BASTET_LOGE("sk: %p state: %d not expected", sk, bsk->bastet_sock_state);
		return;
	}

	/* Sock owner has used since last setup */
	if (time_after(bsk->last_sock_active_time_point + bsk->delay_sync_time_section, jiffies)) {
		setup_sock_sync_delay_timer(sk);
		return;
	}

	/* Sock owner has some data unacked,
	 * Coming ack would trigger delay timer again */
	if (!tcp_write_queue_empty(sk)) {
		BASTET_LOGI("sk: %p has sent data not acked", sk);
		post_indicate_packet(BST_IND_TRIGGER_THAW, &bsk->pid, sizeof(pid_t));
		return;
	}

	/* Sock owner has some data to recv, do not sync.
	 * If sock owner has none recv action,
	 * delay timer should be stopped. */
	if (!skb_queue_empty(&sk->sk_receive_queue)) {
		BASTET_LOGI("sk: %p has received data in queue", sk);
		bsk->last_sock_active_time_point = jiffies;
		setup_sock_sync_delay_timer(sk);
		post_indicate_packet(BST_IND_TRIGGER_THAW, &bsk->pid, sizeof(pid_t));
		return;
	}

	memset(&sock_p, 0, sizeof(struct bst_set_sock_sync_prop));
	bastet_get_comm_prop(sk, &sock_p.guide);
	bastet_get_sock_prop(sk, &sock_p.sync_prop);

	err = post_indicate_packet(BST_IND_SOCK_SYNC_PROP, &sock_p, sizeof(sock_p));
	if (!err) {
		/* if post success */
		bsk->bastet_sock_state = BST_SOCK_INVALID;
	}
}