谈ARP

作者: 404Not_Found | 来源:发表于2021-10-25 14:05 被阅读0次
    • 作者: 雪山肥鱼
    • 时间:20211024 16:18
    • 目的: ARP 回顾
    # 为何需要ARP
    # 地址映射
      ## 静态映射
      ## 动态映射
    # ARP协议
      ## dpdk中解ARP
      ## ARP的分组与封装
      ## ARP的操作
      ## 代理ARP
    # ARP的实现
      ## 高速缓存表
      ## 队列
      ## 输出模块
      ## 输入模块
      ## 高速缓存控制模块
      ## 举例
    

    最近学习dpdk的一些代码,example的例子大多是arp与icmp 相关。于是又掏出<<TCP/IP协议族>>复习下。以前没有整理的习惯。今天整理一下。

    文中讨论的物理地址,均用以太网的MAC地址

    为何需要ARP

    网络层的IP协议,能够把分组从源主机,交付到目的主机,首先要知道 如何交给下一跳的。IP分组可以通过咨询路由表找出下一跳的地址。
    找到了又怎么处理呢?
    IP包,总归要经过数据链路层的,那么不仅要知道下一条的ip地址,同样也需要知道mac地址。

    如果获得同一网络下其他节点的mac地址?这就需要ARP协议。

    地址映射

    在IP层,逻辑地址即IP地址。ipv4 32位,ipv6 128位
    但是IP层的包需要通过物理层才能达到主机和路由器。在这一层,通过物理地址来识别。物理地址是一个本地地址,它的管辖范围是 本地网络

    • 物理地址在本地范围内必须唯一
      但全局上没有此要求。
    • 物理地址(并非总是)在硬件上实现。
      以太网mac 地址 只是物理地址的一个子集。是物理地址的一种,写在了主机or录音透气的网络接口卡(NIC)中。

    物理地址和IP 是两种不同的标识,但是我们都需要。一个物理地址可以为不同的网络层提供服务(IP/IPX),也就是网络层不仅有IP协议,也有IPX等其他协议。
    网络包(如IP协议组的)也可以通过不同的物理网,如以太网(MAC地址)和localtalk(Apple) 发出去。

    逻辑地址+物理地址 是一对组合。互相映射。

    静态映射

    人工维护一张表

    • 缺陷
    1. 一台机器有可能更换INC,就更新了 物理地址
    2. 某些局域网,如LocalTalk,每次其对应的物理地址都会改变
    3. 移动电脑可以从一个物理网,转移到另一个物理网络。会引起物理地址改变.(以太网 转移到 LocalTalkc 网)

    以上动作都会导致静态表更新。增加网络性能开销。

    动态映射

    相对于静态映射,只有更换,就会刷新。

    ARP 协议

    ARP在TCP/IP协议族中的位置.png arp流程.png

    实际上还是属于网络层,但是偏下,可以算得上是 物理层和IP层的枢纽。

    何时发送ARP:

    • 主机需要知道另一台主机or 路由器的 mac地址(也就是说它现在不知道),故而群发。
    • 收到者解包,发现不是自己的IP 则丢到,是则带上自己的mac地址 回复即可。

    dpdk 中 解 ARP

    所以在dpdk 解包的过程中,解udp, 解icmp 解icmp是不同的。

    1. udp:
    a) ether_hdr
    b) ether_type_ipv4
    c) ether_hdr ---> iphdr
    d) iphdr->next_protoal_id == IPPOTO_UDP
    
    2. icmp:
    a) ether_hdr
    b) ether_type_ipv4
    c) ether_hdr ---> iphdr
    d) iphdr ->icmphdr
    e) icmphdr->icmp_type == IP_ICMP_ECHO_REQUEST
    
    3. arp:
    a) ether_hdr
    b) ether_type_arp
    c) ether_hdr-> arp_hdr
    

    上述流程注意:arp 这一个解包,并没有优先匹配ipv4, 因为arp只存在于ipv4, ipv6 用RA/RS NA/NS 代替了 ARP 功能.

    ARP的分组与封装

    ARP 分组.png

    ARP分组里面不仅有 mac和IP,还有其他的字段。

    • 硬件类型:
      定义ARP网络类型(物理/数据链路)。以太网类型是1
      ARP可用在任何物理网络中
    • 协议类型,ipv4 : 0800h
    • 硬件长度
      物理地址长度,以太网的MAC是6
    • 协议长度
      逻辑地址长度,ipv4 就是4
    • 操作
      ARP请求,ARP回答

    封装:


    ARP分组封装.png

    ARP 的操作

    1. 发送方知道对方IP,但不知道MAC
    2. IP请求ARP,创建一个ARP请求报文,填入发送方物理地址,发送方IP,及目标IP地址,MAC地址全部填0
    3. 交给数据链路层,封装成帧,广播
    4. 各个主机判断
    5. 符合目标IP的,用ARP报文进行回答。回答中包含了物理地址。单播方式转发
    6. 接受报文,知道目标物理地址了。存到ARP表中
    7. 发送IP报文,单播形式发出。
    ARP 操作流程.png

    注意点:

    1. IP与16进制整数的转换
      130.23.42.20 =》 0x82172B14 =》20 205 625 424 200多亿
    2. ARP 包含2次MAC地址
      以太网帧头,与ARP分组中

    四种情况

    1. 发送方是主机,发送给同一网络上的另一台主机。
      单纯的主机IP


      图片.png
    2. 发送方主机,发送给另一个网络上的主机。
      主机查路由表,找到终点的下一跳,路由器的ip地址。如果没有,就找默认网关。则寻找 路由器的 ip+mac 的组合


      图片.png
    3. 发送方是路由器,发给另一个网络主机的数据报文。
      同上,只不过是路由器vs路由器之间的。


      图片.png
    4. 路由器发给同一网络上的主机,同情况1


      图片.png

    代理ARP

    起到子网划分的作用
    定义:proxy ARP 代表了一组主机的ARP。当运行代理ARP的路由收到一个ARP请求,希望找到主机中的某一台mac地址时,路由器就返回自己的硬件mac地址。(有点ARP欺骗的意思)

    举例.png
    1. 增加了一个运行代理ARP的路由器。这种情况下,路由器代表了所有安装子网上的主机。
    2. 收到一个目标地址 图中3者之一的arp请求。
    3. 代理arp回答自己的mac地址。当然 代理arp路由器与各个主机之间也有各自的arp表。

    ARP的实现

    架构:


    ARP架构.png
    1. 高速缓存表
    2. 队列
    3. 输出模块:将未得到mac地址的ip包发送到队列中
    4. 输入模块:从队列中取出分组,并连同解析出的物理地址封装发送到数据层
    5. 告诉缓存控制模块

    高速缓存表

    cache 作用。
    包含字段


    字段.png
    • 状态:
      free: 生存周期已到,可以清空
      pending:请求已经发出,但未收到
      resolved:完成映射
    • 接口号:一个路由器or网络主机能够连接到多个不同的网络,每个连接都有不同的接口好。每个网络还可能有不同的硬件类型和协议类型
    • 队列号:ARP使用带编号的队列把等待地址解析的分组进行排队。发往同一个终点的分组通常放在同一个队列中。
    • 尝试: 发了多少次arp
    • 超时: 生存时间

    队列

    一组队列,每个队列对应一个终点,用来ARP尝试解析硬件地址时暂存IP分组的地方。
    输出模块把未解析的分组发送到相应(以目的分组)队列。
    输入模块从队列中取出分组,打包,发送给数据层传输。

    输出模块

    ARP_Output_Module( ) 
    {
      睡眠,直至收到来自IP软件的IP分组
      检查告诉缓存表,寻找这个IP分组终点对应的表项。
      if(找到)
      {
          if(状态是RESOLVED)
          {
              从该表项中提取出硬件地址的值
              把分组联通硬件地址一起发送到数据链路层
              返回
          }//end if
          if(状态是Pending) //既然是pending,说明就已经准备好了一个队列
          {
              把IP分组放入相应的队列(目标IP)
              返回
          }
      }//end if
      if(未找到)
      {
          创建一个高速缓存表项,状态设置为Pending;Attempts设置为1
          创建一个队列(目标IP)
          把分组放入队列中
          发送一个ARP请求
          返回
      }//endif
    }//end module
    

    输出模块主要负责

    1. 没有表项,队列里hold住IP分组,发送ARP请求,
    2. 拿到MAC或者 表项中存在,就带着MAC 发包

    输入模块

    ARP_Input_Module()
    {
      睡眠,直到一个ARP分组(请求or回答)到达
      检查高速缓存表,寻找相应的表项
      if(找到)
      {
        更新表项 //Pending -> Resolved, 同时增加超时时间
        if(状态是Pending)//下次进来就不是Pending,是Resolved了
        {
          while(相应的队列非空)
          {
            从队列中取出一个分组
            将该分组连同硬件地址一起发送
          }//endif
        }//endif
      }//endif
      if(未找到)
      {
        创建一个表项
        新建表象加入表中
      }//endif
      if(分组是请求分组)
      {
        发送ARP回答
      }//endif
      返回
    }//end module
    

    输入模块主要负责:

    1. 收到ARP请求发送回复
    2. 收到回复,表中有就带着mac发数据,表中没有就,创建表项

    高速缓存控制模块

     ARP_Cache_Control_Module()
    {
      睡眠,直至计时器到时
      Repeat for 高速缓存表中的每一项
      {
        if(状态为free)
        {
            继续
        }//endif
        if(状态是Pending)
        {
           Attemp value +1
           if(尝试次数大于最大数)
           {
              把状态改为free
              撤销相应队列
           }//endif
           else
           {
              发送一个ARP请求
           }// endif
           继续
        }//endif
        if(状态为Resloved)
        {
            递减超时字段的值
            if(超时字段的值小于or = 0)
            {
                状态置为free
                撤销相应队列
            }//endif
        }//endif
      }//end repeat
      返回
    }//end module
    

    举例

    图片.png
    1. 输出模块收到一个IP数据报。并且状态是R。直接带着MAC地址发送
    2. 输出模块收到一个IP数据包,表项中无目的IP与mac映射关系。增加一个表项,状态值为Pending,且尝试次数+1,同时输出模块根据这个终点增加一个队列,暂存IP包。 最后发出ARP请求。
      图片.png
    3. 输入模块收到一个ARP分组,将状态从P改为R,重置超时时间,发送队列数据包。


      图片.png
      图片.png
    4. 刷新表项,递减超时时间


      图片.png
      图片.png

    相关文章

      网友评论

          本文标题:谈ARP

          本文链接:https://www.haomeiwen.com/subject/xkzkaltx.html