《TCP/IP具体解释卷2:实现》笔记–IP:网际协议

《TCP/IP具体解释卷2:实现》笔记–IP:网际协议

大家好,又见面了,我是全栈君。

本章介绍IP分组的结构和主要的IP处理过程,包含输入,转发和输出。

下图显示了IP层常见的组织形式。

《TCP/IP具体解释卷2:实现》笔记--IP:网际协议

在之前的文章中。我们看到了网络接口怎样把到达的IP分组放到IP输入队列ipintrq中去,并怎样调用一个软件中断,例如以下图所看到的:

《TCP/IP具体解释卷2:实现》笔记--IP:网际协议

由于硬件中断的优先级比软件中断的要高,所以在发生一次软件中断之前。有的分组可能会被放到队列中。在软件中断中,ipintr

函数不断从ipintrq中移走和处理分组,直到对垒为空。在终于的目的地,IP把分组重装为数据包,并通过函数调用把该数据包直接

传给适当的运输层协议。假设分组没有到达最后的目的地,而且假设主机被配置成一个路由器,则IP把分组传给ip_forward。传输

协议和ip_forward把要输出的分组传给ip_output。由ip_output完毕ip首部,选择输出接口以及在必要时对分组分片。终于的分组

被传给合适的网络接口输出函数。

当产生差错时,IP丢弃该分组,并在某些条件下向分组的源站发出一个差错报文。这些报文是ICMP的一部分。

1.IP分组

我们把传输层协议交给IP的数据称为报文。典型的报文包括一个传输层首部和应用程序数据。下图所看到的的传输协议时UDP。IP在报

文的首部前加上它自己的首部形成一个数据包。假设在选定的网络中。数据报长度太大。IP就把数据包分裂成几个分片,每一个分片

包括它自己的IP首部和一段原来的数据报的数据。

《TCP/IP具体解释卷2:实现》笔记--IP:网际协议

下图显示了IP首部的结构。

《TCP/IP具体解释卷2:实现》笔记--IP:网际协议

下图包括了IP结构中的各成员的名字

《TCP/IP具体解释卷2:实现》笔记--IP:网际协议

《TCP/IP具体解释卷2:实现》笔记--IP:网际协议

标准的IP首部长度是20个字节,所以ip_hl必须大于等于5.大于5表示IP选项紧跟在标准首部后。如ip_hl的最大值为15,同意最多

40各字节的选项。ip_hl是以4字节为单位计算的。

2.输入处理:ipintr函数

当接口把分组放到ipintrq上排队后。通过schednetisr调用一个软中断。当该软中断发生时,假设IP处理过程已经由schednetisr

调度。则内核调用ipintr。在调用ipintr之前。cpu的优先级被改成splnet。

ipintr是一个大函数,主要分4部分讨论:

1.对到达分组验证

2.选项处理及转发

3.分组重装

4.分用

当中选项处理和分用重装比較复杂,会在以后作为单独的章节进行说明。

2.1.验证

把分组从ipintrq中取出,验证他们的内容。损坏和有差错的分组被自己主动丢弃。
IP版本号:
假设网络接口没有指派IP地址,则必须丢掉全部的IP分组。
在ipintr訪问不论什么IP首部字段之前,它必须证实ip_v是4.
IP首部检验和:
ipintr把由in_cksum计算出来的检验和保存首部的ip_sum字段中。

一个未被破坏的首部应该具有0检验和。假设为非0,则该

分组被自己主动丢弃。

以下的章节详细介绍in_cksum。

3.字节顺序
NTOHS宏将IP首部中的全部16bit的值从网络字节序转换成主机字节序:分组长度(ip_len)、数据报标识符(ip_id)和分片
偏移(ip_off)。
4.分组长度
假设分组的逻辑长度(ip_len)比存储在mbuf中的数据量(m_pkthdr.len)大。而且有些字节被丢失了。就必须丢弃该分组,
假设mbuf比分组大,则去掉多余的字节。

丢失字节的一个常见原因是由于数据到达某个没有或仅仅有非常少缓存的串口设备,设备丢弃到达的字节。

多余字节可能产生,如在某个以太网设备上,当一个IP分组的大小比以太网要求的最小长度还要小时。发送该帧是加上的多余
字节就在这里被丢弃。

2.2.选项处理和转发

接下来调用ip_dooptions来处理IP选项,然后决定分组是否到达它最后的目的地。

假设分组没有到达最后目的地,则Net/3会

尝试转发该分组;假设分组到达最后目的地,就被交付给合适的传输层协议。

1.选项处理

ip_dooptions处理选项,假设ip_dooptions返回0,ipintr将继续处理该分组;否则ip_dooptions通过转发或丢弃分组完毕对该

分组的处理。ipintr能够处理输入队列中的下一个分组。

处理完选项后,ipintr通过把ip首部内的ip_dst与配置的全部本地接口的ip地址比較。以决定分组是否已经到达终于目的地。

ipintr

必须考虑与接口相关的几个广播地址、一个或多个单播地址以及随意多个多播地址。

2.转发

假设ip_dst与全部地址都不匹配,分组还没有达到终于目的地。

假设不准备转发,则丢弃分组,否则。ip_forward尝试把分组路由

到它的终于目的地。

2.3.分组重装和分用

ipintr函数最后进行分组的重组和分组。在后面的章节会具体进行介绍。

最后ipintr调用选定protosw结构中的pr_input函数来处理数据报包括的运输报文,当pr_input返回时,ipintr继续处理ipintrq中的

下一个分组。

3.IP头部检验:in_cksum函数

