void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
const struct tcphdr *th, unsigned int len)
{
/*
* Standard slow path.
*/
if (!tcp_validate_incoming(sk, skb, th, 1))
return;
step5:
if (tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0)
goto discard;
tcp_rcv_rtt_measure_ts(sk, skb);
/* Process urgent data. */
tcp_urg(sk, skb, th);
/* step 7: process the segment text */
tcp_data_queue(sk, skb);
tcp_data_snd_check(sk);
tcp_ack_snd_check(sk);
return;
}
/* This routine deals with incoming acks, but not outgoing ones. */
static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
{
/* See if we can take anything off of the retransmit queue. */
acked = tp->packets_out;
flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, sack_rtt);
acked -= tp->packets_out;
}
/* Remove acknowledged frames from the retransmission queue. If our packet
* is before the ack sequence we can discard it as it's confirmed to have
* arrived at the other end.
*/
static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
u32 prior_snd_una, s32 sack_rtt)
{
while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) {
struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
if (after(scb->end_seq, tp->snd_una)) {
fully_acked = false;
}
if (!fully_acked)
break;
tcp_unlink_write_queue(skb, sk);
sk_wmem_free_skb(sk, skb);
if (skb == tp->retransmit_skb_hint)
tp->retransmit_skb_hint = NULL;
if (skb == tp->lost_skb_hint)
tp->lost_skb_hint = NULL;
}
}
---------------------------------------------------------------------------------------
int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t size)
{
while (seglen > 0) {
skb = tcp_write_queue_tail(sk);
if (copy <= 0) {
new_segment:
/* Allocate new segment. If the interface is SG,
* allocate skb fitting to single page.
*/
if (!sk_stream_memory_free(sk))
goto wait_for_sndbuf;
skb = sk_stream_alloc_skb(sk,
select_size(sk, sg),
sk->sk_allocation);
if (!skb)
goto wait_for_memory;
skb_entail(sk, skb);
}
}
---------------------------------------------------------------------------------------
debug kernel 3.13.1
丢出的信息:
[ 56.403621] sendto() len = 560
[ 56.403628] tcp_sendmsg() 1210 skb->len = 560 tmp = 0!
[ 56.403635] ip_finish_output2() skb->len = 612
[ 56.403724] sendto() len = 4095
[ 56.403748] tcp_sendmsg() 1210 skb->len = 4095 tmp = 560!
[ 56.403756] ip_finish_output2() skb->len = 2948
[ 56.403862] sendto() len = 4095
[ 56.403880] tcp_sendmsg() 1210 skb->len = 5294 tmp = 2896!
丢信息的代码如下:
1.tcp.c
tcp_sendmsg(){
while (seglen > 0) {
struct sk_buff *tmp;
tmp = skb->prev;
printk("tcp_sendmsg() 1210 skb->len = %d tmp = %d!\n",skb->len,tmp->len);
}
2.ip_output.c
static inline int ip_finish_output2(struct sk_buff *skb)
{
if (!IS_ERR(neigh)) {
int res = 0;
printk("ip_finish_output2() skb->len = %d\n",skb->len);
res = dst_neigh_output(dst, neigh, skb);
rcu_read_unlock_bh();
return res;
}
}
阅读(1494) | 评论(0) | 转发(0) |