当ARP缓存溢出时会发生什么?

网络工程 路由器 路由 锦缎 arp
2021-07-24 16:07:34

在至少一种实现中,对 ARP 表的容量存在硬限制。当 ARP 缓存已满并且数据包提供的目的地(或下一跳)未缓存时会发生什么?幕后发生了什么,对服务质量有什么影响?

例如,Brocade NetIron XMR 和 Brocade MLX 路由器具有可配置的ip-arp系统最大值这种情况下的默认值为 8192;/19 子网的大小。从文档中不清楚这是针对每个接口还是针对整个路由器,但出于这个问题的目的,我们可以假设它是针对每个接口的。

很少有网络人员会故意在接口上配置 /19 子网,但事实并非如此。我们正在将核心路由器从 Cisco 型号迁移到 Brocade。Cisco 和 Brocade 之间的众多差异之一是 Cisco 接受使用出站接口和下一跳地址定义的静态路由,但 Brocade 坚持其中之一。我们丢弃了下一跳地址并保留了接口。后来,我们知道了我们的方式的错误,并从接口更改为下一跳地址,但最初似乎一切正常。

+----+ iface0    +----+
| R1 |-----------| R2 |---> (10.1.0.0/16 this way)
+----+.1       .2+----+
      10.0.0.0/30

在迁移之前,R1 是 Cisco,并且有以下路由。

ip route 10.1.0.0 255.255.0.0 iface0 10.0.0.2

迁移后,R1是Brocade,有如下路由。

ip route 10.1.0.0 255.255.0.0 iface0

R2是Cisco路由器,Cisco路由器默认执行代理ARP这是生产中的(错误)配置,它为结果是 ARP 缓存溢出奠定了基础。

  1. R1 接收发往 10.1.0.0/16 网络的数据包。
  2. 在静态接口路由的基础上,R1 上的目的 ARP iface0
  3. R2 认识到它可以到达目的地,并使用自己的 MAC 响应 ARP。
  4. R1 缓存将远程网络中的 IP 与 R2 的 MAC 组合在一起的 ARP 结果。

对于 10.1.0.0/16 中的每个不同目的地,都会发生这种情况。因此,即使 /16 在 R2 之外进行了正确的子网划分,并且连接 R1 和 R2 的链路上只有两个节点,R1 仍会遭受 ARP 缓存过载,因为它导致 R2 表现得好像所有 65k 地址都直接连接一样。

我问这个问题的原因是因为我希望它可以帮助我理解导致我们最终导致 ARP 缓存溢出的网络服务故障报告(几天后)。本着 StackExchange 模型的精神,我试图将其提炼为一个我认为可以客观回答的清晰、具体的问题。

编辑 1为明确起见,我问的是数据链路(第 2 层)和网络(第 3 层)之间的粘合层的一部分,而不是数据链路层内的 MAC 转发表。主机或路由器构建前者以将 IP 地址映射到 MAC 地址,而交换机构建后者以将 MAC 地址映射到端口。

编辑 2虽然我很欣赏响应者为解释为什么某些实现不受 ARP 缓存溢出影响所做的努力,但我认为解决这些问题对这个问题很重要。问题是“什么时候会发生什么”,而不是“供应商X 是否容易受到影响”。我现在已经通过描述一个具体的例子完成了我的工作。

编辑 3另一个问题不是“如何防止 ARP 缓存溢出?”

4个回答

编辑2

正如你所说...

ip route 10.1.0.0 255.255.0.0 iface0

强制 Brocade 为 10.1.0.0/16 中的每个目的地代理 arp,就好像它直接连接到iface0.

我无法对 Brocade 的 ARP 缓存实现做出回应,但我只想指出解决您问题的简单方法……以不同的方式配置您的路由:

ip route 10.1.0.0 255.255.0.0 CiscoNextHopIP

通过这样做,您可以防止 Brocade 对所有 10.1.0.0/16 进行 ARP-ing(注意,您可能需要将 R1 和 R2 之间的链接重新编号以使其位于 10.1.0.0/16 之外,具体取决于 Brocade 的实现) .


原答案

我希望在大多数甚至所有实现中,ARP 表的容量都有硬性限制。

Cisco IOS CPU 路由器仅受路由器中 DRAM 数量的限制,但这通常不会成为限制因素。某些交换机(如 Catalyst 6500)对邻接表(与 ARP 表相关)有严格限制;Sup2T 有 100 万个邻接

那么,当 ARP 缓存已满并且数据包提供的目的地(或下一跳)未缓存时会发生什么?

Cisco IOS CPU 路由器不会耗尽 ARP 表中的空间,因为这些 ARP 存储在 DRAM 中。假设您在谈论 Sup2T。可以这样想,假设你有一个 Cat6500 + Sup2T 并且你配置了所有可能的 Vlan,技术上就是

4094 total Vlans - Vlan1002 - Vlan1003 - Vlan1004 - Vlan1005 = 4090 Vlans

假设您将每个 Vlan 设置为 /24(因此有 252 个可能的 ARP),并且您将每个 Vlan 装满……即 100 万个 ARP 条目。

4094 * 252 = 1,030,680 ARP Entries

这些 ARP 中的每一个都会消耗 ARP 表本身以及 IOS 邻接表中的一定数量的内存。我不知道它是什么,但假设总 ARP 开销是 10 字节...

这意味着您现在已经消耗了 10MB 的 ARP 开销;它仍然不是很大的空间......如果你的内存那么低,你会看到类似的东西%SYS-2-MALLOCFAIL

有了这么多 ARP 和 4 小时的 ARP 超时,您平均每秒必须处理近 70 个 ARP;100 万个 ARP 条目的维护更有可能耗尽路由器的 CPU(可能是 CPUHOG 消息)。

此时,您可以开始弹跳路由协议邻接,并且由于路由器 CPU 太忙而无法为 IP 进行 ARP,因此无法访问 IP。

我遇到这种情况的唯一实际经验是在 C3550 交换机上(2-8k MAC 限制,取决于 sdm 模板),它从表中删除了最旧的条目。

对于 IOS 和 JunOS 以及其他商业堆栈,您只需进行测试,幸运的是这并不难。

但是对于linux、freebsd、netbsd、openbsd、uIP、lwIP 和可能的许多其他实现,您可以检查它们的源代码以了解其行为。

在 Linux 中,您需要检查“net/core/neighbor.c”(从“if (entries >= tbl->gc_thresh3' ||”) 和“net/ipv4/arp.c”开始。
在 Linux 中,您似乎有三个完整的级别

  1. gc_thresh1 - 在命中之前什么都不做
  2. gc_thresh2 - 这可以暂时命中
  3. gc_thresh3 - 不能超过这个大小

当 gc_thresh3 试图超过时,它会尝试强制垃圾收集运行,除非它最近已经运行过。垃圾收集似乎删除不再被引用的条目,所以并不意味着最旧或最新,但是 gc_staletime 超出似乎是取消引用条目的一种方式,它再次转化为最旧的条目。
如果无法运行垃圾收集,则不会添加新条目。所有这些 gc_threshN 和定期垃圾收集间隔都可以调整。
该代码与地址族(ipv4、ipv6)无关,因此 IPv6 ND 和 IPv4 ARP 表由完全相同的代码路径处理,而不是重复路径。

它会将 IP 地址的 arp 存储在表中,并根据实现删除最旧的条目。对性能的影响取决于,如果这是一个不常见的事件,影响不大,但这是一个攻击向量,因此有人可以发送大量影响处理器利用率的 arp