- 作者: 雪山肥鱼
- 时间: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) 发出去。
逻辑地址+物理地址 是一对组合。互相映射。
静态映射
人工维护一张表
- 缺陷
- 一台机器有可能更换INC,就更新了 物理地址
- 某些局域网,如LocalTalk,每次其对应的物理地址都会改变
- 移动电脑可以从一个物理网,转移到另一个物理网络。会引起物理地址改变.(以太网 转移到 LocalTalkc 网)
以上动作都会导致静态表更新。增加网络性能开销。
动态映射
相对于静态映射,只有更换,就会刷新。
ARP 协议
![](https://img.haomeiwen.com/i25953572/d5d52cdee9f7ad64.png)
![](https://img.haomeiwen.com/i25953572/58e412821dcd8009.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的分组与封装
![](https://img.haomeiwen.com/i25953572/d50a3e0f7c2357bc.png)
ARP分组里面不仅有 mac和IP,还有其他的字段。
- 硬件类型:
定义ARP网络类型(物理/数据链路)。以太网类型是1
ARP可用在任何物理网络中 - 协议类型,ipv4 : 0800h
- 硬件长度
物理地址长度,以太网的MAC是6 - 协议长度
逻辑地址长度,ipv4 就是4 - 操作
ARP请求,ARP回答
封装:
![](https://img.haomeiwen.com/i25953572/3f72679e9b223c7c.png)
ARP 的操作
- 发送方知道对方IP,但不知道MAC
- IP请求ARP,创建一个ARP请求报文,填入发送方物理地址,发送方IP,及目标IP地址,MAC地址全部填0
- 交给数据链路层,封装成帧,广播
- 各个主机判断
- 符合目标IP的,用ARP报文进行回答。回答中包含了物理地址。单播方式转发
- 接受报文,知道目标物理地址了。存到ARP表中
- 发送IP报文,单播形式发出。
![](https://img.haomeiwen.com/i25953572/0011688353911570.png)
注意点:
- IP与16进制整数的转换
130.23.42.20 =》 0x82172B14 =》20 205 625 424 200多亿 - ARP 包含2次MAC地址
以太网帧头,与ARP分组中
四种情况
-
发送方是主机,发送给同一网络上的另一台主机。
单纯的主机IP
图片.png
-
发送方主机,发送给另一个网络上的主机。
主机查路由表,找到终点的下一跳,路由器的ip地址。如果没有,就找默认网关。则寻找 路由器的 ip+mac 的组合
图片.png
-
发送方是路由器,发给另一个网络主机的数据报文。
同上,只不过是路由器vs路由器之间的。
图片.png
-
路由器发给同一网络上的主机,同情况1
图片.png
代理ARP
起到子网划分的作用
定义:proxy ARP 代表了一组主机的ARP。当运行代理ARP的路由收到一个ARP请求,希望找到主机中的某一台mac地址时,路由器就返回自己的硬件mac地址。(有点ARP欺骗的意思)
![](https://img.haomeiwen.com/i25953572/dfb762659e22b300.png)
- 增加了一个运行代理ARP的路由器。这种情况下,路由器代表了所有安装子网上的主机。
- 收到一个目标地址 图中3者之一的arp请求。
- 代理arp回答自己的mac地址。当然 代理arp路由器与各个主机之间也有各自的arp表。
ARP的实现
架构:
![](https://img.haomeiwen.com/i25953572/0445d215d6cd05f9.png)
- 高速缓存表
- 队列
- 输出模块:将未得到mac地址的ip包发送到队列中
- 输入模块:从队列中取出分组,并连同解析出的物理地址封装发送到数据层
- 告诉缓存控制模块
高速缓存表
cache 作用。
包含字段
![](https://img.haomeiwen.com/i25953572/9e18f325ab047652.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
输出模块主要负责
- 没有表项,队列里hold住IP分组,发送ARP请求,
- 拿到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
输入模块主要负责:
- 收到ARP请求发送回复
- 收到回复,表中有就带着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
举例
![](https://img.haomeiwen.com/i25953572/c6f9216cb2c28b31.png)
- 输出模块收到一个IP数据报。并且状态是R。直接带着MAC地址发送
- 输出模块收到一个IP数据包,表项中无目的IP与mac映射关系。增加一个表项,状态值为Pending,且尝试次数+1,同时输出模块根据这个终点增加一个队列,暂存IP包。 最后发出ARP请求。
图片.png
-
输入模块收到一个ARP分组,将状态从P改为R,重置超时时间,发送队列数据包。
图片.png
图片.png
-
刷新表项,递减超时时间
图片.png
图片.png
网友评论