//ip分片
// 快速路径的条件:
// 1.skb
// 1.skb的数据长度(主缓存区+frags缓存区)小于输出路径的mtu
// 2.skb的数据长度对齐到8字节的边界
// 3.skb没有被分片
// 4.skb没有被共享
// 2.skb->frag_list
// 1.长度小于(mtu-ip报头-选项)
// 2.除最后一个分片外,长度都需要对齐到8字节边界
// 3.head-data之间的空间,可以容纳ip报头
// 注:skb->frag_list的skb,没有填充ip头,skb填充有ip头
//
// 慢速路径条件:
// 只要不满足快速路径其中的一条,使用慢速路径
// 快速路径处理过程:
// 1.第一个分片使用完整的ip选项
// 2.其余分片使用部分ip选项
// 3.除最后一个分片外,设置MF标志
// 4.设置offset
// 5.使用相同的路由信息,向下层传递
// 慢速路径处理过程:
// 1.分配新的skb,长度为mtu,或者剩余数据量,对齐到8字节边界
// 2.预留l2帧头空间
// 3.拷贝l3报头,以及数据到新skb中
// 4.除第一个分片使用完整的ip选项,其余分片使用部分ip选项
// 5.设置offset
// 5.使用相同的路由信息,向下层传递
// 对比快速路径与慢速路径:
// 1.慢速路径的慢主要表现在分配新的缓存区,从旧缓存区中拷贝数据
// 注:ip报头的offset字段,只针对有效载荷(ip头,ip选项不包括在内)
//调用路径ip_output/ip_mc_output->ip_fragment
1.1 int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
{
struct iphdr *iph;
int raw = 0;
int ptr;
struct net_device *dev;
struct sk_buff *skb2;
unsigned int mtu, hlen, left, len, ll_rs;
int offset;
int not_last_frag;
struct rtable *rt = (struct rtable*)skb->dst;
int err = 0;
//出口设备
dev = rt->u.dst.dev;
//ip头
iph = skb->nh.iph;
//ip报头设置有DF标志,禁止分片
skb->local_df如果被设置,则在需要分片,但是设置DF标志,不向发送方传送ICMP消息
if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,/
网络子系统51_ip协议报文分片
最新推荐文章于 2022-06-12 21:40:28 发布