ip_frag_next没看懂的操作

struct sk_buff *ip_frag_next(struct sk_buff *skb, struct ip_frag_state *state)
{
	/* len初始为剩余长度 */
	unsigned int len = state->left;  ---|
	struct sk_buff *skb2;               |
	struct iphdr *iph;                  |?
                                        |
	len = state->left;------------------
	/* IF: it doesn't fit, use 'mtu' - the data space left */
	/* 根据mtu确认长度 */
	if (len > state->mtu)
		len = state->mtu;
	/* IF: we are not sending up to and including the packet end
	   then align the next start on an eight byte boundary */
	/* 除最后分片外,其余8字节对齐 */
	if (len < state->left)	{
		len &= ~7;
	}

	/* Allocate buffer */
	/* 分配skb */
	skb2 = alloc_skb(len + state->hlen + state->ll_rs, GFP_ATOMIC);
	if (!skb2)
		return ERR_PTR(-ENOMEM);

	/*
	 *	Set up data on packet
	 */
    /* 拷贝元数据 */
	ip_copy_metadata(skb2, skb);
	/* 预留空间,设置头部偏移 */
	skb_reserve(skb2, state->ll_rs);
	skb_put(skb2, len + state->hlen);
	skb_reset_network_header(skb2);
	skb2->transport_header = skb2->network_header + state->hlen;

	/*
	 *	Charge the memory for the fragment to any owner
	 *	it might possess
	 */
    /* 关联sk */
	if (skb->sk)
		skb_set_owner_w(skb2, skb->sk);

	/*
	 *	Copy the packet header into the new buffer.
	 */
    /* 拷贝头部 */
	skb_copy_from_linear_data(skb, skb_network_header(skb2), state->hlen);

	/*
	 *	Copy a block of the IP datagram.
	 */
	if (skb_copy_bits(skb, state->ptr, skb_transport_header(skb2), len))
		BUG();
	state->left -= len;

	/*
	 *	Fill in the new header fields.
	 */
	iph = ip_hdr(skb2);
	iph->frag_off = htons((state->offset >> 3));
	if (state->DF)
		iph->frag_off |= htons(IP_DF);

	/*
	 *	Added AC : If we are fragmenting a fragment that's not the
	 *		   last fragment then keep MF on each bit
	 */
	if (state->left > 0 || state->not_last_frag)
		iph->frag_off |= htons(IP_MF);
	state->ptr += len;
	state->offset += len;

	iph->tot_len = htons(len + state->hlen);

	ip_send_check(iph);

	return skb2;
}
EXPORT_SYMBOL(ip_frag_next);

你可能感兴趣的:(Linux源码解析,tcp/ip,网络协议,网络)