Linux内核:从上向下分析网络层IP协议
作者:网络转载 发布时间:[ 2013/1/6 10:08:12 ] 推荐标签:
这个函数中对长度过长的数据包进行了分片,ip_fragment()函数,该函数没有详细分析。
void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int is_frag)
{
struct iphdr *iph;
unsigned char *raw;
unsigned char *ptr;
struct sk_buff *skb2;
int left, mtu, hlen, len;
int offset;
unsigned long flags;
/*
* Point into the IP datagram header.
*/
raw = skb->data;
iph = (struct iphdr *) (raw + dev->hard_header_len);
skb->ip_hdr = iph;
/*
* Setup starting values.
*/
hlen = (iph->ihl * sizeof(unsigned long));
left = ntohs(iph->tot_len) - hlen; /* Space per frame */
hlen += dev->hard_header_len; /* Total header size */
mtu = (dev->mtu - hlen); /* Size of data space */
ptr = (raw + hlen); /* Where to start from */
/*
* Check for any "DF" flag. [DF means do not fragment]
*/
if (ntohs(iph->frag_off) & IP_DF)
{
/*
* Reply giving the MTU of the failed hop.
*/
ip_statistics.IpFragFails++;
icmp_send(skb,ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, dev->mtu, dev);
return;
}
/*
* The protocol doesn't seem to say what to do in the case that the
* frame + options doesn't fit the mtu. As it used to fall down dead
* in this case we were fortunate it didn't happen
*/
if(mtu<8)
{
/* It's wrong but it's better than nothing */
icmp_send(skb,ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED,dev->mtu, dev);
ip_statistics.IpFragFails++;
return;
}
/*
* Fragment the datagram.
*/
/*
* The initial offset is 0 for a complete frame. When
* fragmenting fragments it's wherever this one starts.
*/
if (is_frag & 2)
offset = (ntohs(iph->frag_off) & 0x1fff) << 3;
else
offset = 0;
/*
* Keep copying data until we run out.
*/
while(left > 0)
{
len = left;
/* IF: it doesn't fit, use 'mtu' - the data space left */
if (len > mtu)
len = mtu;
/* IF: we are not sending upto and including the packet end
then align the next start on an eight byte boundary */
if (len < left)
{
len/=8;
len*=8;
}
/*
* Allocate buffer.
*/
if ((skb2 = alloc_skb(len + hlen,GFP_ATOMIC)) == NULL)
{
printk("IP: frag: no memory for new fragment!
");
ip_statistics.IpFragFails++;
return;
}
/*
* Set up data on packet
*/
skb2->arp = skb->arp;
if(skb->free==0)
printk("IP fragmenter: BUG free!=1 in fragmenter
");
skb2->free = 1;
skb2->len = len + hlen;
skb2->h.raw=(char *) skb2->data;
/*
* Charge the memory for the fragment to any owner
* it might possess
*/
save_flags(flags);
if (sk)
{
cli();
sk->wmem_alloc += skb2->mem_len;
skb2->sk=sk;
}
restore_flags(flags);
skb2->raddr = skb->raddr; /* For rebuild_header - must be here */
/*
* Copy the packet header into the new buffer.
*/
memcpy(skb2->h.raw, raw, hlen);
/*
* Copy a block of the IP datagram.
*/
memcpy(skb2->h.raw + hlen, ptr, len);
left -= len;
skb2->h.raw+=dev->hard_header_len;
/*
* Fill in the new header fields.
*/
iph = (struct iphdr *)(skb2->h.raw/*+dev->hard_header_len*/);
iph->frag_off = htons((offset >> 3));
/*
* Added AC : If we are fragmenting a fragment thats not the
* last fragment then keep MF on each bit
*/
if (left > 0 || (is_frag & 1))
iph->frag_off |= htons(IP_MF);
ptr += len;
offset += len;
/*
* Put this fragment into the sending queue.
*/
ip_statistics.IpFragCreates++;
ip_queue_xmit(sk, dev, skb2, 2);//还是调用ip_queue_xmit()函数来发送分片后的数据
}
ip_statistics.IpFragOKs++;
}
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11