【Linux4.1.12源码分析】协议栈gro收包之TCP处理

本文深入分析了Linux4.1.12版本中TCP协议栈的gro收包机制,重点讨论了tcp4_gro_complete函数的四种情况:超过65536字节的同流报文提交、成功合并但无标志、合并后带标志的报文提交以及找不到同流报文时的处理策略。
摘要由CSDN通过智能技术生成

TCP gro实现定义在tcpv4_offload对象

static const struct net_offload tcpv4_offload = {
	.callbacks = {
		.gso_segment	=	tcp4_gso_segment,
		.gro_receive	=	tcp4_gro_receive,
		.gro_complete	=	tcp4_gro_complete,
	},
};
tcp4_gro_receive函数

static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
{
	/* Don't bother verifying checksum if we're going to flush anyway. */
	if (!NAPI_GRO_CB(skb)->flush &&
	    skb_gro_checksum_validate(skb, IPPROTO_TCP,
				      inet_gro_compute_pseudo)) {	//如果flush为0,需要检测csum
		NAPI_GRO_CB(skb)->flush = 1;	//如果检测失败则flush置1,报文将被提交到协议栈
		return NULL;
	}

	return tcp_gro_receive(head, skb);	//TCP gro receive处理,与IP协议无关
}
tcp_gro_receive函数

struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
{
	struct sk_buff **pp = NULL;
	struct sk_buff *p;
	struct tcphdr *th;
	struct tcphdr *th2;
	unsigned int len;
	unsigned int thlen;
	__be32 flags;
	unsigned int mss = 1;
	unsigned int hlen;
	unsigned int off;
	int flush = 1;
	int i;

	off = skb_gro_offset(skb);
	hlen = off + sizeof(*th);
	th = skb_gro_header_fast(skb, off);	//得到TCP头
	if (skb_gro_header_hard(skb, hlen)) {
		th = skb_gro_header_slow(skb, hlen, off);
		if (unlikely(!th))
			goto out;
	}

	thlen = th->doff * 4;	//得到TCP头的长度
	if (thlen < sizeof(*th))
		goto out;

	hlen = off + thlen;
	if (skb_gro_header_hard(skb, hlen)) {	//检测报文
		th = skb_gro_header_slow(skb, hlen, off);
		if (unlikely(!th))
			goto out;
	}

	skb_gro_pull(skb, thlen);	//报文移动到payload数据区

	len = skb_gro_len(skb);		//得到报文的数据区长度
	flags = tcp_flag_word(th);

	for (; (p = *head); head = &p-&g
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值