IP首部校验和的计算方法:
  1.把校验和字段清零。

  2.然后对每16位(2字节)进行二进制反码求和,反码求和的意思是先对每16位求和,再将得到的和转为反码。
  接下来具体描写叙述反码求和的步骤:看以下的代码
  基本算法:

SHORT checksum(USHORT* buffer, int size){    unsigned long cksum = 0;    while(size>1)    {        cksum += *buffer++;        size -= sizeof(USHORT);    }    if(size)    {        cksum += *(UCHAR*)buffer;    }    cksum = (cksum>>16) + (cksum&0xffff);     cksum += (cksum>>16);     return (USHORT)(~cksum);}

  參数buffer是指向16位整数的指针,刚開始指向的是IP首部的起始地址,參数size是IP首部的大小。while循环是将IP首部的内容
以16位为单元加在一起。假设没有整除(即size还有余下的不足16位的部分)。则加上余下的部分,此时的cksum就是相加后的结
果。这个结果往往超出了16位。由于校验和是16位的,所以要将高16位和计算得到的cksum再加工。
  再加工第一步:cksum = (cksum>>16) + (cksum&0xffff); sum>>16是将高16位移位到低16位,sum&0xffff是取出低16位,相加得到新的cksum。
  再加工第二步:cksum += (cksum>>16); 第一步相加时非常可能会产生进位,因此要再次把进位移到低16位进行相加。  
  这样就加工好了,接下来就是取反。并强制转换为16位,这样就得到了终于的校验和。

  校验和计算出来了,接下来就是该怎样校验:
  接收方进行校验时,也是对每16位进行二进制反码求和。

接收方计算校验和时的首部与发送方计算校验和时的首部相比。多了一

个发送方计算出来的校验和。

因此,假设首部在传输过程中没有发生差错。那么接收方计算的结果应该为全一。由于接收方计算除

校验和以外的部分得到值是校验和的反码。再加多出来的校验和当然是全一了。

  最后对上述过程举个样例:
  IP头:
  45 00    00 31
  89 F5    00 00
  6E 06    00 00(校验字段)
  DE B7   45 5D       ->    222.183.69.93
  C0 A8   00 DC     ->    192.168.0.220
  计算:  
  4500 + 0031 +89F5 + 0000 + 6e06+ 0000 + DEB7 + 455D + C0A8 + 00DC =3 22C4
  0003 + 22C4 = 22C7
  ~22C7 = DD38      ->即为应填充的校验和
  当接受到IP数据包时,要检查IP头是否正确,则对IP头进行检验,方法同上:
  计算:
  4500 + 0031 +89F5 + 0000 + 6E06+ DD38 + DEB7 + 455D + C0A8 + 00DC =3 FFFC
  0003 + FFFC = FFFF
  得到的结果是全一。正确。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/115327.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【SSM – SpringMVC篇】09 SpringMVC拦截器Interceptor详解,多个拦截器的执行顺序,拦截器进行权限判断和日志记录,拦截器和过滤器的区别

    【SSM – SpringMVC篇】09 SpringMVC拦截器Interceptor详解,多个拦截器的执行顺序,拦截器进行权限判断和日志记录,拦截器和过滤器的区别配置图文,超详细!!SpringMVC拦截器Interceptor详解,多个拦截器的执行顺序,拦截器进行权限判断和日志记录,拦截器和过滤器的区别

    2022年7月25日
    17
  • ubuntu12.04 安装配置jdk1.7

    ubuntu12.04 安装配置jdk1.7

    2021年12月14日
    46
  • java.lang.ClassNotFoundException: okio.ForwardingTimeout 已解决

    java.lang.ClassNotFoundException: okio.ForwardingTimeout 已解决这个问题发现是由于版本问题引起的,下面是我用的两个jar源码对比:先看看okio-1.13.0.jar的,会发现在forwardingSource下面有ForwardingTimeout这个类下面是okio-2.0.0.jar包,会发现那个ForwardingTimeout没了,不知道官方改成什么了我用okhttp-3.8.0.jar引用okio-2.0.0.jar的时候就会…

    2022年5月29日
    103
  • 博客目录与概览

    从即日起,我将开始开始着手写作《深入理解机器学习》分类下的文章。《深入理解机器学习》不仅仅把目光局限机器学习算法的推导与实现,更多的会将目光聚焦于从数学、统计学以及统计学习的角度来深入理解机器学习算法,除此之外,我还会讨论各个机器学习算法局限与瓶颈,纵横向比较各种机器学习算法的优劣等。在详细介绍机器学习算法的同时,我还会通过Python和Scala给出相关项目的实战代码。所以,想深入学习机器学习的…

    2022年4月6日
    39
  • 差模信号和共模信号彻底理解_形容理解的不全面

    差模信号和共模信号彻底理解_形容理解的不全面前言AOP英文名为AspectOrientedProgramming,意为面向切面编程,通过预编译方式和运行期间动态代理实现程序功能统一维护的一种技术。AOP是OOP的延续,是Spring框架中的一个重要内容,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。通过以上定义似乎还是不能理解AOP到底是什么,下面通过一个现实中的实例来说明。先看一下传统程序的流程,比如银行系统会有一个取款流程我们可以把方框里的流程

    2022年8月11日
    5
  • 电商网站的商品详情页系统架构

    电商网站的商品详情页系统架构电商网站的商品详情页系统架构1小型电商架构:小型电商网站的页面展示采用页面全量静态化的思想。数据库中存放了所有的商品信息,页面静态化系统,将数据填充进静态模板中,形成静态化页面推入Nginx服务器。用户浏览网站页面时,取用一个已经静态化好的html页面,例如freemarker,thymeleaf等,直接返回回去,不涉及任何的业务逻辑处理。例如下面一个简单的魔板…

    2022年9月26日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号